/* * SPDX license identifier: MPL-2.0 * * Copyright (C) 2011-2015, BMW AG * * This file is part of GENIVI Project DLT - Diagnostic Log and Trace. * * This Source Code Form is subject to the terms of the * Mozilla Public License (MPL), v. 2.0. * If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. * * For further information see http://www.genivi.org/. */ /*! * \author Alexander Wenzel * * \copyright Copyright © 2011-2015 BMW AG. \n * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/. * * \file dlt_shm.c */ /******************************************************************************* ** ** ** SRC-MODULE: dlt_shm.c ** ** ** ** TARGET : linux ** ** ** ** PROJECT : DLT ** ** ** ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de ** ** ** ** PURPOSE : ** ** ** ** REMARKS : ** ** ** ** PLATFORM DEPENDANT [yes/no]: yes ** ** ** ** TO BE CHANGED BY USER [yes/no]: no ** ** ** *******************************************************************************/ /******************************************************************************* ** Author Identity ** ******************************************************************************** ** ** ** Initials Name Company ** ** -------- ------------------------- ---------------------------------- ** ** aw Alexander Wenzel BMW ** *******************************************************************************/ #include #include #include #include #include #include #include #if !defined(_MSC_VER) #include #include #endif #include #include void dlt_shm_print_hex(char *ptr, int size) { int num; for (num = 0; num < size; num++) { if ((num % 16) == 15) printf("%.2x\n", ((unsigned char *)ptr)[num]); else printf("%.2x ", ((unsigned char *)ptr)[num]); } printf("\n"); } DltReturnValue dlt_shm_init_server(DltShm *buf, const char *name, int size) { unsigned char *ptr; /* 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; } /* 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 */ } /* 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. */ 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 */ } /** * 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 */ } /* 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 */ } return DLT_RETURN_OK; /* OK */ } DltReturnValue dlt_shm_init_client(DltShm *buf, const char *name) { struct stat shm_buf; unsigned char *ptr; /* 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; } /* 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 (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. */ 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 */ } /** * 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.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)); } int dlt_shm_get_used_size(DltShm *buf) { int ret; /* 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->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)); } int dlt_shm_push(DltShm *buf, const unsigned char *data1, unsigned int size1, const unsigned char *data2, unsigned int size2, const unsigned char *data3, unsigned int size3) { int ret; /* 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->sem); ret = dlt_buffer_push3(&(buf->buffer), data1, size1, data2, size2, data3, size3); DLT_SHM_SEM_FREE(buf->sem); return ret; } int dlt_shm_pull(DltShm *buf, unsigned char *data, int max_size) { int ret; /* 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->sem); ret = dlt_buffer_pull(&(buf->buffer), data, max_size); DLT_SHM_SEM_FREE(buf->sem); return ret; } int dlt_shm_copy(DltShm *buf, unsigned char *data, int max_size) { int ret; /* 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->sem); ret = dlt_buffer_copy(&(buf->buffer), data, max_size); DLT_SHM_SEM_FREE(buf->sem); return ret; } int dlt_shm_remove(DltShm *buf) { int ret; /* 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->sem); ret = dlt_buffer_remove(&(buf->buffer)); DLT_SHM_SEM_FREE(buf->sem); return ret; } 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 (munmap(buf->buffer.shm, buf->buffer.min_size) == -1) { dlt_vlog(LOG_ERR, "%s: munmap() failed: %s\n", __func__, strerror(errno)); } if (shm_unlink(name) == -1) { dlt_vlog(LOG_ERR, "%s: shm_unlink() 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)); } if (sem_unlink(name) == -1) { dlt_vlog(LOG_ERR, "%s: sem_unlink() failed: %s\n", __func__, strerror(errno)); } /* Reset parameters */ 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 (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->shmfd = 0; buf->sem = NULL; return dlt_buffer_free_static(&(buf->buffer)); }