From 3f7dc3fd80e7fe548f89b96ab4228135dca688db Mon Sep 17 00:00:00 2001 From: Vo Trung Chi Date: Thu, 1 Aug 2019 07:38:42 +0700 Subject: using POSIX shared memory APIs (#90) (#151) Replace all Linux specific shared memory APIs with POSIX alternatives. Signed-off-by: Vo Trung Chi --- src/shared/dlt_shm.c | 339 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 239 insertions(+), 100 deletions(-) (limited to 'src/shared/dlt_shm.c') diff --git a/src/shared/dlt_shm.c b/src/shared/dlt_shm.c index 8fb3a72..e1c96b7 100644 --- a/src/shared/dlt_shm.c +++ b/src/shared/dlt_shm.c @@ -53,16 +53,16 @@ *******************************************************************************/ #include -#include -#include -#include +#include #include +#include #include #include +#include #if !defined(_MSC_VER) -# include -# include +#include +#include #endif #include @@ -82,114 +82,206 @@ void dlt_shm_print_hex(char *ptr, int size) printf("\n"); } -void dlt_shm_pv(int id, int operation) +DltReturnValue dlt_shm_init_server(DltShm *buf, const char *name, int size) { - static struct sembuf semaphor; - - semaphor.sem_op = operation; - semaphor.sem_flg = SEM_UNDO; - - if (semop(id, &semaphor, 1) == -1) - dlt_log(LOG_WARNING, "SHM: semop() failed"); -} - -int dlt_shm_init_server(DltShm *buf, int key, int size) -{ - struct shmid_ds shm_buf; unsigned char *ptr; - /* Init parameters */ - buf->shmid = 0; - buf->semid = 0; + /* Check if buffer and name available */ + if (buf == NULL || name == NULL) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } - /* Create the segment. */ - if ((buf->shmid = shmget(key, size, IPC_CREAT | 0666)) < 0) { - dlt_log(LOG_WARNING, "SHM: shmget() failed"); + /* Init parameters */ + buf->shmfd = 0; + buf->sem = NULL; + + /** + * Create the shared memory segment. + * @name Name of the new shared memory object. + * (shm_open will create a file under /dev/shm/) + * @oflag O_CREAT | O_EXCL | O_RDWR + * O_CREAT | O_EXCL: The shm_open() fails if the shared memory exists. + * O_RDWR: Open the object for read-write access. + * @mode 0666 + * The shared memory object's permission. + */ + buf->shmfd = shm_open(name, O_CREAT | O_EXCL | O_RDWR, 0666); + if (buf->shmfd == -1) + { + dlt_vlog(LOG_ERR, "%s: shm_open() failed: %s\n", + __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } - /* get the size of shm */ - if (shmctl(buf->shmid, IPC_STAT, &shm_buf)) { - dlt_log(LOG_WARNING, "SHM: shmctl() failed"); + /* Set the size of shm */ + if (ftruncate(buf->shmfd, size) == -1) + { + dlt_vlog(LOG_ERR, "%s: ftruncate() failed: %s\n", + __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } /* Now we attach the segment to our data space. */ - if ((ptr = shmat(buf->shmid, NULL, 0)) == (unsigned char *)-1) { - dlt_log(LOG_WARNING, "SHM: shmat() failed"); + ptr = (unsigned char *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, + buf->shmfd, 0); + if (ptr == MAP_FAILED) + { + dlt_vlog(LOG_ERR, "%s: mmap() failed: %s\n", + __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } - /* Init semaphore */ - if ((buf->semid = semget(DLT_SHM_SEM, 1, S_IRWXU | S_IRWXG | S_IRWXO | IPC_CREAT | IPC_EXCL)) == -1) { - if ((buf->semid = semget(DLT_SHM_SEM, 1, S_IRWXU | S_IRWXG | S_IRWXO | IPC_EXCL)) == -1) { - dlt_log(LOG_WARNING, "SHM: semget() failed"); - return DLT_RETURN_ERROR; /* ERROR */ - } + /** + * Create the semaphore with input name + * @name name + * Name of the new semaphore + * (sem_open will create a file under /dev/shm/sem.) + * @oflag O_CREAT | O_EXCEL + * The sem_open() fails if the semaphore name exists. + * @mode 0777 + * The permissions to be placed on the new semaphore. + * @value 1 + * Initial value for the new semaphore. + */ + buf->sem = sem_open(name, O_CREAT | O_EXCL, 0666, 1); + if (buf->sem == SEM_FAILED) + { + dlt_vlog(LOG_ERR, "%s: sem_open() failed: %s\n", + __func__, strerror(errno)); + return DLT_RETURN_ERROR; /* ERROR */ } - if (semctl(buf->semid, 0, SETVAL, (int)1) == -1) { - dlt_log(LOG_WARNING, "SHM: semctl() failed"); + /* Init buffer */ + dlt_buffer_init_static_server(&(buf->buffer), ptr, size); + + /* The 'buf->shmfd' is no longer needed */ + if (close(buf->shmfd) == -1) + { + dlt_vlog(LOG_ERR, "%s: Failed to close shared memory" + " file descriptor: %s\n", __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } - /* init buffer */ - dlt_buffer_init_static_server(&(buf->buffer), ptr, shm_buf.shm_segsz); - return DLT_RETURN_OK; /* OK */ } -DltReturnValue dlt_shm_init_client(DltShm *buf, int key) +DltReturnValue dlt_shm_init_client(DltShm *buf, const char *name) { - struct shmid_ds shm_buf; + struct stat shm_buf; unsigned char *ptr; - /* init parameters */ - buf->shmid = 0; - buf->semid = 0; + /* Check if buffer and name available */ + if (buf == NULL || name == NULL) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } - /* Create the segment. */ - if ((buf->shmid = shmget(key, 0, 0666)) < 0) { - dlt_log(LOG_WARNING, "SHM: shmget() failed"); + /* Init parameters */ + buf->shmfd = 0; + buf->sem = NULL; + + /** + * Open the existing shared memory segment created by the server. + * @name Name of the existing shared memory object. + * (shm_open will open the file under /dev/shm/) + * @oflag O_RDWR + * Open the object for read-write access. + * @mode 0 + * We are not creating a new object, this argument should be specified as 0. + */ + buf->shmfd = shm_open(name, O_RDWR, 0); + if (buf->shmfd == -1) + { + dlt_vlog(LOG_ERR, "%s: shm_open() failed: %s\n", + __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } - /* get the size of shm */ - if (shmctl(buf->shmid, IPC_STAT, &shm_buf)) { - dlt_log(LOG_WARNING, "SHM: shmctl() failed"); - return DLT_RETURN_ERROR; /* ERROR */ + /* Get the size of shm */ + if (fstat(buf->shmfd, &shm_buf) == -1) + { + dlt_vlog(LOG_ERR, "%s: fstat() failed: %s\n", + __func__, strerror(errno)); + return DLT_RETURN_ERROR; /* ERROR */ } /* Now we attach the segment to our data space. */ - if ((ptr = shmat(buf->shmid, NULL, 0)) == (unsigned char *)-1) { - dlt_log(LOG_WARNING, "shmat() failed"); + ptr = (unsigned char *)mmap(NULL, shm_buf.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, buf->shmfd, 0); + if (ptr == MAP_FAILED) + { + dlt_vlog(LOG_ERR, "%s: mmap() failed: %s\n", + __func__, strerror(errno)); return DLT_RETURN_ERROR; /* ERROR */ } - /* Init semaphore */ - if ((buf->semid = semget(DLT_SHM_SEM, 0, 0)) == -1) { - dlt_log(LOG_WARNING, "SHM: semget() failed"); - return DLT_RETURN_ERROR; /* ERROR */ + /** + * Open the existing semaphore with name created by the server + * The call requires only two arguments. + * @name name + * Name of the existing semaphore + * (sem_open will open a file under /dev/shm/sem.) + * @oflag 0 + * We are accessing an existing semaphore, oflag should be specified as 0. + */ + buf->sem = sem_open(name, 0); + if (buf->sem == SEM_FAILED) + { + dlt_vlog(LOG_ERR, "%s: sem_open() failed: %s\n", + __func__, strerror(errno)); + return DLT_RETURN_ERROR; /* ERROR */ } - /* init buffer */ - dlt_buffer_init_static_client(&(buf->buffer), ptr, shm_buf.shm_segsz); + /* Init buffer */ + dlt_buffer_init_static_client(&(buf->buffer), ptr, shm_buf.st_size); + + /* The 'buf->shmfd' is no longer needed */ + if (close(buf->shmfd) == -1) + { + dlt_vlog(LOG_ERR, "%s: Failed to close shared memory" + " file descriptor: %s\n", __func__, strerror(errno)); + return DLT_RETURN_ERROR; /* ERROR */ + } return DLT_RETURN_OK; /* OK */ } void dlt_shm_info(DltShm *buf) { + /* Check if buffer available */ + if (buf == NULL) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); + return; + } + dlt_buffer_info(&(buf->buffer)); } void dlt_shm_status(DltShm *buf) { + /* Check if buffer available */ + if (buf == NULL) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); + return; + } + dlt_buffer_status(&(buf->buffer)); } int dlt_shm_get_total_size(DltShm *buf) { + /* Check if buffer available */ + if (buf == NULL) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); + return -1; + } + return dlt_buffer_get_total_size(&(buf->buffer)); } @@ -197,19 +289,28 @@ int dlt_shm_get_used_size(DltShm *buf) { int ret; - /* check if buffer available */ - if (!buf->buffer.mem) + /* Check if buffer available */ + if ((buf == NULL) || (buf->buffer.mem == NULL)) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; + } - DLT_SHM_SEM_GET(buf->semid); - ret = dlt_buffer_get_used_size(&(buf->buffer)); - DLT_SHM_SEM_FREE(buf->semid); + DLT_SHM_SEM_GET(buf->sem); + ret = dlt_buffer_get_used_size(&(buf->buffer)); + DLT_SHM_SEM_FREE(buf->sem); return ret; } int dlt_shm_get_message_count(DltShm *buf) { + /* Check if buffer available */ + if (buf == NULL) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); + return -1; + } return dlt_buffer_get_message_count(&(buf->buffer)); } @@ -223,13 +324,17 @@ int dlt_shm_push(DltShm *buf, { int ret; - /* check if buffer available */ - if (!buf->buffer.mem) + /* Check if buffer available */ + if ((buf == NULL) || (buf->buffer.mem == NULL)) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; + } - DLT_SHM_SEM_GET(buf->semid); - ret = dlt_buffer_push3(&(buf->buffer), data1, size1, data2, size2, data3, size3); - DLT_SHM_SEM_FREE(buf->semid); + DLT_SHM_SEM_GET(buf->sem); + ret = dlt_buffer_push3(&(buf->buffer), + data1, size1, data2, size2, data3, size3); + DLT_SHM_SEM_FREE(buf->sem); return ret; } @@ -238,13 +343,16 @@ int dlt_shm_pull(DltShm *buf, unsigned char *data, int max_size) { int ret; - /* check if buffer available */ - if (!buf->buffer.mem) + /* Check if buffer available */ + if ((buf == NULL) || (buf->buffer.mem == NULL)) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; + } - DLT_SHM_SEM_GET(buf->semid); + DLT_SHM_SEM_GET(buf->sem); ret = dlt_buffer_pull(&(buf->buffer), data, max_size); - DLT_SHM_SEM_FREE(buf->semid); + DLT_SHM_SEM_FREE(buf->sem); return ret; } @@ -253,13 +361,16 @@ int dlt_shm_copy(DltShm *buf, unsigned char *data, int max_size) { int ret; - /* check if buffer available */ - if (!buf->buffer.mem) + /* Check if buffer available */ + if ((buf == NULL) || (buf->buffer.mem == NULL)) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; + } - DLT_SHM_SEM_GET(buf->semid); + DLT_SHM_SEM_GET(buf->sem); ret = dlt_buffer_copy(&(buf->buffer), data, max_size); - DLT_SHM_SEM_FREE(buf->semid); + DLT_SHM_SEM_FREE(buf->sem); return ret; } @@ -268,54 +379,82 @@ int dlt_shm_remove(DltShm *buf) { int ret; - /* check if buffer available */ - if (!buf->buffer.mem) + /* Check if buffer available */ + if ((buf == NULL) || (buf->buffer.mem == NULL)) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); return -1; + } - DLT_SHM_SEM_GET(buf->semid); + DLT_SHM_SEM_GET(buf->sem); ret = dlt_buffer_remove(&(buf->buffer)); - DLT_SHM_SEM_FREE(buf->semid); + DLT_SHM_SEM_FREE(buf->sem); return ret; } -DltReturnValue dlt_shm_free_server(DltShm *buf) +DltReturnValue dlt_shm_free_server(DltShm *buf, const char *name) { + if ((buf == NULL) || (buf->buffer.shm == NULL) || name == NULL) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } - if (shmdt(buf->buffer.shm)) { - dlt_log(LOG_WARNING, "SHM: shmdt() failed"); - return DLT_RETURN_ERROR; /* ERROR */ + if (munmap(buf->buffer.shm, buf->buffer.min_size) == -1) + { + dlt_vlog(LOG_ERR, "%s: munmap() failed: %s\n", + __func__, strerror(errno)); } - if (shmctl(buf->shmid, IPC_RMID, NULL) == -1) { - dlt_log(LOG_WARNING, "SHM: shmdt() failed"); - return DLT_RETURN_ERROR; /* ERROR */ + if (shm_unlink(name) == -1) + { + dlt_vlog(LOG_ERR, "%s: shm_unlink() failed: %s\n", + __func__, strerror(errno)); } - if (semctl(buf->semid, 0, IPC_RMID, (int)0) == -1) { - dlt_log(LOG_WARNING, "SHM: shmdt() failed"); - return DLT_RETURN_ERROR; /* ERROR */ + if (sem_close(buf->sem) == -1) + { + dlt_vlog(LOG_ERR, "%s: sem_close() failed: %s\n", + __func__, strerror(errno)); + } + + if (sem_unlink(name) == -1) + { + dlt_vlog(LOG_ERR, "%s: sem_unlink() failed: %s\n", + __func__, strerror(errno)); } /* Reset parameters */ - buf->shmid = 0; - buf->semid = 0; + buf->shmfd = 0; + buf->sem = NULL; return dlt_buffer_free_static(&(buf->buffer)); - } DltReturnValue dlt_shm_free_client(DltShm *buf) { + if ((buf == NULL) || (buf->buffer.shm == NULL)) + { + dlt_vlog(LOG_ERR, "%s: Wrong parameter: Null pointer\n", __func__); + return DLT_RETURN_WRONG_PARAMETER; + } - if (shmdt(buf->buffer.shm)) { - dlt_log(LOG_WARNING, "SHM: shmdt() failed"); - return DLT_RETURN_ERROR; /* ERROR */ + if (munmap(buf->buffer.shm, buf->buffer.min_size) == -1) + { + dlt_vlog(LOG_ERR, "%s: munmap() failed: %s\n", + __func__, strerror(errno)); + } + + if (sem_close(buf->sem) == -1) + { + dlt_vlog(LOG_ERR, "%s: sem_close() failed: %s\n", + __func__, strerror(errno)); } /* Reset parameters */ - buf->shmid = 0; - buf->semid = 0; + buf->shmfd = 0; + buf->sem = NULL; return dlt_buffer_free_static(&(buf->buffer)); } -- cgit v1.2.1