2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 ////////////////////////////////////////////////////////////////////////////////////////////////////
18 /// \ingroup tag_NSRingBuffer
19 /// \brief This file contains implementation of class CNSRingBuffer.
20 /// This class provides API to open, read, write and close ring buffer
22 ////////////////////////////////////////////////////////////////////////////////////////////////////
24 ////////////////////////////////////////////////////////////////////////////////////////////////////
26 ////////////////////////////////////////////////////////////////////////////////////////////////////
37 #include <native_service/ns_ringbuffer.h>
38 #include <native_service/cl_lock.h>
42 #define RBUF_HEADER_EXT "Hdr"
43 #define RBUF_RETRY_SLEEP (1000)
44 #define RBUF_RETRY_COUNT (8)
45 #define RBUF_PAGE_SIZE (4096)
46 #define RBUF_PAGE_ALIGN(p) ((p / RBUF_PAGE_SIZE) * RBUF_PAGE_SIZE)
48 ////////////////////////////////////////////////////////////////////////////////////////////////
50 /// Parameterized Constructor of CNSRingBuffer class
51 ////////////////////////////////////////////////////////////////////////////////////////////////
52 CNSRingBuffer::CNSRingBuffer(const std::string &f_cMappedFilePath, const UI_32 f_uiSize, int f_lid):
53 m_cMappedFilePath(f_cMappedFilePath), m_uiRingBuffSize(f_uiSize), m_pRbufMtx(NULL), m_pRbufHdr(NULL), m_pRbuf(NULL),
54 m_lid(f_lid), m_pLockAddr(NULL), m_siProcessLastWrtPage(-1) { // LCOV_EXCL_BR_LINE 11: except branch
55 m_cMappedFileHdrPath = f_cMappedFilePath;
56 m_cMappedFileHdrPath.append(RBUF_HEADER_EXT); // LCOV_EXCL_BR_LINE 11: except branch
58 m_cRbufMtxName = f_cMappedFilePath;
59 std::size_t found = m_cRbufMtxName.find_first_of('/');
60 while (found != std::string::npos) {
61 m_cRbufMtxName[found] = '_';
62 found = m_cRbufMtxName.find_first_of('/', found + 1);
64 m_cRbufMtxName[0] = '/';
65 pthread_mutex_init(&m_tOpenMutex, NULL);
68 ////////////////////////////////////////////////////////////////////////////////////////////////
70 /// Constructor of CNSRingBuffer class
71 ////////////////////////////////////////////////////////////////////////////////////////////////
72 CNSRingBuffer::CNSRingBuffer():
73 m_cMappedFilePath(""), m_uiRingBuffSize(0), m_pRbufMtx(NULL), m_pRbufHdr(NULL), m_pRbuf(NULL), m_lid(-1),
74 m_pLockAddr(NULL), m_siProcessLastWrtPage(-1) {
75 pthread_mutex_init(&m_tOpenMutex, NULL);
78 ////////////////////////////////////////////////////////////////////////////////////////////////
80 /// Destructor of CNSRingBuffer class
81 ////////////////////////////////////////////////////////////////////////////////////////////////
82 CNSRingBuffer::~CNSRingBuffer() {
83 if (NULL != m_pRbufHdr) {
84 // un-map the ring buffer object
90 pthread_mutex_destroy(&m_tOpenMutex);
93 ////////////////////////////////////////////////////////////////////////////////////////////////
95 /// This function opens and maps the ring buffer object.
96 /// It creates the ring buffer if it does not exists.
97 ////////////////////////////////////////////////////////////////////////////////////////////////
98 EFrameworkunifiedStatus CNSRingBuffer::Open() {
99 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusErrOther;
101 pthread_mutex_lock(&m_tOpenMutex);
103 if (NULL == m_pRbufMtx) {
104 // Open ring buffer mutex
105 if (eFrameworkunifiedStatusOK != (l_eStatus = MapSM(reinterpret_cast<PVOID *>(&m_pRbufMtx),
106 m_cRbufMtxName, sizeof(NSRingBufferMtx)))) {
107 if (ENOENT == errno) {
111 // if (eFrameworkunifiedStatusOK == CreateRBMutex()) {
112 EFrameworkunifiedStatus l_eStatus1 = CreateRBMutex();
113 if ((l_eStatus1 == eFrameworkunifiedStatusOK) || (l_eStatus1 == eFrameworkunifiedStatusDuplicate)) {
115 l_eStatus = MapSM(reinterpret_cast<PVOID *>(&m_pRbufMtx), m_cRbufMtxName, sizeof(NSRingBufferMtx));
119 if (m_pRbufMtx->m_lid != m_lid) {
120 // Different Lock ID in constructor parameter and mutex object
121 l_eStatus = eFrameworkunifiedStatusInvldParam;
126 if (eFrameworkunifiedStatusOK == l_eStatus) {
127 if (m_lid >= 0 && NULL == m_pLockAddr) {
128 CL_LockProcessInit();
129 if ((m_pLockAddr = CL_LockMap(m_lid)) == MAP_FAILED) {
130 l_eStatus = eFrameworkunifiedStatusFail;
135 if (eFrameworkunifiedStatusOK == l_eStatus) {
136 if (NULL == m_pRbufHdr) {
137 // Open header ring buffer
138 if (eFrameworkunifiedStatusOK != (l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbufHdr),
139 m_cMappedFileHdrPath, sizeof(NSRingBufferHdr)))) {
140 if (ENOENT == errno) { // ring buffer is not created yet
143 // Create ring buffer
145 // if (eFrameworkunifiedStatusOK == CreateRBHeader()) {
146 EFrameworkunifiedStatus l_eStatus1 = CreateRBHeader();
147 if ((l_eStatus1 == eFrameworkunifiedStatusOK) || (l_eStatus1 == eFrameworkunifiedStatusDuplicate)) {
150 l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbufHdr),
151 m_cMappedFileHdrPath, sizeof(NSRingBufferHdr));
155 l_eStatus = l_eStatus1;
165 int ret = stat(m_cMappedFilePath.c_str(), &st);
167 if (m_uiRingBuffSize == 0) {
168 if (ret == 0) { // LCOV_EXCL_BR_LINE 5:stat's error case.
169 // LCOV_EXCL_START 5: stat's error case.
170 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
171 if ((UI_32)st.st_size != m_pRbufHdr->m_uiRingBufferSize || (UI_32)st.st_size < m_pRbufHdr->m_uiReadPtr
172 || (UI_32)st.st_size < m_pRbufHdr->m_uiWritePtr) {
173 memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr));
174 m_pRbufHdr->m_uiRingBufferSize = static_cast<UI_32>(st.st_size);
175 unlink(m_cMappedFilePath.c_str());
177 m_uiRingBuffSize = static_cast<UI_32>(st.st_size);
181 if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize || m_uiRingBuffSize < m_pRbufHdr->m_uiReadPtr
182 || m_uiRingBuffSize < m_pRbufHdr->m_uiWritePtr || (ret == 0 && m_uiRingBuffSize != (UI_32)st.st_size)) {
183 memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr));
184 m_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize;
185 unlink(m_cMappedFilePath.c_str());
192 if ( (ret = LockMtx()) == 0) {
194 int ret = stat(m_cMappedFilePath.c_str(), &st);
196 if (m_uiRingBuffSize == 0) {
198 if ((UI_32)st.st_size != m_pRbufHdr->m_uiRingBufferSize || (UI_32)st.st_size < m_pRbufHdr->m_uiReadPtr ||
199 (UI_32)st.st_size < m_pRbufHdr->m_uiWritePtr) {
200 memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr));
201 m_pRbufHdr->m_uiRingBufferSize = static_cast<UI_32>(st.st_size);
202 unlink(m_cMappedFilePath.c_str());
204 m_uiRingBuffSize = static_cast<UI_32>(st.st_size);
207 if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize || m_uiRingBuffSize < m_pRbufHdr->m_uiReadPtr ||
208 m_uiRingBuffSize < m_pRbufHdr->m_uiWritePtr || (ret == 0 && m_uiRingBuffSize != (UI_32)st.st_size)) {
209 memset(m_pRbufHdr, 0, sizeof(NSRingBufferHdr));
210 m_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize;
211 unlink(m_cMappedFilePath.c_str());
217 fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
218 munmap(m_pRbufHdr, sizeof(NSRingBufferHdr));
220 l_eStatus = eFrameworkunifiedStatusFail;
227 if (eFrameworkunifiedStatusOK == l_eStatus && 0 != m_uiRingBuffSize) {
228 if (NULL == m_pRbuf) {
229 // Open ring buffer data buffer, create if not exists
230 if (eFrameworkunifiedStatusOK != (l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbuf),
231 m_cMappedFilePath, m_uiRingBuffSize))) {
232 if (ENOENT == errno) { // ring buffer is not created yet
233 // Create ring buffer
235 // if (eFrameworkunifiedStatusOK == CreateRBDataBuffer()) {
236 EFrameworkunifiedStatus l_eStatus1 = CreateRBDataBuffer();
237 if ((l_eStatus1 == eFrameworkunifiedStatusOK) || (l_eStatus1 == eFrameworkunifiedStatusDuplicate)) {
240 l_eStatus = Map(reinterpret_cast<PVOID *>(&m_pRbuf),
241 m_cMappedFilePath, m_uiRingBuffSize);
248 pthread_mutex_unlock(&m_tOpenMutex);
253 ////////////////////////////////////////////////////////////////////////////////////////////////
255 /// This function is used to check whether the ring buffer is opened or not.
256 ////////////////////////////////////////////////////////////////////////////////////////////////
257 BOOL CNSRingBuffer::IsOpen() {
258 return NULL == m_pRbufHdr ? FALSE : TRUE;
261 ////////////////////////////////////////////////////////////////////////////////////////////////
263 /// This function closes the ring buffer object.
264 ////////////////////////////////////////////////////////////////////////////////////////////////
265 EFrameworkunifiedStatus CNSRingBuffer::Close() {
266 if (NULL != m_pLockAddr) {
267 CL_LockUnmap(m_pLockAddr);
270 EFrameworkunifiedStatus l_eStatus1 = UnMap(m_pRbufHdr, sizeof(NSRingBufferHdr));
273 EFrameworkunifiedStatus l_eStatus2 = eFrameworkunifiedStatusOK;
274 if (0 != m_uiRingBuffSize) {
275 l_eStatus2 = UnMap(m_pRbuf, m_uiRingBuffSize);
279 EFrameworkunifiedStatus l_eStatus3 = UnMap(m_pRbufMtx, sizeof(NSRingBufferMtx));
282 return (eFrameworkunifiedStatusOK != l_eStatus1 || eFrameworkunifiedStatusOK != l_eStatus2 ||
283 eFrameworkunifiedStatusOK != l_eStatus3) ? eFrameworkunifiedStatusFail : eFrameworkunifiedStatusOK;
286 ////////////////////////////////////////////////////////////////////////////////////////////////
288 /// This function reads data from the ring buffer.
289 ////////////////////////////////////////////////////////////////////////////////////////////////
290 SI_32 CNSRingBuffer::Read(PSTR f_pBuffer, const UI_32 f_uilength) {
291 SI_32 l_iReadSize = -1;
293 if ((NULL != f_pBuffer) && (NULL != m_pRbufHdr) && (0 != f_uilength)) {
294 UI_32 l_uiDataSizeToRead = 0;
296 // Remaining buffer size from read pointer to end of the buffer
297 UI_32 l_uiRemainSize = 0;
303 // if ring buffer size is changed by some other process, remap the updated buffer size in this process
304 // ring buffer size can only be changed if the initial size is 0.
305 if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize) {
306 if (eFrameworkunifiedStatusOK == Map(reinterpret_cast<PVOID *>(&m_pRbuf),
307 m_cMappedFilePath, m_pRbufHdr->m_uiRingBufferSize)) {
308 m_uiRingBuffSize = m_pRbufHdr->m_uiRingBufferSize;
312 if (NULL != m_pRbuf) {
313 l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiReadPtr;
315 // Round read data size depending on un-read data size in the buffer
316 l_uiDataSizeToRead = m_pRbufHdr->m_uiUnReadSize < f_uilength ? m_pRbufHdr->m_uiUnReadSize : f_uilength;
318 if (l_uiRemainSize < l_uiDataSizeToRead) {
320 memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiRemainSize);
321 memcpy(f_pBuffer + l_uiRemainSize, m_pRbuf, l_uiDataSizeToRead - l_uiRemainSize);
322 m_pRbufHdr->m_uiReadPtr = l_uiDataSizeToRead - l_uiRemainSize;
324 memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiDataSizeToRead);
326 m_pRbufHdr->m_uiReadPtr += l_uiDataSizeToRead;
328 // Read pointer is the end of the buffer
329 if (m_pRbufHdr->m_uiReadPtr == m_uiRingBuffSize) {
330 m_pRbufHdr->m_uiReadPtr = 0;
334 m_pRbufHdr->m_uiUnReadSize -= l_uiDataSizeToRead; // Update un-read data size
336 l_iReadSize = l_uiDataSizeToRead;
342 if ( (ret = LockMtx()) == 0) {
343 // if ring buffer size is changed by some other process, remap the updated buffer size in this process
344 // ring buffer size can only be changed if the initial size is 0.
345 if (m_uiRingBuffSize != m_pRbufHdr->m_uiRingBufferSize) {
346 if (eFrameworkunifiedStatusOK == Map(reinterpret_cast<PVOID *>(&m_pRbuf),
347 m_cMappedFilePath, m_pRbufHdr->m_uiRingBufferSize)) {
348 m_uiRingBuffSize = m_pRbufHdr->m_uiRingBufferSize;
352 if (NULL != m_pRbuf) {
353 l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiReadPtr;
355 // Round read data size depending on un-read data size in the buffer
356 l_uiDataSizeToRead = m_pRbufHdr->m_uiUnReadSize < f_uilength ? m_pRbufHdr->m_uiUnReadSize : f_uilength;
358 if (l_uiRemainSize < l_uiDataSizeToRead) {
360 memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiRemainSize);
361 memcpy(f_pBuffer + l_uiRemainSize, m_pRbuf, l_uiDataSizeToRead - l_uiRemainSize);
362 m_pRbufHdr->m_uiReadPtr = l_uiDataSizeToRead - l_uiRemainSize;
364 memcpy(f_pBuffer, m_pRbuf + m_pRbufHdr->m_uiReadPtr, l_uiDataSizeToRead);
366 m_pRbufHdr->m_uiReadPtr += l_uiDataSizeToRead;
368 // Read pointer is the end of the buffer
369 if (m_pRbufHdr->m_uiReadPtr == m_uiRingBuffSize) {
370 m_pRbufHdr->m_uiReadPtr = 0;
374 m_pRbufHdr->m_uiUnReadSize -= l_uiDataSizeToRead; // Update un-read data size
376 l_iReadSize = l_uiDataSizeToRead;
381 fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
390 ////////////////////////////////////////////////////////////////////////////////////////////////
392 /// This function writes the data into the ring buffer.
393 ////////////////////////////////////////////////////////////////////////////////////////////////
394 SI_32 CNSRingBuffer::Write(PCSTR f_pBuffer, const UI_32 f_uilength) {
395 SI_32 l_iWriteSize = -1;
397 // size available in buffer
398 UI_32 l_uiRemainSize = 0;
400 if (NULL != m_pRbufHdr && NULL != m_pRbuf && NULL != f_pBuffer && f_uilength <= m_uiRingBuffSize) { // LCOV_EXCL_BR_LINE 11:except branch
404 UI_32 l_uiLastPage = RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr);
405 l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr;
407 if (m_siProcessLastWrtPage >= 0) {
408 if ((UI_32)m_siProcessLastWrtPage != l_uiLastPage) {
409 if (madvise(m_pRbuf + m_siProcessLastWrtPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) {
410 fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n",
411 m_pRbuf + m_siProcessLastWrtPage, strerror(errno));
416 // Write data to the buffer
417 if (l_uiRemainSize < f_uilength) {
419 memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, l_uiRemainSize);
420 memcpy(m_pRbuf, f_pBuffer + l_uiRemainSize, f_uilength - l_uiRemainSize);
422 // Update the write pointer
423 m_pRbufHdr->m_uiWritePtr = f_uilength - l_uiRemainSize;
425 // The buffer is full of valid data
426 m_pRbufHdr->m_bIsFull = TRUE;
428 memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, f_uilength);
430 // Update the write pointer
431 m_pRbufHdr->m_uiWritePtr += f_uilength;
433 // Write pointer is the end of the buffer
434 if (m_pRbufHdr->m_uiWritePtr == m_uiRingBuffSize) {
435 m_pRbufHdr->m_uiWritePtr = 0;
437 // The buffer is full of valid data
438 m_pRbufHdr->m_bIsFull = TRUE;
442 // Update un-read data size
443 m_pRbufHdr->m_uiUnReadSize += f_uilength;
445 // Set read pointer to be same as write pointer if write pointer exceeds the read pointer
446 if (m_uiRingBuffSize < m_pRbufHdr->m_uiUnReadSize) {
447 m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr;
448 m_pRbufHdr->m_uiUnReadSize = m_uiRingBuffSize;
451 while (l_uiLastPage != RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr)) {
452 if (madvise(m_pRbuf + l_uiLastPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) {
453 fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n", m_pRbuf + l_uiLastPage, strerror(errno));
455 l_uiLastPage += RBUF_PAGE_SIZE;
456 if (l_uiLastPage >= m_uiRingBuffSize) {
460 m_siProcessLastWrtPage = (SI_32)l_uiLastPage;
464 l_iWriteSize = f_uilength;
467 if ( (ret = LockMtx()) == 0) {
468 UI_32 l_uiLastPage = RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr);
469 l_uiRemainSize = m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr;
471 if (m_siProcessLastWrtPage >= 0) {
472 if ((UI_32)m_siProcessLastWrtPage != l_uiLastPage) {
473 if (madvise(m_pRbuf + m_siProcessLastWrtPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) {
474 fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n",
475 m_pRbuf + m_siProcessLastWrtPage, strerror(errno));
480 // Write data to the buffer
481 if (l_uiRemainSize < f_uilength) {
483 memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, l_uiRemainSize);
484 memcpy(m_pRbuf, f_pBuffer + l_uiRemainSize, f_uilength - l_uiRemainSize);
486 // Update the write pointer
487 m_pRbufHdr->m_uiWritePtr = f_uilength - l_uiRemainSize;
489 // The buffer is full of valid data
490 m_pRbufHdr->m_bIsFull = TRUE;
492 memcpy(m_pRbuf + m_pRbufHdr->m_uiWritePtr, f_pBuffer, f_uilength);
494 // Update the write pointer
495 m_pRbufHdr->m_uiWritePtr += f_uilength;
497 // Write pointer is the end of the buffer
498 if (m_pRbufHdr->m_uiWritePtr == m_uiRingBuffSize) {
499 m_pRbufHdr->m_uiWritePtr = 0;
501 // The buffer is full of valid data
502 m_pRbufHdr->m_bIsFull = TRUE;
506 // Update un-read data size
507 m_pRbufHdr->m_uiUnReadSize += f_uilength;
509 // Set read pointer to be same as write pointer if write pointer exceeds the read pointer
510 if (m_uiRingBuffSize < m_pRbufHdr->m_uiUnReadSize) {
511 m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr;
512 m_pRbufHdr->m_uiUnReadSize = m_uiRingBuffSize;
515 while (l_uiLastPage != RBUF_PAGE_ALIGN(m_pRbufHdr->m_uiWritePtr)) {
516 if (madvise(m_pRbuf + l_uiLastPage, RBUF_PAGE_SIZE, MADV_DONTNEED) < 0) {
517 fprintf(stderr, "[CNSRingBuffer::Write] madvise(%p) error: %s\n",
518 m_pRbuf + l_uiLastPage, strerror(errno));
520 l_uiLastPage += RBUF_PAGE_SIZE;
521 if (l_uiLastPage >= m_uiRingBuffSize) {
525 m_siProcessLastWrtPage = (SI_32)l_uiLastPage;
529 l_iWriteSize = f_uilength;
531 fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
540 ////////////////////////////////////////////////////////////////////////////////////////////////
542 /// This function writes all the data in the buffer into provided file f_pPath.
543 ////////////////////////////////////////////////////////////////////////////////////////////////
544 EFrameworkunifiedStatus CNSRingBuffer::DumpToFile(PCSTR f_pPath, PUI_32 f_uiDumpSize) {
545 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
551 if (NULL == f_uiDumpSize) {
552 return eFrameworkunifiedStatusNullPointer;
556 if (NULL != f_pPath) {
557 if (NULL != m_pRbufHdr) {
559 if (-1 != (fd = open(f_pPath, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640))) {
560 if (NULL != m_pRbuf && 0 != m_uiRingBuffSize) {
564 // Write buffer data to file
565 if (m_pRbufHdr->m_bIsFull) {
566 // Buffer has full of data (read data from write pointer)
567 if (-1 != (l_iSize = write(fd, m_pRbuf + m_pRbufHdr->m_uiWritePtr,
568 m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr))) {
569 *f_uiDumpSize += static_cast<UI_32>(l_iSize);
571 l_eStatus = eFrameworkunifiedStatusErrOther;
575 if (-1 != (l_iSize = write(fd, m_pRbuf, m_pRbufHdr->m_uiWritePtr))) {
576 *f_uiDumpSize += static_cast<UI_32>(l_iSize);
582 if ( (ret = LockMtx()) == 0) {
583 // Write buffer data to file
584 if (m_pRbufHdr->m_bIsFull) {
585 // Buffer has full of data (read data from write pointer)
586 if (-1 != (l_iSize = write(fd, m_pRbuf + m_pRbufHdr->m_uiWritePtr,
587 m_uiRingBuffSize - m_pRbufHdr->m_uiWritePtr))) {
589 // *f_uiDumpSize += l_iSize;
590 *f_uiDumpSize += static_cast<UI_32>(l_iSize);
592 l_eStatus = eFrameworkunifiedStatusErrOther;
596 if (-1 != (l_iSize = write(fd, m_pRbuf, m_pRbufHdr->m_uiWritePtr))) {
598 // *f_uiDumpSize += l_iSize;
599 *f_uiDumpSize += static_cast<UI_32>(l_iSize);
604 fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
607 } else if (NULL == m_pRbuf && 0 != m_uiRingBuffSize) {
608 l_eStatus = eFrameworkunifiedStatusFail;
613 // Sync the file to force I/O operation completed
618 l_eStatus = eFrameworkunifiedStatusFileLoadError;
621 l_eStatus = eFrameworkunifiedStatusFail;
624 l_eStatus = eFrameworkunifiedStatusInvldParam;
630 ////////////////////////////////////////////////////////////////////////////////////////////////
632 /// This function returns the number of unread bytes which can be read by Read().
633 ////////////////////////////////////////////////////////////////////////////////////////////////
634 SI_32 CNSRingBuffer::GetSize() {
635 SI_32 l_uiReadSize = -1;
637 if (NULL != m_pRbufHdr) {
638 l_uiReadSize = m_pRbufHdr->m_uiUnReadSize;
644 ////////////////////////////////////////////////////////////////////////////////////////////////
646 /// This function clears the buffer.
647 ////////////////////////////////////////////////////////////////////////////////////////////////
648 EFrameworkunifiedStatus CNSRingBuffer::ClearBuf() {
649 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
651 if (NULL != m_pRbufHdr) {
656 // Initialize the r/w pointers
657 m_pRbufHdr->m_uiReadPtr = 0;
658 m_pRbufHdr->m_uiWritePtr = 0;
659 m_pRbufHdr->m_uiUnReadSize = 0;
660 m_pRbufHdr->m_bIsFull = FALSE;
665 if ((ret = LockMtx()) == 0) {
666 // Initialize the r/w pointers
667 m_pRbufHdr->m_uiReadPtr = 0;
668 m_pRbufHdr->m_uiWritePtr = 0;
669 m_pRbufHdr->m_uiUnReadSize = 0;
670 m_pRbufHdr->m_bIsFull = FALSE;
674 fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
678 l_eStatus = eFrameworkunifiedStatusFail;
684 ////////////////////////////////////////////////////////////////////////////////////////////////
685 /// SetReadPtrToWritePtr
686 /// This function sets the position of read ptr to write ptr in buffer.
687 ////////////////////////////////////////////////////////////////////////////////////////////////
688 EFrameworkunifiedStatus CNSRingBuffer::SetReadPtrToWritePtr() {
689 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
691 if (NULL != m_pRbufHdr) {
696 // Initialize the r/w pointers
697 m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr;
698 m_pRbufHdr->m_uiUnReadSize = 0;
703 if ( (ret = LockMtx()) == 0) {
704 // Initialize the r/w pointers
705 m_pRbufHdr->m_uiReadPtr = m_pRbufHdr->m_uiWritePtr;
706 m_pRbufHdr->m_uiUnReadSize = 0;
710 fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
714 l_eStatus = eFrameworkunifiedStatusFail;
720 ////////////////////////////////////////////////////////////////////////////////////////////////
722 /// This function creates the shared memory object for mutex.
723 ////////////////////////////////////////////////////////////////////////////////////////////////
724 EFrameworkunifiedStatus CNSRingBuffer::CreateRBMutex() {
725 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
727 // file descriptor of shared memory
731 NSRingBufferMtx *l_pRbufMtx = NULL;
733 if ((!m_cRbufMtxName.empty()) || (m_cRbufMtxName.size() <= NAME_MAX)) {
734 // Try to create shared memory
735 l_siId = shm_open(m_cRbufMtxName.c_str(), O_CREAT | O_EXCL | O_RDWR, 0640);
738 // Set the size of shared memory
739 if (-1 != ftruncate(l_siId, sizeof(NSRingBufferMtx))) {
740 // Map the shared memory
741 l_pRbufMtx = reinterpret_cast<NSRingBufferMtx *>(mmap(NULL,
742 sizeof(NSRingBufferMtx), (PROT_READ | PROT_WRITE), MAP_SHARED, l_siId, 0));
744 if (MAP_FAILED != l_pRbufMtx) {
747 pthread_mutexattr_t l_tMtxAttr = {};
750 pthread_mutexattr_init(&l_tMtxAttr);
751 pthread_mutexattr_setpshared(&l_tMtxAttr, PTHREAD_PROCESS_SHARED);
752 pthread_mutex_init(&l_pRbufMtx->m_tBufMutex, &l_tMtxAttr);
753 pthread_mutexattr_destroy(&l_tMtxAttr);
755 l_eStatus = eFrameworkunifiedStatusOK;
758 l_eStatus = eFrameworkunifiedStatusOK;
760 l_pRbufMtx->m_lid = m_lid;
762 // Once initialized un-map the shared memory
763 munmap(l_pRbufMtx, sizeof(NSRingBufferMtx));
768 } else if (EEXIST == errno) {
769 // Shared memory is already created
770 l_eStatus = eFrameworkunifiedStatusDuplicate;
775 l_eStatus = eFrameworkunifiedStatusInvldParam;
781 ////////////////////////////////////////////////////////////////////////////////////////////////
783 /// This function creates the ring buffer object for header.
784 ////////////////////////////////////////////////////////////////////////////////////////////////
785 EFrameworkunifiedStatus CNSRingBuffer::CreateRBHeader() {
786 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
788 // file descriptor of ring buffer
791 // ring buffer headers
792 NSRingBufferHdr *l_pRbufHdr = NULL;
794 if (!m_cMappedFileHdrPath.empty()) { // LCOV_EXCL_BR_LINE 11: except branch
795 // Try to create ring buffer
796 l_siFd = open(m_cMappedFileHdrPath.c_str(), O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0640);
799 // Set the size of ring buffer
800 if (-1 != ftruncate(l_siFd, sizeof(NSRingBufferHdr))) {
801 // Map the ring buffer
802 l_pRbufHdr = reinterpret_cast<NSRingBufferHdr *>(mmap(NULL,
803 sizeof(NSRingBufferHdr), (PROT_READ | PROT_WRITE), MAP_SHARED, l_siFd, 0));
805 if (MAP_FAILED != l_pRbufHdr) {
810 // Initialize the r/w pointers
811 l_pRbufHdr->m_uiReadPtr = 0;
812 l_pRbufHdr->m_uiWritePtr = 0;
813 l_pRbufHdr->m_uiUnReadSize = 0;
814 l_pRbufHdr->m_bIsFull = FALSE;
815 l_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize;
820 if ( (ret = LockMtx()) == 0) {
821 // Initialize the r/w pointers
822 l_pRbufHdr->m_uiReadPtr = 0;
823 l_pRbufHdr->m_uiWritePtr = 0;
824 l_pRbufHdr->m_uiUnReadSize = 0;
825 l_pRbufHdr->m_bIsFull = FALSE;
826 l_pRbufHdr->m_uiRingBufferSize = m_uiRingBuffSize;
829 l_eStatus = eFrameworkunifiedStatusOK;
831 fprintf(stderr, "[%s] LockMtx error: %s\n", __PRETTY_FUNCTION__, strerror(ret));
832 l_eStatus = eFrameworkunifiedStatusFail;
836 // Once initialized un-map the ring buffer
837 munmap(l_pRbufHdr, sizeof(NSRingBufferHdr));
842 } else if (EEXIST == errno) {
843 // ring buffer is already created
844 l_eStatus = eFrameworkunifiedStatusDuplicate;
849 l_eStatus = eFrameworkunifiedStatusInvldParam;
855 ////////////////////////////////////////////////////////////////////////////////////////////////
856 /// CreateRBDataBuffer
857 /// This function creates the ring buffer object for data buffer.
858 ////////////////////////////////////////////////////////////////////////////////////////////////
859 EFrameworkunifiedStatus CNSRingBuffer::CreateRBDataBuffer() {
860 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
862 // file descriptor of ring buffer
865 if (!m_cMappedFilePath.empty()) {
866 // Try to create ring buffer
867 l_siFd = open(m_cMappedFilePath.c_str(), O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0640);
870 // Set the size of ring buffer
871 if (-1 != ftruncate(l_siFd, m_uiRingBuffSize)) {
872 l_eStatus = eFrameworkunifiedStatusOK;
876 } else if (EEXIST == errno) {
877 // ring buffer is already created
878 l_eStatus = eFrameworkunifiedStatusDuplicate;
883 l_eStatus = eFrameworkunifiedStatusInvldParam;
889 ////////////////////////////////////////////////////////////////////////////////////////////////
891 /// This function open and maps in process space.
892 ////////////////////////////////////////////////////////////////////////////////////////////////
893 EFrameworkunifiedStatus CNSRingBuffer::Map(PVOID *f_pRbuf, const std::string &f_cMappedFile, const UI_32 f_uiRbufSize) {
894 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
896 // file descriptor of ring buffer
899 // ring buffer headers
900 PVOID l_pRbuf = NULL;
903 l_siFd = open(f_cMappedFile.c_str(), O_RDWR | O_CLOEXEC, NULL);
906 if (CheckSize(l_siFd, f_uiRbufSize) == eFrameworkunifiedStatusOK) {
907 // Map the ring buffer into its memory space
908 l_pRbuf = mmap(NULL, f_uiRbufSize, (PROT_READ | PROT_WRITE), MAP_SHARED, l_siFd, 0);
910 if (MAP_FAILED != l_pRbuf) {
912 l_eStatus = eFrameworkunifiedStatusOK;
922 ////////////////////////////////////////////////////////////////////////////////////////////////
924 /// This function check mmap size
925 ////////////////////////////////////////////////////////////////////////////////////////////////
926 EFrameworkunifiedStatus CNSRingBuffer::CheckSize(int fd, off_t size) {
927 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
931 for (i = 0; i < RBUF_RETRY_COUNT; i++) {
932 if (fstat(fd, &st) < 0) {
933 fprintf(stderr, "[CNSRingBuffer::CheckSize] fstat error: %s\n", strerror(errno));
936 if (st.st_size == size) {
937 l_eStatus = eFrameworkunifiedStatusOK;
940 usleep(RBUF_RETRY_SLEEP);
942 if (i >= RBUF_RETRY_COUNT) {
950 ////////////////////////////////////////////////////////////////////////////////////////////////
952 /// This function shm_open and maps the shared memory in process space.
953 ////////////////////////////////////////////////////////////////////////////////////////////////
954 EFrameworkunifiedStatus CNSRingBuffer::MapSM(PVOID *f_pShMem, const std::string &f_cShmName, const UI_32 f_uiShmSize) {
955 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusFail;
957 // file descriptor of shared memory
960 // shared memory buffer headers
961 PVOID l_pShmBuf = NULL;
963 // Open shared memory
964 l_siId = shm_open(f_cShmName.c_str(), O_RDWR, 0640);
967 if (CheckSize(l_siId, f_uiShmSize) == eFrameworkunifiedStatusOK) {
968 // Map the shared memory into its memory space
969 l_pShmBuf = mmap(NULL, f_uiShmSize, (PROT_READ | PROT_WRITE), MAP_SHARED, l_siId, 0);
971 if (MAP_FAILED != l_pShmBuf) {
972 *f_pShMem = l_pShmBuf;
973 l_eStatus = eFrameworkunifiedStatusOK;
983 ////////////////////////////////////////////////////////////////////////////////////////////////
985 /// This function unmaps object.
986 ////////////////////////////////////////////////////////////////////////////////////////////////
987 EFrameworkunifiedStatus CNSRingBuffer::UnMap(PVOID f_pRbuf, const UI_32 f_uiRbufSize) {
988 EFrameworkunifiedStatus l_eStatus = eFrameworkunifiedStatusOK;
990 // Un-map the ring buffer
991 if (NULL != f_pRbuf) {
992 if (0 != munmap(f_pRbuf, f_uiRbufSize)) {
993 l_eStatus = eFrameworkunifiedStatusFail;
996 l_eStatus = eFrameworkunifiedStatusNullPointer;
1003 //void CNSRingBuffer::LockMtx() {
1004 // if (m_lid == -1) {
1005 // pthread_mutex_lock(&m_pRbufMtx->m_tBufMutex);
1007 // CL_LockGet(m_pLockAddr);
1010 int CNSRingBuffer::LockMtx() {
1014 ret = pthread_mutex_lock(&m_pRbufMtx->m_tBufMutex);
1016 ret = CL_LockGet(m_pLockAddr);
1023 void CNSRingBuffer::UnlockMtx() {
1025 pthread_mutex_unlock(&m_pRbufMtx->m_tBufMutex);
1027 CL_LockRelease(m_pLockAddr);