X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=service%2Fnative%2Fframework_unified%2Fclient%2FNS_SharedMemIf%2Fsrc%2Fns_sharedmem.cpp;fp=service%2Fnative%2Fframework_unified%2Fclient%2FNS_SharedMemIf%2Fsrc%2Fns_sharedmem.cpp;h=fe1e9bc47f058befedf3333d38c918d7797af791;hb=17cf21bcf8a2e29d2cbcf0a313474d2a4ee44f5d;hp=0000000000000000000000000000000000000000;hpb=9e86046cdb356913ae026f616e5bf17f6f238aa5;p=staging%2Fbasesystem.git diff --git a/service/native/framework_unified/client/NS_SharedMemIf/src/ns_sharedmem.cpp b/service/native/framework_unified/client/NS_SharedMemIf/src/ns_sharedmem.cpp new file mode 100755 index 0000000..fe1e9bc --- /dev/null +++ b/service/native/framework_unified/client/NS_SharedMemIf/src/ns_sharedmem.cpp @@ -0,0 +1,697 @@ +/* + * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// \ingroup tag_NSSharedMemory +/// \brief This file contains implementation of class CNSSharedMem. +/// This class provides API to open, read, write and close shared memory +/// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Files +//////////////////////////////////////////////////////////////////////////////////////////////////// +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +static CNSSharedMem *g_pTransmitLogSharedBuf = NULL; + +#define SHM_HEADER_EXT "Hdr" + +#ifdef __cplusplus +extern "C" { +#endif + + +//////////////////////////////////////////////////////////////////////////////////////////// +/// NSSharedMemTransmitLogOpen +/// Open the shared memory for transmit logging +//////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus NSSharedMemTransmitLogOpen() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + if (NULL == g_pTransmitLogSharedBuf) { + // Create the instance + g_pTransmitLogSharedBuf = new(std::nothrow) CNSSharedMem(TRANSMIT_LOG_SHAREDMEM_NAME, TRANSMIT_LOG_SHAREDMEM_SIZE); + } + + if (NULL != g_pTransmitLogSharedBuf) { + if (!g_pTransmitLogSharedBuf->IsOpen()) { + // maps the shared memory buffer + l_eStatus = g_pTransmitLogSharedBuf->Open(); + } + } else { + l_eStatus = eFrameworkunifiedStatusNullPointer; + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////// +/// NSSharedMemTransmitLogClose +/// Close the transmit logging shared memory +//////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus NSSharedMemTransmitLogClose() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + if (NULL != g_pTransmitLogSharedBuf) { + // un-map the shared memory object + l_eStatus = g_pTransmitLogSharedBuf->Close(); + + delete g_pTransmitLogSharedBuf; + g_pTransmitLogSharedBuf = NULL; + } else { + l_eStatus = eFrameworkunifiedStatusNullPointer; + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////// +/// NSSharedMemReadTransmitLog +/// Reads transmit log from the shared memory buffer. +//////////////////////////////////////////////////////////////////////////////////////////// +SI_32 NSSharedMemReadTransmitLog(PSTR f_pBuffer, const UI_32 f_uiLength, const BOOL f_bBlock) { + // no. of bytes read + SI_32 l_iReadSize = NS_SHM_ERROR; + + if (NULL != g_pTransmitLogSharedBuf && NULL != f_pBuffer) { + // Writes log data into shared memory buffer + l_iReadSize = g_pTransmitLogSharedBuf->Read(f_pBuffer, f_uiLength, f_bBlock); + } + + return l_iReadSize; +} + +//////////////////////////////////////////////////////////////////////////////////////////// +/// NSSharedMemWriteTransmitLog +/// Write transmit log into the shared memory buffer. +//////////////////////////////////////////////////////////////////////////////////////////// +SI_32 NSSharedMemWriteTransmitLog(PCSTR f_pBuffer, const UI_32 f_uiLength) { + // no. of bytes read + SI_32 l_iWriteSize = NS_SHM_ERROR; + + if (NULL != g_pTransmitLogSharedBuf && NULL != f_pBuffer) { + // Writes log data into shared memory buffer + l_iWriteSize = g_pTransmitLogSharedBuf->Write(f_pBuffer, f_uiLength); + } + + return l_iWriteSize; +} + +//////////////////////////////////////////////////////////////////////////////////////////// +/// NSSharedMemDumpTransmitLogToFile +/// Dump transmit log from the shared memory buffer into file. +//////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus NSSharedMemDumpTransmitLogToFile(PCSTR f_pPath, PUI_32 f_puiDumpSize) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail; + + if (NULL != g_pTransmitLogSharedBuf && NULL != f_pPath) { + // Writes log data into shared memory buffer + l_eStatus = g_pTransmitLogSharedBuf->DumpToFile(f_pPath, f_puiDumpSize); + } + + return l_eStatus; +} + +// Used only in nstest_sharedmem. +#if defined(SHM_UNITTEST_ENABLE) +//////////////////////////////////////////////////////////////////////////////////////////// +/// NSSharedMemTransmitLogIsOpen +//////////////////////////////////////////////////////////////////////////////////////////// +BOOL NSSharedMemTransmitLogIsOpen() { + if (g_pTransmitLogSharedBuf != NULL) { + return g_pTransmitLogSharedBuf->IsOpen(); + } else { + return FALSE; + } +} +#endif + +#ifdef __cplusplus +} +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// CNSSharedMem +/// Parameterized Constructor of CNSSharedMem class +//////////////////////////////////////////////////////////////////////////////////////////////// +CNSSharedMem::CNSSharedMem(const std::string &f_cSharedMemName, const UI_32 f_uiSize): + m_cShmName(f_cSharedMemName), m_uiShmBuffSize(f_uiSize), m_pShmHdr(NULL), m_pShmBuff(NULL) { + m_cShmHdrName = f_cSharedMemName; + m_cShmHdrName.append(SHM_HEADER_EXT); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// CNSSharedMem +/// Constructor of CNSSharedMem class +//////////////////////////////////////////////////////////////////////////////////////////////// +CNSSharedMem::CNSSharedMem(): + m_cShmName(""), m_uiShmBuffSize(0), m_pShmHdr(NULL), m_pShmBuff(NULL) { + // do nothing +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// ~CNSSharedMem +/// Destructor of CNSSharedMem class +//////////////////////////////////////////////////////////////////////////////////////////////// +CNSSharedMem::~CNSSharedMem() { + if (NULL != m_pShmHdr) { + // un-map the shared memory object + Close(); + + m_pShmHdr = NULL; + } + + // TODO(framework_unified): currently shared memory is not being unlinked, + // we need to find a method where we can unlink the sharedmem + // shm_unlink(m_cShmName.c_str()); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// Open +/// This function opens and maps the shared memory object. +/// It creates the shared memory if it does not exists. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSSharedMem::Open() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusErrOther; + +// Used only in nstest_sharedmem. +#if defined(SHM_UNITTEST_ENABLE) + if (getenv(NSTEST_FAIL_SHAREDMEM_OPEN) != NULL) { + return l_eStatus; + } +#endif + + if (NULL == m_pShmHdr) { + // Open header shared memory + if (eFrameworkunifiedStatusOK != (l_eStatus = MapSM(reinterpret_cast(&m_pShmHdr), + m_cShmHdrName, sizeof(NSSharedBufferHdr)))) { + if (ENOENT == errno) { // Shared memory is not created yet + errno = EOK; + + // Create shared memory + if (eFrameworkunifiedStatusOK == CreateSMHeader()) { + // Retry to open + l_eStatus = MapSM(reinterpret_cast(&m_pShmHdr), m_cShmHdrName, sizeof(NSSharedBufferHdr)); + } + } + } else { + pthread_mutex_lock(&m_pShmHdr->m_tBufMutex); + + // if shared memory buffer is created with size 0, then set new size in header if any change + if (0 == m_pShmHdr->m_uiShMemSize && 0 < m_uiShmBuffSize) { + m_pShmHdr->m_uiShMemSize = m_uiShmBuffSize; + } else if (0 < m_pShmHdr->m_uiShMemSize && 0 == m_uiShmBuffSize) { + m_uiShmBuffSize = m_pShmHdr->m_uiShMemSize; + } else { + // do nothing + } + + pthread_mutex_unlock(&m_pShmHdr->m_tBufMutex); + } + } + + if (eFrameworkunifiedStatusOK == l_eStatus && 0 != m_uiShmBuffSize) { + if (NULL == m_pShmBuff) { + // Open shared memory data buffer, create if not exists + if (eFrameworkunifiedStatusOK != (l_eStatus = MapSM(reinterpret_cast(&m_pShmBuff), m_cShmName, m_uiShmBuffSize))) { + if (ENOENT == errno) { // Shared memory is not created yet + // Create shared memory + if (eFrameworkunifiedStatusOK == CreateSMDataBuffer()) { + // Retry to open + l_eStatus = MapSM(reinterpret_cast(&m_pShmBuff), m_cShmName, m_uiShmBuffSize); + } + } + } + } else { + l_eStatus = eFrameworkunifiedStatusErrOther; + } + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// IsOpen +/// This function is used to check whether the shared memory buffer is opened or not. +//////////////////////////////////////////////////////////////////////////////////////////////// +BOOL CNSSharedMem::IsOpen() { + return NULL == m_pShmHdr ? FALSE : TRUE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// Close +/// This function closes the shared memory object. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSSharedMem::Close() { + EFrameworkunifiedStatus l_eStatus1 = UnMapSM(m_pShmHdr, sizeof(NSSharedBufferHdr)); + m_pShmHdr = NULL; + + EFrameworkunifiedStatus l_eStatus2 = eFrameworkunifiedStatusOK; + if (0 != m_uiShmBuffSize) { + l_eStatus2 = UnMapSM(m_pShmBuff, m_uiShmBuffSize); + m_pShmBuff = NULL; + } + /* + * todo + * Even if an error occurs due to eFrameworkunifiedStatusNullPointer when UnMapSM fails, + * the error type cannot be determined by the caller because it is rounded to eFrameworkunifiedStatusFail + * if the API final determination is not OK. + */ + return (eFrameworkunifiedStatusOK != l_eStatus1 || eFrameworkunifiedStatusOK != l_eStatus2) ? eFrameworkunifiedStatusFail : eFrameworkunifiedStatusOK; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// Read +/// This function reads data from the shared memory. +//////////////////////////////////////////////////////////////////////////////////////////////// +SI_32 CNSSharedMem::Read(PSTR f_pBuffer, const UI_32 f_uilength, const BOOL f_bBlock) { + SI_32 l_iReadSize = NS_SHM_ERROR; + + if ((NULL != f_pBuffer) && (NULL != m_pShmHdr) && (0 != f_uilength)) { + UI_32 l_uiDataSizeToRead = 0; + + // Remaining buffer size from read pointer to end of the buffer + UI_32 l_uiRemainSize = 0; + + if (0 == pthread_mutex_lock(&m_pShmHdr->m_tBufMutex)) { + if ((TRUE == f_bBlock) && (0 == m_pShmHdr->m_uiUnReadSize)) { + pthread_cond_wait(&m_pShmHdr->m_tCondVar, &m_pShmHdr->m_tBufMutex); + } + + // if shared memory buffer size is changed by some other process, remap the updated buffer size in this process + // shared memory buffer size can only be changed if the initial size is 0. + if (m_uiShmBuffSize != m_pShmHdr->m_uiShMemSize) { + if (eFrameworkunifiedStatusOK == MapSM(reinterpret_cast(&m_pShmBuff), m_cShmName, m_pShmHdr->m_uiShMemSize)) { + m_uiShmBuffSize = m_pShmHdr->m_uiShMemSize; + } + } + + if (NULL != m_pShmBuff) { + l_uiRemainSize = m_uiShmBuffSize - m_pShmHdr->m_uiReadPtr; + + // Round read data size depending on un-read data size in the buffer + l_uiDataSizeToRead = m_pShmHdr->m_uiUnReadSize < f_uilength ? m_pShmHdr->m_uiUnReadSize : f_uilength; + + if (l_uiRemainSize < l_uiDataSizeToRead) { + // Wrapping read + memcpy(f_pBuffer, m_pShmBuff + m_pShmHdr->m_uiReadPtr, l_uiRemainSize); + memcpy(f_pBuffer + l_uiRemainSize, m_pShmBuff, l_uiDataSizeToRead - l_uiRemainSize); + m_pShmHdr->m_uiReadPtr = l_uiDataSizeToRead - l_uiRemainSize; + } else { + memcpy(f_pBuffer, m_pShmBuff + m_pShmHdr->m_uiReadPtr, l_uiDataSizeToRead); + + m_pShmHdr->m_uiReadPtr += l_uiDataSizeToRead; + + // Read pointer is the end of the buffer + if (m_pShmHdr->m_uiReadPtr == m_uiShmBuffSize) { + m_pShmHdr->m_uiReadPtr = 0; + } + } + + m_pShmHdr->m_uiUnReadSize -= l_uiDataSizeToRead; // Update un-read data size + + l_iReadSize = l_uiDataSizeToRead; + } + + pthread_mutex_unlock(&m_pShmHdr->m_tBufMutex); + } + } + + return l_iReadSize; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// Write +/// This function writes the data into the shared memory. +//////////////////////////////////////////////////////////////////////////////////////////////// +SI_32 CNSSharedMem::Write(PCSTR f_pBuffer, const UI_32 f_uilength) { + SI_32 l_iWriteSize = NS_SHM_ERROR; + + // size available in buffer + UI_32 l_uiRemainSize = 0; + + if (NULL != m_pShmHdr && NULL != m_pShmBuff && NULL != f_pBuffer && f_uilength <= m_uiShmBuffSize) { + if (0 == pthread_mutex_lock(&m_pShmHdr->m_tBufMutex)) { + l_uiRemainSize = m_uiShmBuffSize - m_pShmHdr->m_uiWritePtr; + + // Write data to the buffer + if (l_uiRemainSize < f_uilength) { + // Wrapping write + memcpy(m_pShmBuff + m_pShmHdr->m_uiWritePtr, f_pBuffer, l_uiRemainSize); + memcpy(m_pShmBuff, f_pBuffer + l_uiRemainSize, f_uilength - l_uiRemainSize); + + // Update the write pointer + m_pShmHdr->m_uiWritePtr = f_uilength - l_uiRemainSize; + + // The buffer is full of valid data + m_pShmHdr->m_bIsFull = TRUE; + } else { + memcpy(m_pShmBuff + m_pShmHdr->m_uiWritePtr, f_pBuffer, f_uilength); + + // Update the write pointer + m_pShmHdr->m_uiWritePtr += f_uilength; + + // Write pointer is the end of the buffer + if (m_pShmHdr->m_uiWritePtr == m_uiShmBuffSize) { + m_pShmHdr->m_uiWritePtr = 0; + + // The buffer is full of valid data + m_pShmHdr->m_bIsFull = TRUE; + } + } + + // Update un-read data size + m_pShmHdr->m_uiUnReadSize += f_uilength; + + // Set read pointer to be same as write pointer if write pointer exceeds the read pointer + if (m_uiShmBuffSize < m_pShmHdr->m_uiUnReadSize) { + m_pShmHdr->m_uiReadPtr = m_pShmHdr->m_uiWritePtr; + m_pShmHdr->m_uiUnReadSize = m_uiShmBuffSize; + } + + pthread_cond_signal(&m_pShmHdr->m_tCondVar); + + pthread_mutex_unlock(&m_pShmHdr->m_tBufMutex); + + l_iWriteSize = f_uilength; + } + } + + return l_iWriteSize; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// DumpToFile +/// This function writes all the data in the buffer into provided file f_pPath. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSSharedMem::DumpToFile(PCSTR f_pPath, PUI_32 f_uiDumpSize) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + ssize_t l_iSize = 0; + + SI_32 fd = -1; + + if (NULL == f_uiDumpSize) { + return eFrameworkunifiedStatusNullPointer; + } + *f_uiDumpSize = 0; + + if (NULL != f_pPath) { + if (NULL != m_pShmHdr) { + // Open file + if (-1 != (fd = open(f_pPath, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRWXU | S_IRWXG | S_IRWXO))) { + if (NULL != m_pShmBuff && 0 != m_uiShmBuffSize) { + if (0 == pthread_mutex_lock(&m_pShmHdr->m_tBufMutex)) { + // Write buffer data to file + if (m_pShmHdr->m_bIsFull) { + // Buffer has full of data (read data from write pointer) + if (-1 != (l_iSize = write(fd, m_pShmBuff + m_pShmHdr->m_uiWritePtr, + m_uiShmBuffSize - m_pShmHdr->m_uiWritePtr))) { + *f_uiDumpSize += static_cast(l_iSize); + } else { + l_eStatus = eFrameworkunifiedStatusErrOther; + } + } + + if (-1 != (l_iSize = write(fd, m_pShmBuff, m_pShmHdr->m_uiWritePtr))) { + *f_uiDumpSize += static_cast(l_iSize); + } + + if (0 != pthread_mutex_unlock(&m_pShmHdr->m_tBufMutex)) { + l_eStatus = eFrameworkunifiedStatusSemUnlockFail; + } + } else { + l_eStatus = eFrameworkunifiedStatusSemLockFail; + } + } else if (NULL == m_pShmBuff && 0 != m_uiShmBuffSize) { + l_eStatus = eFrameworkunifiedStatusFail; + } else { + // do nothing + } + + // Sync the file to force I/O operation completed + fsync(fd); + + close(fd); + } else { + l_eStatus = eFrameworkunifiedStatusFileLoadError; + } + } else { + l_eStatus = eFrameworkunifiedStatusFail; + } + } else { + l_eStatus = eFrameworkunifiedStatusInvldParam; + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// GetSize +/// This function returns the number of unread bytes which can be read by Read(). +//////////////////////////////////////////////////////////////////////////////////////////////// +SI_32 CNSSharedMem::GetSize() { + SI_32 l_uiReadSize = NS_SHM_ERROR; + + if (NULL != m_pShmHdr) { + l_uiReadSize = m_pShmHdr->m_uiUnReadSize; + } + + return l_uiReadSize; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// ClearBuf +/// This function clears the buffer. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSSharedMem::ClearBuf() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + if (NULL != m_pShmHdr) { + if (0 == pthread_mutex_lock(&m_pShmHdr->m_tBufMutex)) { + // Initialize the r/w pointers + m_pShmHdr->m_uiReadPtr = 0; + m_pShmHdr->m_uiWritePtr = 0; + m_pShmHdr->m_uiUnReadSize = 0; + m_pShmHdr->m_bIsFull = FALSE; + + if (0 != pthread_mutex_unlock(&m_pShmHdr->m_tBufMutex)) { + l_eStatus = eFrameworkunifiedStatusSemUnlockFail; + } + } else { + l_eStatus = eFrameworkunifiedStatusSemLockFail; + } + } else { + l_eStatus = eFrameworkunifiedStatusFail; + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// SetReadPtrToWritePtr +/// This function sets the position of read ptr to write ptr in buffer. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSSharedMem::SetReadPtrToWritePtr() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + if (NULL != m_pShmHdr) { + if (0 == pthread_mutex_lock(&m_pShmHdr->m_tBufMutex)) { // LCOV_EXCL_BR_LINE 5: pthread_mutex_lock's error case + // Initialize the r/w pointers + m_pShmHdr->m_uiReadPtr = m_pShmHdr->m_uiWritePtr; + m_pShmHdr->m_uiUnReadSize = 0; + + if (0 != pthread_mutex_unlock(&m_pShmHdr->m_tBufMutex)) { // LCOV_EXCL_BR_LINE 5: pthread_mutex_unlock's error + l_eStatus = eFrameworkunifiedStatusSemUnlockFail; + } + } else { + l_eStatus = eFrameworkunifiedStatusSemLockFail; + } + } else { + l_eStatus = eFrameworkunifiedStatusFail; + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// CreateSMHeader +/// This function creates the shared memory object for header. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSSharedMem::CreateSMHeader() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail; + + // file descriptor of shared memory + SI_32 l_siId = -1; + + // shared memory buffer headers + NSSharedBufferHdr *l_pShmHdr = NULL; + + if ((!m_cShmHdrName.empty()) && (m_cShmHdrName.size() <= NAME_MAX)) { + // Try to create shared memory + l_siId = shm_open(m_cShmHdrName.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO); + + if (-1 != l_siId) { + // Set the size of shared memory + if (-1 != ftruncate(l_siId, sizeof(NSSharedBufferHdr))) { + // Map the shared memory + l_pShmHdr = reinterpret_cast(mmap(NULL, sizeof(NSSharedBufferHdr), + (PROT_READ | PROT_WRITE), MAP_SHARED, l_siId, 0)); + + if (MAP_FAILED != l_pShmHdr) { + // mutex attribute + pthread_mutexattr_t l_tMtxAttr = {}; + pthread_condattr_t l_tCondAttr = {}; + + // Initialize mutex + pthread_mutexattr_init(&l_tMtxAttr); + pthread_mutexattr_setpshared(&l_tMtxAttr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&l_pShmHdr->m_tBufMutex, &l_tMtxAttr); + pthread_mutexattr_destroy(&l_tMtxAttr); + + pthread_condattr_init(&l_tCondAttr); + pthread_condattr_setpshared(&l_tCondAttr, PTHREAD_PROCESS_SHARED); + pthread_cond_init(&l_pShmHdr->m_tCondVar, &l_tCondAttr); + pthread_condattr_destroy(&l_tCondAttr); + + pthread_mutex_lock(&l_pShmHdr->m_tBufMutex); + + // Initialize the r/w pointers + l_pShmHdr->m_uiReadPtr = 0; + l_pShmHdr->m_uiWritePtr = 0; + l_pShmHdr->m_uiUnReadSize = 0; + l_pShmHdr->m_bIsFull = FALSE; + l_pShmHdr->m_uiShMemSize = m_uiShmBuffSize; + + pthread_mutex_unlock(&l_pShmHdr->m_tBufMutex); + + // Once initialized un-map the shared memory + munmap(l_pShmHdr, sizeof(NSSharedBufferHdr)); + + l_eStatus = eFrameworkunifiedStatusOK; + } + } + + close(l_siId); + } else if (EEXIST == errno) { + // Shared memory is already created + l_eStatus = eFrameworkunifiedStatusDuplicate; + } else { + // do nothing + } + } else { + l_eStatus = eFrameworkunifiedStatusInvldParam; + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// CreateSMDataBuffer +/// This function creates the shared memory object for data buffer. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSSharedMem::CreateSMDataBuffer() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail; + + // file descriptor of shared memory + SI_32 l_siId = -1; + + if ((!m_cShmName.empty()) && (m_cShmName.size() <= NAME_MAX)) { + // Try to create shared memory + l_siId = shm_open(m_cShmName.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO); + + if (-1 != l_siId) { + // Set the size of shared memory + if (-1 != ftruncate(l_siId, m_uiShmBuffSize)) { + l_eStatus = eFrameworkunifiedStatusOK; + } + + close(l_siId); + } else if (EEXIST == errno) { + // Shared memory is already created + l_eStatus = eFrameworkunifiedStatusDuplicate; + } else { + // do nothing + } + } else { + l_eStatus = eFrameworkunifiedStatusInvldParam; + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// MapSMHeader +/// This function open and maps the shared memory header in process space. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSSharedMem::MapSM(PVOID *f_pShMem, const std::string &f_cShmName, const UI_32 f_uiShmSize) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail; + + // file descriptor of shared memory + SI_32 l_siId = -1; + + // shared memory buffer headers + PVOID l_pShmBuf = NULL; + + // Open shared memory + l_siId = shm_open(f_cShmName.c_str(), O_RDWR, 0); + + if (-1 != l_siId) { + // Map the shared memory into its memory space + l_pShmBuf = mmap(NULL, f_uiShmSize, (PROT_READ | PROT_WRITE), MAP_SHARED, l_siId, 0); + + if (MAP_FAILED != l_pShmBuf) { + *f_pShMem = l_pShmBuf; + l_eStatus = eFrameworkunifiedStatusOK; + } + + close(l_siId); + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// UnMapSM +/// This function unmaps the shared memory object. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSSharedMem::UnMapSM(PVOID f_pShMem, const UI_32 f_uiShmSize) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + // Un-map the shared memory + if (NULL != f_pShMem) { + if (0 != munmap(f_pShMem, f_uiShmSize)) { + l_eStatus = eFrameworkunifiedStatusFail; + } + } else { + l_eStatus = eFrameworkunifiedStatusNullPointer; + } + + return l_eStatus; +}