diff options
author | 2020-11-20 23:36:23 +0900 | |
---|---|---|
committer | 2020-11-22 09:02:55 +0900 | |
commit | 17cf21bcf8a2e29d2cbcf0a313474d2a4ee44f5d (patch) | |
tree | 582a9768558d9eaf261ca5df6136e9de54c95816 /service/native/framework_unified/client/NS_RingBuffer/src | |
parent | 9e86046cdb356913ae026f616e5bf17f6f238aa5 (diff) |
Re-organized sub-directory by category
Since all the sub-directories were placed in the
first level, created sub-directories, "hal", "module",
and "service" for classification and relocated each component.
Signed-off-by: Tadao Tanikawa <tanikawa.tadao@jp.panasonic.com>
Change-Id: Ifdf743ac0d1893bd8e445455cf0d2c199a011d5c
Diffstat (limited to 'service/native/framework_unified/client/NS_RingBuffer/src')
-rwxr-xr-x | service/native/framework_unified/client/NS_RingBuffer/src/ns_ringbuffer.cpp | 1029 |
1 files changed, 1029 insertions, 0 deletions
diff --git a/service/native/framework_unified/client/NS_RingBuffer/src/ns_ringbuffer.cpp b/service/native/framework_unified/client/NS_RingBuffer/src/ns_ringbuffer.cpp new file mode 100755 index 0000000..1fbc5b5 --- /dev/null +++ b/service/native/framework_unified/client/NS_RingBuffer/src/ns_ringbuffer.cpp @@ -0,0 +1,1029 @@ +/* + * @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_NSRingBuffer +/// \brief This file contains implementation of class CNSRingBuffer. +/// This class provides API to open, read, write and close ring buffer +/// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Include Files +//////////////////////////////////////////////////////////////////////////////////////////////////// +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <limits.h> + +#include <native_service/ns_ringbuffer.h> +#include <native_service/cl_lock.h> + +#include <string> + +#define RBUF_HEADER_EXT "Hdr" +#define RBUF_RETRY_SLEEP (1000) +#define RBUF_RETRY_COUNT (8) +#define RBUF_PAGE_SIZE (4096) +#define RBUF_PAGE_ALIGN(p) ((p / RBUF_PAGE_SIZE) * RBUF_PAGE_SIZE) + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// CNSRingBuffer +/// Parameterized Constructor of CNSRingBuffer class +//////////////////////////////////////////////////////////////////////////////////////////////// +CNSRingBuffer::CNSRingBuffer(const std::string &f_cMappedFilePath, const UI_32 f_uiSize, int f_lid): + m_cMappedFilePath(f_cMappedFilePath), m_uiRingBuffSize(f_uiSize), m_pRbufMtx(NULL), m_pRbufHdr(NULL), m_pRbuf(NULL), + m_lid(f_lid), m_pLockAddr(NULL), m_siProcessLastWrtPage(-1) { // LCOV_EXCL_BR_LINE 11: except branch + m_cMappedFileHdrPath = f_cMappedFilePath; + m_cMappedFileHdrPath.append(RBUF_HEADER_EXT); // LCOV_EXCL_BR_LINE 11: except branch + + m_cRbufMtxName = f_cMappedFilePath; + std::size_t found = m_cRbufMtxName.find_first_of('/'); + while (found != std::string::npos) { + m_cRbufMtxName[found] = '_'; + found = m_cRbufMtxName.find_first_of('/', found + 1); + } + m_cRbufMtxName[0] = '/'; + pthread_mutex_init(&m_tOpenMutex, NULL); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// CNSRingBuffer +/// Constructor of CNSRingBuffer class +//////////////////////////////////////////////////////////////////////////////////////////////// +CNSRingBuffer::CNSRingBuffer(): + m_cMappedFilePath(""), m_uiRingBuffSize(0), m_pRbufMtx(NULL), m_pRbufHdr(NULL), m_pRbuf(NULL), m_lid(-1), + m_pLockAddr(NULL), m_siProcessLastWrtPage(-1) { + pthread_mutex_init(&m_tOpenMutex, NULL); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// ~CNSRingBuffer +/// Destructor of CNSRingBuffer class +//////////////////////////////////////////////////////////////////////////////////////////////// +CNSRingBuffer::~CNSRingBuffer() { + if (NULL != m_pRbufHdr) { + // un-map the ring buffer object + Close(); + + m_pRbufHdr = NULL; + m_pRbufMtx = NULL; + } + pthread_mutex_destroy(&m_tOpenMutex); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// Open +/// This function opens and maps the ring buffer object. +/// It creates the ring buffer if it does not exists. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::Open() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusErrOther; + + pthread_mutex_lock(&m_tOpenMutex); + + if (NULL == m_pRbufMtx) { + // Open ring buffer mutex + if (eFrameworkunifiedStatusOK != (l_eStatus = MapSM(reinterpret_cast<PVOID *>(&m_pRbufMtx), + m_cRbufMtxName, sizeof(NSRingBufferMtx)))) { + if (ENOENT == errno) { + errno = EOK; + + +// if (eFrameworkunifiedStatusOK == CreateRBMutex()) { + EFrameworkunifiedStatus l_eStatus1 = CreateRBMutex(); + if ((l_eStatus1 == eFrameworkunifiedStatusOK) || (l_eStatus1 == eFrameworkunifiedStatusDuplicate)) { + + l_eStatus = MapSM(reinterpret_cast<PVOID *>(&m_pRbufMtx), m_cRbufMtxName, sizeof(NSRingBufferMtx)); + } + } + } else { + if (m_pRbufMtx->m_lid != m_lid) { + // Different Lock ID in constructor parameter and mutex object + l_eStatus = eFrameworkunifiedStatusInvldParam; + } + } + } + + if (eFrameworkunifiedStatusOK == l_eStatus) { + if (m_lid >= 0 && NULL == m_pLockAddr) { + CL_LockProcessInit(); + if ((m_pLockAddr = CL_LockMap(m_lid)) == MAP_FAILED) { + l_eStatus = eFrameworkunifiedStatusFail; + } + } + } + + if (eFrameworkunifiedStatusOK == l_eStatus) { + if (NULL == m_pRbufHdr) { + // Open header ring buffer + if (eFrameworkunifiedStatusOK != (l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbufHdr), + m_cMappedFileHdrPath, sizeof(NSRingBufferHdr)))) { + if (ENOENT == errno) { // ring buffer is not created yet + errno = EOK; + + // Create ring buffer + +// if (eFrameworkunifiedStatusOK == CreateRBHeader()) { + EFrameworkunifiedStatus l_eStatus1 = CreateRBHeader(); + if ((l_eStatus1 == eFrameworkunifiedStatusOK) || (l_eStatus1 == eFrameworkunifiedStatusDuplicate)) { + + // Retry to open + l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbufHdr), + m_cMappedFileHdrPath, sizeof(NSRingBufferHdr)); + +// } + } else { + l_eStatus = l_eStatus1; + } + + } + } else { + +#if 0 + LockMtx(); + + struct stat st; + int ret = stat(m_cMappedFilePath.c_str(), &st); + + if (m_uiRingBuffSize == 0) { + if (ret == 0) { // LCOV_EXCL_BR_LINE 5:stat's error case. + // LCOV_EXCL_START 5: stat's error case. + AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert + if ((UI_32)st.st_size != m_pRbufHdr->m_uiRingBufferSize || (UI_32)st.st_size < m_pRbufHdr->m_uiReadPtr + || (UI_32)st.st_size < m_pRbufHdr->m_uiWritePtr) { + memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr)); + m_pRbufHdr->m_uiRingBufferSize = static_cast<UI_32>(st.st_size); + unlink(m_cMappedFilePath.c_str()); + } + m_uiRingBuffSize = static_cast<UI_32>(st.st_size); + // LCOV_EXCL_STOP + } + } else { + if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize || m_uiRingBuffSize < m_pRbufHdr->m_uiReadPtr + || m_uiRingBuffSize < m_pRbufHdr->m_uiWritePtr || (ret == 0 && m_uiRingBuffSize != (UI_32)st.st_size)) { + memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr)); + m_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize; + unlink(m_cMappedFilePath.c_str()); + } + } + + UnlockMtx(); +#endif + int ret; + if ( (ret = LockMtx()) == 0) { + struct stat st; + int ret = stat(m_cMappedFilePath.c_str(), &st); + + if (m_uiRingBuffSize == 0) { + if (ret == 0) { + if ((UI_32)st.st_size != m_pRbufHdr->m_uiRingBufferSize || (UI_32)st.st_size < m_pRbufHdr->m_uiReadPtr || + (UI_32)st.st_size < m_pRbufHdr->m_uiWritePtr) { + memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr)); + m_pRbufHdr->m_uiRingBufferSize = static_cast<UI_32>(st.st_size); + unlink(m_cMappedFilePath.c_str()); + } + m_uiRingBuffSize = static_cast<UI_32>(st.st_size); + } + } else { + if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize || m_uiRingBuffSize < m_pRbufHdr->m_uiReadPtr || + m_uiRingBuffSize < m_pRbufHdr->m_uiWritePtr || (ret == 0 && m_uiRingBuffSize != (UI_32)st.st_size)) { + memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr)); + m_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize; + unlink(m_cMappedFilePath.c_str()); + } + } + + UnlockMtx(); + } else { + fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret)); + munmap(m_pRbufHdr, sizeof(NSRingBufferHdr)); + m_pRbufHdr = NULL; + l_eStatus = eFrameworkunifiedStatusFail; + } + + } + } + } + + if (eFrameworkunifiedStatusOK == l_eStatus && 0 != m_uiRingBuffSize) { + if (NULL == m_pRbuf) { + // Open ring buffer data buffer, create if not exists + if (eFrameworkunifiedStatusOK != (l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbuf), + m_cMappedFilePath, m_uiRingBuffSize))) { + if (ENOENT == errno) { // ring buffer is not created yet + // Create ring buffer + +// if (eFrameworkunifiedStatusOK == CreateRBDataBuffer()) { + EFrameworkunifiedStatus l_eStatus1 = CreateRBDataBuffer(); + if ((l_eStatus1 == eFrameworkunifiedStatusOK) || (l_eStatus1 == eFrameworkunifiedStatusDuplicate)) { + + // Retry to open + l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbuf), + m_cMappedFilePath, m_uiRingBuffSize); + } + } + } + } + } + + pthread_mutex_unlock(&m_tOpenMutex); + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// IsOpen +/// This function is used to check whether the ring buffer is opened or not. +//////////////////////////////////////////////////////////////////////////////////////////////// +BOOL CNSRingBuffer::IsOpen() { + return NULL == m_pRbufHdr ? FALSE : TRUE; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// Close +/// This function closes the ring buffer object. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::Close() { + if (NULL != m_pLockAddr) { + CL_LockUnmap(m_pLockAddr); + } + + EFrameworkunifiedStatus l_eStatus1 = UnMap(m_pRbufHdr, sizeof(NSRingBufferHdr)); + m_pRbufHdr = NULL; + + EFrameworkunifiedStatus l_eStatus2 = eFrameworkunifiedStatusOK; + if (0 != m_uiRingBuffSize) { + l_eStatus2 = UnMap(m_pRbuf, m_uiRingBuffSize); + m_pRbuf = NULL; + } + + EFrameworkunifiedStatus l_eStatus3 = UnMap(m_pRbufMtx, sizeof(NSRingBufferMtx)); + m_pRbufMtx = NULL; + + return (eFrameworkunifiedStatusOK != l_eStatus1 || eFrameworkunifiedStatusOK != l_eStatus2 || + eFrameworkunifiedStatusOK != l_eStatus3) ? eFrameworkunifiedStatusFail : eFrameworkunifiedStatusOK; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// Read +/// This function reads data from the ring buffer. +//////////////////////////////////////////////////////////////////////////////////////////////// +SI_32 CNSRingBuffer::Read(PSTR f_pBuffer, const UI_32 f_uilength) { + SI_32 l_iReadSize = -1; + + if ((NULL != f_pBuffer) && (NULL != m_pRbufHdr) && (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 + LockMtx(); + + // if ring buffer size is changed by some other process, remap the updated buffer size in this process + // ring buffer size can only be changed if the initial size is 0. + if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize) { + if (eFrameworkunifiedStatusOK == Map(reinterpret_cast<PVOID *>(&m_pRbuf), + m_cMappedFilePath, m_pRbufHdr->m_uiRingBufferSize)) { + m_uiRingBuffSize = m_pRbufHdr->m_uiRingBufferSize; + } + } + + if (NULL != m_pRbuf) { + l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiReadPtr; + + // Round read data size depending on un-read data size in the buffer + l_uiDataSizeToRead = m_pRbufHdr->m_uiUnReadSize < f_uilength ? m_pRbufHdr->m_uiUnReadSize : f_uilength; + + if (l_uiRemainSize < l_uiDataSizeToRead) { + // Wrapping read + memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiRemainSize); + memcpy(f_pBuffer + l_uiRemainSize, m_pRbuf, l_uiDataSizeToRead - l_uiRemainSize); + m_pRbufHdr->m_uiReadPtr = l_uiDataSizeToRead - l_uiRemainSize; + } else { + memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiDataSizeToRead); + + m_pRbufHdr->m_uiReadPtr += l_uiDataSizeToRead; + + // Read pointer is the end of the buffer + if (m_pRbufHdr->m_uiReadPtr == m_uiRingBuffSize) { + m_pRbufHdr->m_uiReadPtr = 0; + } + } + + m_pRbufHdr->m_uiUnReadSize -= l_uiDataSizeToRead; // Update un-read data size + + l_iReadSize = l_uiDataSizeToRead; + } + + UnlockMtx(); +#endif + int ret; + if ( (ret = LockMtx()) == 0) { + // if ring buffer size is changed by some other process, remap the updated buffer size in this process + // ring buffer size can only be changed if the initial size is 0. + if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize) { + if (eFrameworkunifiedStatusOK == Map(reinterpret_cast<PVOID *>(&m_pRbuf), + m_cMappedFilePath, m_pRbufHdr->m_uiRingBufferSize)) { + m_uiRingBuffSize = m_pRbufHdr->m_uiRingBufferSize; + } + } + + if (NULL != m_pRbuf) { + l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiReadPtr; + + // Round read data size depending on un-read data size in the buffer + l_uiDataSizeToRead = m_pRbufHdr->m_uiUnReadSize < f_uilength ? m_pRbufHdr->m_uiUnReadSize : f_uilength; + + if (l_uiRemainSize < l_uiDataSizeToRead) { + // Wrapping read + memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiRemainSize); + memcpy(f_pBuffer + l_uiRemainSize, m_pRbuf, l_uiDataSizeToRead - l_uiRemainSize); + m_pRbufHdr->m_uiReadPtr = l_uiDataSizeToRead - l_uiRemainSize; + } else { + memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiDataSizeToRead); + + m_pRbufHdr->m_uiReadPtr += l_uiDataSizeToRead; + + // Read pointer is the end of the buffer + if (m_pRbufHdr->m_uiReadPtr == m_uiRingBuffSize) { + m_pRbufHdr->m_uiReadPtr = 0; + } + } + + m_pRbufHdr->m_uiUnReadSize -= l_uiDataSizeToRead; // Update un-read data size + + l_iReadSize = l_uiDataSizeToRead; + } + + UnlockMtx(); + } else { + fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret)); + l_iReadSize = 0; + } + + } + + return l_iReadSize; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// Write +/// This function writes the data into the ring buffer. +//////////////////////////////////////////////////////////////////////////////////////////////// +SI_32 CNSRingBuffer::Write(PCSTR f_pBuffer, const UI_32 f_uilength) { + SI_32 l_iWriteSize = -1; + + // size available in buffer + UI_32 l_uiRemainSize = 0; + + if (NULL != m_pRbufHdr && NULL != m_pRbuf && NULL != f_pBuffer && f_uilength <= m_uiRingBuffSize) { // LCOV_EXCL_BR_LINE 11:except branch +#if 0 + LockMtx(); + + UI_32 l_uiLastPage = RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr); + l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr; + + if (m_siProcessLastWrtPage >= 0) { + if ((UI_32)m_siProcessLastWrtPage != l_uiLastPage) { + if (madvise(m_pRbuf + m_siProcessLastWrtPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) { + fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n", + m_pRbuf + m_siProcessLastWrtPage, strerror(errno)); + } + } + } + + // Write data to the buffer + if (l_uiRemainSize < f_uilength) { + // Wrapping write + memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, l_uiRemainSize); + memcpy(m_pRbuf, f_pBuffer + l_uiRemainSize, f_uilength - l_uiRemainSize); + + // Update the write pointer + m_pRbufHdr->m_uiWritePtr = f_uilength - l_uiRemainSize; + + // The buffer is full of valid data + m_pRbufHdr->m_bIsFull = TRUE; + } else { + memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, f_uilength); + + // Update the write pointer + m_pRbufHdr->m_uiWritePtr += f_uilength; + + // Write pointer is the end of the buffer + if (m_pRbufHdr->m_uiWritePtr == m_uiRingBuffSize) { + m_pRbufHdr->m_uiWritePtr = 0; + + // The buffer is full of valid data + m_pRbufHdr->m_bIsFull = TRUE; + } + } + + // Update un-read data size + m_pRbufHdr->m_uiUnReadSize += f_uilength; + + // Set read pointer to be same as write pointer if write pointer exceeds the read pointer + if (m_uiRingBuffSize < m_pRbufHdr->m_uiUnReadSize) { + m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr; + m_pRbufHdr->m_uiUnReadSize = m_uiRingBuffSize; + } + + while (l_uiLastPage != RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr)) { + if (madvise(m_pRbuf + l_uiLastPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) { + fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n", m_pRbuf + l_uiLastPage, strerror(errno)); + } + l_uiLastPage += RBUF_PAGE_SIZE; + if (l_uiLastPage >= m_uiRingBuffSize) { + l_uiLastPage = 0; + } + } + m_siProcessLastWrtPage = (SI_32)l_uiLastPage; + + UnlockMtx(); + + l_iWriteSize = f_uilength; +#endif + int ret; + if ( (ret = LockMtx()) == 0) { + UI_32 l_uiLastPage = RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr); + l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr; + + if (m_siProcessLastWrtPage >= 0) { + if ((UI_32)m_siProcessLastWrtPage != l_uiLastPage) { + if (madvise(m_pRbuf + m_siProcessLastWrtPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) { + fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n", + m_pRbuf + m_siProcessLastWrtPage, strerror(errno)); + } + } + } + + // Write data to the buffer + if (l_uiRemainSize < f_uilength) { + // Wrapping write + memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, l_uiRemainSize); + memcpy(m_pRbuf, f_pBuffer + l_uiRemainSize, f_uilength - l_uiRemainSize); + + // Update the write pointer + m_pRbufHdr->m_uiWritePtr = f_uilength - l_uiRemainSize; + + // The buffer is full of valid data + m_pRbufHdr->m_bIsFull = TRUE; + } else { + memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, f_uilength); + + // Update the write pointer + m_pRbufHdr->m_uiWritePtr += f_uilength; + + // Write pointer is the end of the buffer + if (m_pRbufHdr->m_uiWritePtr == m_uiRingBuffSize) { + m_pRbufHdr->m_uiWritePtr = 0; + + // The buffer is full of valid data + m_pRbufHdr->m_bIsFull = TRUE; + } + } + + // Update un-read data size + m_pRbufHdr->m_uiUnReadSize += f_uilength; + + // Set read pointer to be same as write pointer if write pointer exceeds the read pointer + if (m_uiRingBuffSize < m_pRbufHdr->m_uiUnReadSize) { + m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr; + m_pRbufHdr->m_uiUnReadSize = m_uiRingBuffSize; + } + + while (l_uiLastPage != RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr)) { + if (madvise(m_pRbuf + l_uiLastPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) { + fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n", + m_pRbuf + l_uiLastPage, strerror(errno)); + } + l_uiLastPage += RBUF_PAGE_SIZE; + if (l_uiLastPage >= m_uiRingBuffSize) { + l_uiLastPage = 0; + } + } + m_siProcessLastWrtPage = (SI_32)l_uiLastPage; + + UnlockMtx(); + + l_iWriteSize = f_uilength; + } else { + fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret)); + l_iWriteSize = 0; + } + + } + + return l_iWriteSize; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// DumpToFile +/// This function writes all the data in the buffer into provided file f_pPath. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::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_pRbufHdr) { + // Open file + if (-1 != (fd = open(f_pPath, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640))) { + if (NULL != m_pRbuf && 0 != m_uiRingBuffSize) { + +#if 0 + LockMtx(); + // Write buffer data to file + if (m_pRbufHdr->m_bIsFull) { + // Buffer has full of data (read data from write pointer) + if (-1 != (l_iSize = write(fd, m_pRbuf + m_pRbufHdr->m_uiWritePtr, + m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr))) { + *f_uiDumpSize += static_cast<UI_32>(l_iSize); + } else { + l_eStatus = eFrameworkunifiedStatusErrOther; + } + } + + if (-1 != (l_iSize = write(fd, m_pRbuf, m_pRbufHdr->m_uiWritePtr))) { + *f_uiDumpSize += static_cast<UI_32>(l_iSize); + } + + UnlockMtx(); +#endif + int ret; + if ( (ret = LockMtx()) == 0) { + // Write buffer data to file + if (m_pRbufHdr->m_bIsFull) { + // Buffer has full of data (read data from write pointer) + if (-1 != (l_iSize = write(fd, m_pRbuf + m_pRbufHdr->m_uiWritePtr, + m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr))) { + +// *f_uiDumpSize += l_iSize; + *f_uiDumpSize += static_cast<UI_32>(l_iSize); + } else { + l_eStatus = eFrameworkunifiedStatusErrOther; + } + } + + if (-1 != (l_iSize = write(fd, m_pRbuf, m_pRbufHdr->m_uiWritePtr))) { + +// *f_uiDumpSize += l_iSize; + *f_uiDumpSize += static_cast<UI_32>(l_iSize); + } + + UnlockMtx(); + } else { + fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret)); + } + + } else if (NULL == m_pRbuf && 0 != m_uiRingBuffSize) { + 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 CNSRingBuffer::GetSize() { + SI_32 l_uiReadSize = -1; + + if (NULL != m_pRbufHdr) { + l_uiReadSize = m_pRbufHdr->m_uiUnReadSize; + } + + return l_uiReadSize; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// ClearBuf +/// This function clears the buffer. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::ClearBuf() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + if (NULL != m_pRbufHdr) { + +#if 0 + LockMtx(); + + // Initialize the r/w pointers + m_pRbufHdr->m_uiReadPtr = 0; + m_pRbufHdr->m_uiWritePtr = 0; + m_pRbufHdr->m_uiUnReadSize = 0; + m_pRbufHdr->m_bIsFull = FALSE; + + UnlockMtx(); +#endif + int ret; + if ((ret = LockMtx()) == 0) { + // Initialize the r/w pointers + m_pRbufHdr->m_uiReadPtr = 0; + m_pRbufHdr->m_uiWritePtr = 0; + m_pRbufHdr->m_uiUnReadSize = 0; + m_pRbufHdr->m_bIsFull = FALSE; + + UnlockMtx(); + } else { + fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret)); + } + + } else { + l_eStatus = eFrameworkunifiedStatusFail; + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// SetReadPtrToWritePtr +/// This function sets the position of read ptr to write ptr in buffer. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::SetReadPtrToWritePtr() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + if (NULL != m_pRbufHdr) { + +#if 0 + LockMtx(); + + // Initialize the r/w pointers + m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr; + m_pRbufHdr->m_uiUnReadSize = 0; + + UnlockMtx(); +#endif + int ret; + if ( (ret = LockMtx()) == 0) { + // Initialize the r/w pointers + m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr; + m_pRbufHdr->m_uiUnReadSize = 0; + + UnlockMtx(); + } else { + fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret)); + } + + } else { + l_eStatus = eFrameworkunifiedStatusFail; + } + + return l_eStatus; +} +// +//////////////////////////////////////////////////////////////////////////////////////////////// +/// CreateRBMutex +/// This function creates the shared memory object for mutex. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::CreateRBMutex() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail; + + // file descriptor of shared memory + SI_32 l_siId = -1; + + // ring buffer mutex + NSRingBufferMtx *l_pRbufMtx = NULL; + + if ((!m_cRbufMtxName.empty()) || (m_cRbufMtxName.size() <= NAME_MAX)) { + // Try to create shared memory + l_siId = shm_open(m_cRbufMtxName.c_str(), O_CREAT | O_EXCL | O_RDWR, 0640); + + if (-1 != l_siId) { + // Set the size of shared memory + if (-1 != ftruncate(l_siId, sizeof(NSRingBufferMtx))) { + // Map the shared memory + l_pRbufMtx = reinterpret_cast<NSRingBufferMtx *>(mmap(NULL, + sizeof(NSRingBufferMtx), (PROT_READ | PROT_WRITE), MAP_SHARED, l_siId, 0)); + + if (MAP_FAILED != l_pRbufMtx) { + if (m_lid == -1) { + // mutex attribute + pthread_mutexattr_t l_tMtxAttr = {}; + + // Initialize mutex + pthread_mutexattr_init(&l_tMtxAttr); + pthread_mutexattr_setpshared(&l_tMtxAttr, PTHREAD_PROCESS_SHARED); + pthread_mutex_init(&l_pRbufMtx->m_tBufMutex, &l_tMtxAttr); + pthread_mutexattr_destroy(&l_tMtxAttr); + + l_eStatus = eFrameworkunifiedStatusOK; + } else { + // CL_Lock + l_eStatus = eFrameworkunifiedStatusOK; + } + l_pRbufMtx->m_lid = m_lid; + + // Once initialized un-map the shared memory + munmap(l_pRbufMtx, sizeof(NSRingBufferMtx)); + } + } + + 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; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// CreateRBHeader +/// This function creates the ring buffer object for header. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::CreateRBHeader() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail; + + // file descriptor of ring buffer + SI_32 l_siFd = -1; + + // ring buffer headers + NSRingBufferHdr *l_pRbufHdr = NULL; + + if (!m_cMappedFileHdrPath.empty()) { // LCOV_EXCL_BR_LINE 11: except branch + // Try to create ring buffer + l_siFd = open(m_cMappedFileHdrPath.c_str(), O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0640); + + if (-1 != l_siFd) { + // Set the size of ring buffer + if (-1 != ftruncate(l_siFd, sizeof(NSRingBufferHdr))) { + // Map the ring buffer + l_pRbufHdr = reinterpret_cast<NSRingBufferHdr *>(mmap(NULL, + sizeof(NSRingBufferHdr), (PROT_READ | PROT_WRITE), MAP_SHARED, l_siFd, 0)); + + if (MAP_FAILED != l_pRbufHdr) { + +#if 0 + LockMtx(); + + // Initialize the r/w pointers + l_pRbufHdr->m_uiReadPtr = 0; + l_pRbufHdr->m_uiWritePtr = 0; + l_pRbufHdr->m_uiUnReadSize = 0; + l_pRbufHdr->m_bIsFull = FALSE; + l_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize; + + UnlockMtx(); +#endif + int ret; + if ( (ret = LockMtx()) == 0) { + // Initialize the r/w pointers + l_pRbufHdr->m_uiReadPtr = 0; + l_pRbufHdr->m_uiWritePtr = 0; + l_pRbufHdr->m_uiUnReadSize = 0; + l_pRbufHdr->m_bIsFull = FALSE; + l_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize; + + UnlockMtx(); + l_eStatus = eFrameworkunifiedStatusOK; + } else { + fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret)); + l_eStatus = eFrameworkunifiedStatusFail; + } + + + // Once initialized un-map the ring buffer + munmap(l_pRbufHdr, sizeof(NSRingBufferHdr)); + } + } + + close(l_siFd); + } else if (EEXIST == errno) { + // ring buffer is already created + l_eStatus = eFrameworkunifiedStatusDuplicate; + } else { + // do nothing + } + } else { + l_eStatus = eFrameworkunifiedStatusInvldParam; + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// CreateRBDataBuffer +/// This function creates the ring buffer object for data buffer. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::CreateRBDataBuffer() { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail; + + // file descriptor of ring buffer + SI_32 l_siFd = -1; + + if (!m_cMappedFilePath.empty()) { + // Try to create ring buffer + l_siFd = open(m_cMappedFilePath.c_str(), O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0640); + + if (-1 != l_siFd) { + // Set the size of ring buffer + if (-1 != ftruncate(l_siFd, m_uiRingBuffSize)) { + l_eStatus = eFrameworkunifiedStatusOK; + } + + close(l_siFd); + } else if (EEXIST == errno) { + // ring buffer is already created + l_eStatus = eFrameworkunifiedStatusDuplicate; + } else { + // do nothing + } + } else { + l_eStatus = eFrameworkunifiedStatusInvldParam; + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// MapRBHeader +/// This function open and maps in process space. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::Map(PVOID *f_pRbuf, const std::string &f_cMappedFile, const UI_32 f_uiRbufSize) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail; + + // file descriptor of ring buffer + SI_32 l_siFd = -1; + + // ring buffer headers + PVOID l_pRbuf = NULL; + + // Open ring buffer + l_siFd = open(f_cMappedFile.c_str(), O_RDWR | O_CLOEXEC, NULL); + + if (-1 != l_siFd) { + if (CheckSize(l_siFd, f_uiRbufSize) == eFrameworkunifiedStatusOK) { + // Map the ring buffer into its memory space + l_pRbuf = mmap(NULL, f_uiRbufSize, (PROT_READ | PROT_WRITE), MAP_SHARED, l_siFd, 0); + + if (MAP_FAILED != l_pRbuf) { + *f_pRbuf = l_pRbuf; + l_eStatus = eFrameworkunifiedStatusOK; + } + } + + close(l_siFd); + } + + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// CheckSize +/// This function check mmap size +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::CheckSize(int fd, off_t size) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail; + struct stat st; + int i; + + for (i = 0; i < RBUF_RETRY_COUNT; i++) { + if (fstat(fd, &st) < 0) { + fprintf(stderr, "[CNSRingBuffer::CheckSize] fstat error: %s\n", strerror(errno)); + goto out; + } + if (st.st_size == size) { + l_eStatus = eFrameworkunifiedStatusOK; + break; + } + usleep(RBUF_RETRY_SLEEP); + } + if (i >= RBUF_RETRY_COUNT) { + errno = ENOMEM; + } + +out: + return l_eStatus; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// MapSM +/// This function shm_open and maps the shared memory in process space. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::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, 0640); + + if (-1 != l_siId) { + if (CheckSize(l_siId, f_uiShmSize) == eFrameworkunifiedStatusOK) { + // 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; +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +/// UnMap +/// This function unmaps object. +//////////////////////////////////////////////////////////////////////////////////////////////// +EFrameworkunifiedStatus CNSRingBuffer::UnMap(PVOID f_pRbuf, const UI_32 f_uiRbufSize) { + EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK; + + // Un-map the ring buffer + if (NULL != f_pRbuf) { + if (0 != munmap(f_pRbuf, f_uiRbufSize)) { + l_eStatus = eFrameworkunifiedStatusFail; + } + } else { + l_eStatus = eFrameworkunifiedStatusNullPointer; + } + + return l_eStatus; +} + + +//void CNSRingBuffer::LockMtx() { +// if (m_lid == -1) { +// pthread_mutex_lock(&m_pRbufMtx->m_tBufMutex); +// } else { +// CL_LockGet(m_pLockAddr); +// } +//} +int CNSRingBuffer::LockMtx() { + int ret = 0; + + if (m_lid == -1) { + ret = pthread_mutex_lock(&m_pRbufMtx->m_tBufMutex); + } else { + ret = CL_LockGet(m_pLockAddr); + } + + return ret; +} + + +void CNSRingBuffer::UnlockMtx() { + if (m_lid == -1) { + pthread_mutex_unlock(&m_pRbufMtx->m_tBufMutex); + } else { + CL_LockRelease(m_pLockAddr); + } +} |