1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: Project independend shared buffer (linear + circular)
8 Description: Implementation of platform independend part for the
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
20 2. Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in the
22 documentation and/or other materials provided with the distribution.
24 3. Neither the name of SYSTEC electronic GmbH nor the names of its
25 contributors may be used to endorse or promote products derived
26 from this software without prior written permission. For written
27 permission, please contact info@systec-electronic.com.
29 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
32 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
33 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
35 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
36 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
39 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 POSSIBILITY OF SUCH DAMAGE.
44 If a provision of this License is or becomes illegal, invalid or
45 unenforceable in any jurisdiction, that shall not affect:
46 1. the validity or enforceability in that jurisdiction of any other
47 provision of this License; or
48 2. the validity or enforceability in other jurisdictions of that or
49 any other provision of this License.
51 -------------------------------------------------------------------------
53 2006/06/27 -rs: V 1.00 (initial version)
55 ****************************************************************************/
57 #if defined(WIN32) || defined(_WIN32)
74 // MSVC needs to include windows.h at first
75 // the following defines ar necessary for function prototypes for waitable timers
76 #define _WIN32_WINDOWS 0x0401
77 #define _WIN32_WINNT 0x0400
85 #include "SharedBuff.h"
88 // d.k. Linux kernel modules needs other header files for memcpy()
89 #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
90 #include <linux/string.h>
97 /***************************************************************************/
100 /* G L O B A L D E F I N I T I O N S */
103 /***************************************************************************/
105 #if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
107 //---------------------------------------------------------------------------
109 //---------------------------------------------------------------------------
111 //---------------------------------------------------------------------------
112 // Constant definitions
113 //---------------------------------------------------------------------------
115 #define SBC_MAGIC_ID 0x53424323 // magic ID ("SBC#")
116 #define SBL_MAGIC_ID 0x53424C23 // magic ID ("SBL#")
118 //---------------------------------------------------------------------------
120 //---------------------------------------------------------------------------
122 // structure to administrate circular shared buffer head
124 unsigned long m_ShbCirMagicID; // magic ID ("SBC#")
125 unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
126 unsigned long m_ulBufferDataSize; // size of complete data area
127 unsigned long m_ulWrIndex; // current write index (set bevore write)
128 unsigned long m_ulRdIndex; // current read index (set after read)
129 unsigned long m_ulNumOfWriteJobs; // number of currently (parallel running) write operations
130 unsigned long m_ulDataInUse; // currently used buffer size (incl. uncompleted write operations)
131 unsigned long m_ulDataApended; // buffer size of complete new written but not yet readable data (in case of m_ulNumOfWriteJobs>1)
132 unsigned long m_ulBlocksApended; // number of complete new written but not yet readable data blocks (in case of m_ulNumOfWriteJobs>1)
133 unsigned long m_ulDataReadable; // buffer size with readable (complete written) data
134 unsigned long m_ulBlocksReadable; // number of readable (complete written) data blocks
135 tShbCirSigHndlrNewData m_pfnSigHndlrNewData; // application handler to signal new data
136 unsigned int m_fBufferLocked; // TRUE if buffer is locked (because of pending reset request)
137 tShbCirSigHndlrReset m_pfnSigHndlrReset; // application handler to signal buffer reset is done
138 unsigned char m_Data; // start of data area (the real data size is unknown at this time)
142 // structure to administrate linear shared buffer head
144 unsigned int m_ShbLinMagicID; // magic ID ("SBL#")
145 unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
146 unsigned long m_ulBufferDataSize; // size of complete data area
147 unsigned char m_Data; // start of data area (the real data size is unknown at this time)
151 // type to save size of a single data block inside the circular shared buffer
153 unsigned int m_uiFullBlockSize:28; // a single block must not exceed a length of 256MByte :-)
154 unsigned int m_uiAlignFillBytes:4;
158 #define SBC_BLOCK_ALIGNMENT 4 // alignment must *not* be lower than sizeof(tShbCirBlockSize)!
159 #define SBC_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
161 #define SBL_BLOCK_ALIGNMENT 4
162 #define SBL_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
164 //---------------------------------------------------------------------------
166 //---------------------------------------------------------------------------
168 //---------------------------------------------------------------------------
170 //---------------------------------------------------------------------------
172 //---------------------------------------------------------------------------
173 // Prototypes of internal functions
174 //---------------------------------------------------------------------------
176 //---------------------------------------------------------------------------
177 // Get pointer to Circular Shared Buffer
178 //---------------------------------------------------------------------------
180 INLINE_FUNCTION tShbCirBuff *ShbCirGetBuffer(tShbInstance pShbInstance_p)
183 tShbCirBuff *pShbCirBuff;
185 pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
186 ASSERT(pShbCirBuff->m_ShbCirMagicID == SBC_MAGIC_ID);
188 return (pShbCirBuff);
192 //---------------------------------------------------------------------------
193 // Get pointer to Linear Shared Buffer
194 //---------------------------------------------------------------------------
196 INLINE_FUNCTION tShbLinBuff *ShbLinGetBuffer(tShbInstance pShbInstance_p)
199 tShbLinBuff *pShbLinBuff;
201 pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
202 ASSERT(pShbLinBuff->m_ShbLinMagicID == SBL_MAGIC_ID);
204 return (pShbLinBuff);
208 // not inlined internal functions
209 int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p);
210 void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
211 unsigned int fTimeOut_p);
215 //=========================================================================//
217 // P U B L I C F U N C T I O N S //
219 //=========================================================================//
221 #if !defined(INLINE_ENABLED)
222 // not inlined external functions
224 //---------------------------------------------------------------------------
225 // Initialize Shared Buffer Module
226 //---------------------------------------------------------------------------
228 tShbError ShbInit(void)
233 ShbError = ShbIpcInit();
239 //---------------------------------------------------------------------------
240 // Deinitialize Shared Buffer Module
241 //---------------------------------------------------------------------------
243 tShbError ShbExit(void)
248 ShbError = ShbIpcExit();
254 //-------------------------------------------------------------------------//
256 // C i r c u l a r S h a r e d B u f f e r //
258 //-------------------------------------------------------------------------//
260 //---------------------------------------------------------------------------
261 // Allocate Circular Shared Buffer
262 //---------------------------------------------------------------------------
264 tShbError ShbCirAllocBuffer(unsigned long ulBufferSize_p,
265 const char *pszBufferID_p,
266 tShbInstance * ppShbInstance_p,
267 unsigned int *pfShbNewCreated_p)
270 tShbInstance pShbInstance;
271 tShbCirBuff *pShbCirBuff;
272 unsigned int fShbNewCreated;
273 unsigned long ulBufferDataSize;
274 unsigned long ulBufferTotalSize;
278 if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
279 return (kShbInvalidArg);
282 // calculate length of memory to allocate
285 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
286 ulBufferTotalSize = ulBufferDataSize + sizeof(tShbCirBuff);
288 // allocate a new or open an existing shared buffer
289 ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
290 &pShbInstance, &fShbNewCreated);
291 if (ShbError != kShbOk) {
295 if (pShbInstance == NULL) {
296 ShbError = kShbOutOfMem;
300 // get pointer to shared buffer
301 pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance);
303 // if the shared buffer was new created, than this process has
304 // to initialize it, otherwise the buffer is already in use
305 // and *must not* be reseted
306 if (fShbNewCreated) {
309 memset(pShbCirBuff, 0xCC, ulBufferTotalSize);
313 pShbCirBuff->m_ShbCirMagicID = SBC_MAGIC_ID;
314 pShbCirBuff->m_ulBufferTotalSize = ulBufferTotalSize;
315 pShbCirBuff->m_ulBufferDataSize = ulBufferDataSize;
316 pShbCirBuff->m_ulWrIndex = 0;
317 pShbCirBuff->m_ulRdIndex = 0;
318 pShbCirBuff->m_ulNumOfWriteJobs = 0;
319 pShbCirBuff->m_ulDataInUse = 0;
320 pShbCirBuff->m_ulDataApended = 0;
321 pShbCirBuff->m_ulBlocksApended = 0;
322 pShbCirBuff->m_ulDataReadable = 0;
323 pShbCirBuff->m_ulBlocksReadable = 0;
324 pShbCirBuff->m_pfnSigHndlrNewData = NULL;
325 pShbCirBuff->m_fBufferLocked = FALSE;
326 pShbCirBuff->m_pfnSigHndlrReset = NULL;
328 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
329 ShbError = kShbInvalidBufferType;
336 *ppShbInstance_p = pShbInstance;
337 *pfShbNewCreated_p = fShbNewCreated;
343 //---------------------------------------------------------------------------
344 // Release Circular Shared Buffer
345 //---------------------------------------------------------------------------
347 tShbError ShbCirReleaseBuffer(tShbInstance pShbInstance_p)
353 if (pShbInstance_p == NULL) {
358 ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
366 #endif // !defined(INLINE_ENABLED)
368 #if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
370 //---------------------------------------------------------------------------
371 // Reset Circular Shared Buffer
372 //---------------------------------------------------------------------------
374 INLINE_FUNCTION tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p,
375 unsigned long ulTimeOut_p,
377 pfnSignalHandlerReset_p)
380 tShbCirBuff *pShbCirBuff;
381 unsigned long ulNumOfWriteJobs = 0; // d.k. GCC complains about uninitialized variable otherwise
385 if (pShbInstance_p == NULL) {
386 ShbError = kShbInvalidArg;
390 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
393 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
394 ShbError = kShbInvalidBufferType;
398 // start reset job by setting request request in buffer header
399 ShbIpcEnterAtomicSection(pShbInstance_p);
401 if (!pShbCirBuff->m_fBufferLocked) {
402 ulNumOfWriteJobs = pShbCirBuff->m_ulNumOfWriteJobs;
404 pShbCirBuff->m_fBufferLocked = TRUE;
405 pShbCirBuff->m_pfnSigHndlrReset =
406 pfnSignalHandlerReset_p;
408 ShbError = kShbAlreadyReseting;
411 ShbIpcLeaveAtomicSection(pShbInstance_p);
413 if (ShbError != kShbOk) {
417 // if there is currently no running write operation then reset buffer
418 // immediately, otherwise wait until the last write job is ready by
419 // starting a signal process
420 if (ulNumOfWriteJobs == 0) {
421 // there is currently no running write operation
422 // -> reset buffer immediately
423 ShbCirSignalHandlerReset(pShbInstance_p, FALSE);
426 // there is currently at least one running write operation
427 // -> starting signal process to wait until the last write job is ready
429 ShbIpcStartSignalingJobReady(pShbInstance_p, ulTimeOut_p,
430 ShbCirSignalHandlerReset);
439 //---------------------------------------------------------------------------
440 // Write data block to Circular Shared Buffer
441 //---------------------------------------------------------------------------
443 INLINE_FUNCTION tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p,
444 const void *pSrcDataBlock_p,
445 unsigned long ulDataBlockSize_p)
448 tShbCirBuff *pShbCirBuff;
449 tShbCirBlockSize ShbCirBlockSize;
450 unsigned int uiFullBlockSize;
451 unsigned int uiAlignFillBytes;
452 unsigned char *pShbCirDataPtr;
453 unsigned char *pScrDataPtr;
454 unsigned long ulDataSize;
455 unsigned long ulChunkSize;
456 unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
457 unsigned int fSignalNewData;
458 unsigned int fSignalReset;
464 if (pShbInstance_p == NULL) {
465 ShbError = kShbInvalidArg;
469 if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
470 // nothing to do here
475 if (ulDataBlockSize_p > SBC_MAX_BLOCK_SIZE) {
476 ShbError = kShbExceedDataSizeLimit;
480 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
481 pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
482 fSignalNewData = FALSE;
483 fSignalReset = FALSE;
486 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
487 ShbError = kShbInvalidBufferType;
491 // calculate data block size in circular buffer
494 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
495 uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
496 uiAlignFillBytes = ulDataSize - ulDataBlockSize_p;
498 ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
499 ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
501 // reserve the needed memory for the write operation to do now
502 // and make necessary adjustments in the circular buffer header
503 ShbIpcEnterAtomicSection(pShbInstance_p);
505 // check if there is sufficient memory available to store
509 (pShbCirBuff->m_ulBufferDataSize -
510 pShbCirBuff->m_ulDataInUse);
512 // set write pointer for the write operation to do now
513 // to the current write pointer of the circular buffer
514 ulWrIndex = pShbCirBuff->m_ulWrIndex;
516 // reserve the needed memory for the write operation to do now
517 pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
519 // set new write pointer behind the reserved memory
520 // for the write operation to do now
521 pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
522 pShbCirBuff->m_ulWrIndex %=
523 pShbCirBuff->m_ulBufferDataSize;
525 // increment number of currently (parallel running)
527 pShbCirBuff->m_ulNumOfWriteJobs++;
530 ShbIpcLeaveAtomicSection(pShbInstance_p);
533 ShbError = kShbBufferFull;
537 // copy the data to the circular buffer
538 // (the copy process itself will be done outside of any
539 // critical/locked section)
540 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
542 // write real size of current block (incl. alignment fill bytes)
543 *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
544 ulWrIndex += sizeof(tShbCirBlockSize);
545 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
547 if (ulWrIndex + ulDataBlockSize_p <= pShbCirBuff->m_ulBufferDataSize) {
548 // linear write operation
549 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
552 // wrap-around write operation
553 ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
554 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulChunkSize);
555 memcpy(pShbCirDataPtr, pScrDataPtr + ulChunkSize,
556 ulDataBlockSize_p - ulChunkSize);
559 // adjust header information for circular buffer with properties
560 // of the wiritten data block
561 ShbIpcEnterAtomicSection(pShbInstance_p);
563 pShbCirBuff->m_ulDataApended += uiFullBlockSize;
564 pShbCirBuff->m_ulBlocksApended++;
566 // decrement number of currently (parallel running) write operations
567 if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
568 // if there is no other write process running then
569 // set new size of readable (complete written) data and
570 // adjust number of readable blocks
571 pShbCirBuff->m_ulDataReadable +=
572 pShbCirBuff->m_ulDataApended;
573 pShbCirBuff->m_ulBlocksReadable +=
574 pShbCirBuff->m_ulBlocksApended;
576 pShbCirBuff->m_ulDataApended = 0;
577 pShbCirBuff->m_ulBlocksApended = 0;
579 fSignalNewData = TRUE;
580 fSignalReset = pShbCirBuff->m_fBufferLocked;
583 ShbIpcLeaveAtomicSection(pShbInstance_p);
585 // signal new data event to a potentially reading application
586 if (fSignalNewData) {
587 ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
588 if (ShbError == kShbOk) {
589 ShbError = ShbError2;
592 // signal that the last write job has been finished to allow
593 // a waiting application to reset the buffer now
595 ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
596 if (ShbError == kShbOk) {
597 ShbError = ShbError2;
607 //---------------------------------------------------------------------------
608 // Allocate block within the Circular Shared Buffer for chunk writing
609 //---------------------------------------------------------------------------
611 INLINE_FUNCTION tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p,
612 tShbCirChunk * pShbCirChunk_p,
613 unsigned long ulDataBufferSize_p)
616 tShbCirBuff *pShbCirBuff;
617 tShbCirBlockSize ShbCirBlockSize;
618 unsigned int uiFullBlockSize;
619 unsigned int uiAlignFillBytes;
620 unsigned char *pShbCirDataPtr;
621 unsigned long ulDataSize;
622 unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
627 if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)) {
628 ShbError = kShbInvalidArg;
632 if (ulDataBufferSize_p == 0) {
633 ShbError = kShbInvalidArg;
637 if (ulDataBufferSize_p > SBC_MAX_BLOCK_SIZE) {
638 ShbError = kShbExceedDataSizeLimit;
642 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
645 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
646 ShbError = kShbInvalidBufferType;
650 // calculate data block size in circular buffer
652 (ulDataBufferSize_p +
653 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
654 uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
655 uiAlignFillBytes = ulDataSize - ulDataBufferSize_p;
657 ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
658 ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
660 // reserve the needed memory for the write operation to do now
661 // and make necessary adjustments in the circular buffer header
662 ShbIpcEnterAtomicSection(pShbInstance_p);
664 // check if there is sufficient memory available to store
668 (pShbCirBuff->m_ulBufferDataSize -
669 pShbCirBuff->m_ulDataInUse));
671 // set write pointer for the write operation to do now
672 // to the current write pointer of the circular buffer
673 ulWrIndex = pShbCirBuff->m_ulWrIndex;
675 // reserve the needed memory for the write operation to do now
676 pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
678 // set new write pointer behind the reserved memory
679 // for the write operation to do now
680 pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
681 pShbCirBuff->m_ulWrIndex %=
682 pShbCirBuff->m_ulBufferDataSize;
684 // increment number of currently (parallel running)
686 pShbCirBuff->m_ulNumOfWriteJobs++;
689 ShbIpcLeaveAtomicSection(pShbInstance_p);
692 ShbError = kShbBufferFull;
696 // setup header information for allocated buffer
697 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
699 // write real size of current block (incl. alignment fill bytes)
700 *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
701 ulWrIndex += sizeof(tShbCirBlockSize);
702 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
704 // setup chunk descriptor
705 pShbCirChunk_p->m_uiFullBlockSize = uiFullBlockSize;
706 pShbCirChunk_p->m_ulAvailableSize = ulDataBufferSize_p;
707 pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
708 pShbCirChunk_p->m_fBufferCompleted = FALSE;
716 //---------------------------------------------------------------------------
717 // Write data chunk into an allocated buffer of the Circular Shared Buffer
718 //---------------------------------------------------------------------------
720 INLINE_FUNCTION tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p,
721 tShbCirChunk * pShbCirChunk_p,
722 const void *pSrcDataChunk_p,
723 unsigned long ulDataChunkSize_p,
725 *pfBufferCompleted_p)
728 tShbCirBuff *pShbCirBuff;
729 unsigned char *pShbCirDataPtr;
730 unsigned char *pScrDataPtr;
731 unsigned long ulSubChunkSize;
732 unsigned long ulWrIndex;
733 unsigned int fBufferCompleted;
734 unsigned int fSignalNewData;
735 unsigned int fSignalReset;
740 if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)
741 || (pfBufferCompleted_p == NULL)) {
742 ShbError = kShbInvalidArg;
746 if ((pSrcDataChunk_p == NULL) || (ulDataChunkSize_p == 0)) {
747 // nothing to do here
752 if (pShbCirChunk_p->m_fBufferCompleted) {
753 ShbError = kShbBufferAlreadyCompleted;
757 if (ulDataChunkSize_p > pShbCirChunk_p->m_ulAvailableSize) {
758 ShbError = kShbExceedDataSizeLimit;
762 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
763 pScrDataPtr = (unsigned char *)pSrcDataChunk_p;
764 fSignalNewData = FALSE;
765 fSignalReset = FALSE;
768 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
769 ShbError = kShbInvalidBufferType;
773 ulWrIndex = pShbCirChunk_p->m_ulWrIndex;
775 // copy the data to the circular buffer
776 // (the copy process itself will be done outside of any
777 // critical/locked section)
778 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
780 if (ulWrIndex + ulDataChunkSize_p <= pShbCirBuff->m_ulBufferDataSize) {
781 // linear write operation
782 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
785 // wrap-around write operation
786 ulSubChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
787 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulSubChunkSize);
788 memcpy(pShbCirDataPtr, pScrDataPtr + ulSubChunkSize,
789 ulDataChunkSize_p - ulSubChunkSize);
792 // adjust chunk descriptor
793 ulWrIndex += ulDataChunkSize_p;
794 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
796 pShbCirChunk_p->m_ulAvailableSize -= ulDataChunkSize_p;
797 pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
799 fBufferCompleted = (pShbCirChunk_p->m_ulAvailableSize == 0);
800 pShbCirChunk_p->m_fBufferCompleted = fBufferCompleted;
802 // if the complete allocated buffer is filled with data then
803 // adjust header information for circular buffer with properties
804 // of the wiritten data block
805 if (fBufferCompleted) {
806 ShbIpcEnterAtomicSection(pShbInstance_p);
808 pShbCirBuff->m_ulDataApended +=
809 pShbCirChunk_p->m_uiFullBlockSize;
810 pShbCirBuff->m_ulBlocksApended++;
812 // decrement number of currently (parallel running) write operations
813 if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
814 // if there is no other write process running then
815 // set new size of readable (complete written) data and
816 // adjust number of readable blocks
817 pShbCirBuff->m_ulDataReadable +=
818 pShbCirBuff->m_ulDataApended;
819 pShbCirBuff->m_ulBlocksReadable +=
820 pShbCirBuff->m_ulBlocksApended;
822 pShbCirBuff->m_ulDataApended = 0;
823 pShbCirBuff->m_ulBlocksApended = 0;
825 fSignalNewData = TRUE;
826 fSignalReset = pShbCirBuff->m_fBufferLocked;
829 ShbIpcLeaveAtomicSection(pShbInstance_p);
832 // signal new data event to a potentially reading application
833 if (fSignalNewData) {
834 ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
835 if (ShbError == kShbOk) {
836 ShbError = ShbError2;
839 // signal that the last write job has been finished to allow
840 // a waiting application to reset the buffer now
842 ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
843 if (ShbError == kShbOk) {
844 ShbError = ShbError2;
848 *pfBufferCompleted_p = fBufferCompleted;
856 //---------------------------------------------------------------------------
857 // Read data block from Circular Shared Buffer
858 //---------------------------------------------------------------------------
860 INLINE_FUNCTION tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p,
861 void *pDstDataBlock_p,
862 unsigned long ulRdBuffSize_p,
863 unsigned long *pulDataBlockSize_p)
866 tShbCirBuff *pShbCirBuff;
867 tShbCirBlockSize ShbCirBlockSize;
868 unsigned long ulDataReadable;
869 unsigned char *pShbCirDataPtr;
870 unsigned char *pDstDataPtr;
871 unsigned long ulDataSize = 0; // d.k. GCC complains about uninitialized variable otherwise
872 unsigned long ulChunkSize;
873 unsigned long ulRdIndex;
877 if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
878 return (kShbInvalidArg);
881 if ((pDstDataBlock_p == NULL) || (ulRdBuffSize_p == 0)) {
882 // nothing to do here
888 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
889 pDstDataPtr = (unsigned char *)pDstDataBlock_p;
892 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
893 ShbError = kShbInvalidBufferType;
897 // get total number of readable bytes for the whole circular buffer
898 ShbIpcEnterAtomicSection(pShbInstance_p);
900 ulDataReadable = pShbCirBuff->m_ulDataReadable;
902 ShbIpcLeaveAtomicSection(pShbInstance_p);
904 // if there are readable data available, then there must be at least
905 // one complete readable data block
906 if (ulDataReadable > 0) {
907 // get pointer to start of data area and current read index
908 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
909 ulRdIndex = pShbCirBuff->m_ulRdIndex;
911 // get real size of current block (incl. alignment fill bytes)
913 *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
914 ulRdIndex += sizeof(tShbCirBlockSize);
915 ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
917 // get size of user data inside the current block
919 ShbCirBlockSize.m_uiFullBlockSize -
920 ShbCirBlockSize.m_uiAlignFillBytes;
921 ulDataSize -= sizeof(tShbCirBlockSize);
924 // ulDataSize = MIN(ulDataSize, ulRdBuffSize_p);
925 if (ulDataSize > ulRdBuffSize_p) {
926 ulDataSize = ulRdBuffSize_p;
927 ShbError = kShbDataTruncated;
930 if (ulDataSize == 0) {
931 // nothing to do here
932 ShbError = kShbNoReadableData;
936 // copy the data from the circular buffer
937 // (the copy process itself will be done outside of any
938 // critical/locked section)
939 if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
940 // linear read operation
941 memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulDataSize);
943 // wrap-around read operation
944 ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
945 memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulChunkSize);
946 memcpy(pDstDataPtr + ulChunkSize, pShbCirDataPtr,
947 ulDataSize - ulChunkSize);
952 tShbCirBlockSize ClrShbCirBlockSize;
954 if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
956 memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulDataSize);
958 // wrap-around read operation
960 pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
961 memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulChunkSize);
962 memset(pShbCirDataPtr, 0xDD, ulDataSize - ulChunkSize);
965 ClrShbCirBlockSize.m_uiFullBlockSize = /*(unsigned int) */ -1; // -1 = xFFFFFFF
966 ClrShbCirBlockSize.m_uiAlignFillBytes = /*(unsigned int) */ -1; // -1 = Fxxxxxxx
967 *(tShbCirBlockSize *) (pShbCirDataPtr +
968 pShbCirBuff->m_ulRdIndex) =
971 #endif // #ifndef NDEBUG
973 // set new size of readable data, data in use, new read index
974 // and adjust number of readable blocks
975 ShbIpcEnterAtomicSection(pShbInstance_p);
977 pShbCirBuff->m_ulDataInUse -= ShbCirBlockSize.m_uiFullBlockSize;
978 pShbCirBuff->m_ulDataReadable -=
979 ShbCirBlockSize.m_uiFullBlockSize;
980 pShbCirBuff->m_ulBlocksReadable--;
982 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
983 if ((pShbCirBuff->m_ulDataInUse == 0)
984 && (pShbCirBuff->m_ulDataReadable == 0)) {
985 ASSERT(pShbCirBuff->m_ulBlocksReadable == 0);
987 pShbCirBuff->m_ulWrIndex = 0;
988 pShbCirBuff->m_ulRdIndex = 0;
990 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
992 pShbCirBuff->m_ulRdIndex +=
993 ShbCirBlockSize.m_uiFullBlockSize;
994 pShbCirBuff->m_ulRdIndex %=
995 pShbCirBuff->m_ulBufferDataSize;
998 ShbIpcLeaveAtomicSection(pShbInstance_p);
1002 *pulDataBlockSize_p = ulDataSize;
1008 //---------------------------------------------------------------------------
1009 // Get data size of next readable block from Circular Shared Buffer
1010 //---------------------------------------------------------------------------
1012 INLINE_FUNCTION tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p,
1014 *pulDataBlockSize_p)
1017 tShbCirBuff *pShbCirBuff;
1018 unsigned long ulDataReadable;
1019 unsigned char *pShbCirDataPtr;
1020 tShbCirBlockSize ShbCirBlockSize;
1021 unsigned long ulDataSize;
1025 if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
1026 return (kShbInvalidArg);
1029 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1033 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1034 ShbError = kShbInvalidBufferType;
1038 // get total number of readable bytes for the whole circular buffer
1039 ShbIpcEnterAtomicSection(pShbInstance_p);
1041 ulDataReadable = pShbCirBuff->m_ulDataReadable;
1043 ShbIpcLeaveAtomicSection(pShbInstance_p);
1045 // if there are readable data available, then there must be at least
1046 // one complete readable data block
1047 if (ulDataReadable > 0) {
1049 &pShbCirBuff->m_Data + pShbCirBuff->m_ulRdIndex;
1051 // get real size of current block (incl. alignment fill bytes)
1052 ShbCirBlockSize = *(tShbCirBlockSize *) pShbCirDataPtr;
1054 // get size of user data inside the current block
1056 ShbCirBlockSize.m_uiFullBlockSize -
1057 ShbCirBlockSize.m_uiAlignFillBytes;
1058 ulDataSize -= sizeof(tShbCirBlockSize);
1063 *pulDataBlockSize_p = ulDataSize;
1069 //---------------------------------------------------------------------------
1070 // Get number of readable blocks from Circular Shared Buffer
1071 //---------------------------------------------------------------------------
1073 INLINE_FUNCTION tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p,
1075 *pulDataBlockCount_p)
1078 tShbCirBuff *pShbCirBuff;
1079 unsigned long ulBlockCount;
1083 if ((pShbInstance_p == NULL) || (pulDataBlockCount_p == NULL)) {
1084 ShbError = kShbInvalidArg;
1088 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1092 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1093 ShbError = kShbInvalidBufferType;
1097 ShbIpcEnterAtomicSection(pShbInstance_p);
1099 ulBlockCount = pShbCirBuff->m_ulBlocksReadable;
1101 ShbIpcLeaveAtomicSection(pShbInstance_p);
1103 *pulDataBlockCount_p = ulBlockCount;
1111 //---------------------------------------------------------------------------
1112 // Set application handler to signal new data for Circular Shared Buffer
1113 // d.k.: new parameter priority as enum
1114 //---------------------------------------------------------------------------
1116 INLINE_FUNCTION tShbError ShbCirSetSignalHandlerNewData(tShbInstance
1118 tShbCirSigHndlrNewData
1119 pfnSignalHandlerNewData_p,
1124 tShbCirBuff *pShbCirBuff;
1128 if (pShbInstance_p == NULL) {
1129 ShbError = kShbInvalidArg;
1133 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1136 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1137 ShbError = kShbInvalidBufferType;
1141 if (pfnSignalHandlerNewData_p != NULL) {
1142 // set a new signal handler
1143 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1144 ShbError = kShbAlreadySignaling;
1148 pShbCirBuff->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
1150 ShbIpcStartSignalingNewData(pShbInstance_p,
1151 ShbCirSignalHandlerNewData,
1154 // remove existing signal handler
1155 ShbError = ShbIpcStopSignalingNewData(pShbInstance_p);
1156 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1157 pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p, 0);
1159 pShbCirBuff->m_pfnSigHndlrNewData = NULL;
1170 #if !defined(INLINE_ENABLED)
1172 //---------------------------------------------------------------------------
1173 // DEBUG: Trace Circular Shared Buffer
1174 //---------------------------------------------------------------------------
1177 tShbError ShbCirTraceBuffer(tShbInstance pShbInstance_p)
1180 tShbCirBuff *pShbCirBuff;
1181 char szMagigID[sizeof(SBC_MAGIC_ID) + 1];
1182 tShbCirBlockSize ShbCirBlockSize;
1183 unsigned long ulDataReadable;
1184 unsigned char *pShbCirDataPtr;
1185 unsigned long ulBlockIndex;
1186 unsigned int nBlockCount;
1187 unsigned long ulDataSize;
1188 unsigned long ulChunkSize;
1189 unsigned long ulRdIndex;
1192 TRACE0("\n\n##### Circular Shared Buffer #####\n");
1195 if (pShbInstance_p == NULL) {
1196 TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1197 (unsigned long)pShbInstance_p);
1198 ShbError = kShbInvalidArg;
1202 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1205 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1206 ShbError = kShbInvalidBufferType;
1210 *(unsigned long *)&szMagigID[0] = pShbCirBuff->m_ShbCirMagicID;
1211 szMagigID[sizeof(SBC_MAGIC_ID)] = '\0';
1213 ShbIpcEnterAtomicSection(pShbInstance_p);
1215 TRACE1("\nBuffer Address: 0x%08lX\n",
1216 (unsigned long)pShbCirBuff);
1218 TRACE0("\nHeader Info:");
1219 TRACE2("\nMagigID: '%s' (%08lX)", szMagigID,
1220 pShbCirBuff->m_ShbCirMagicID);
1221 TRACE1("\nBufferTotalSize: %4lu [Bytes]",
1222 pShbCirBuff->m_ulBufferTotalSize);
1223 TRACE1("\nBufferDataSize: %4lu [Bytes]",
1224 pShbCirBuff->m_ulBufferDataSize);
1225 TRACE1("\nWrIndex: %4lu", pShbCirBuff->m_ulWrIndex);
1226 TRACE1("\nRdIndex: %4lu", pShbCirBuff->m_ulRdIndex);
1227 TRACE1("\nNumOfWriteJobs: %4lu",
1228 pShbCirBuff->m_ulNumOfWriteJobs);
1229 TRACE1("\nDataInUse: %4lu [Bytes]",
1230 pShbCirBuff->m_ulDataInUse);
1231 TRACE1("\nDataApended: %4lu [Bytes]",
1232 pShbCirBuff->m_ulDataApended);
1233 TRACE1("\nBlocksApended: %4lu",
1234 pShbCirBuff->m_ulBlocksApended);
1235 TRACE1("\nDataReadable: %4lu [Bytes]",
1236 pShbCirBuff->m_ulDataReadable);
1237 TRACE1("\nBlocksReadable: %4lu",
1238 pShbCirBuff->m_ulBlocksReadable);
1239 TRACE1("\nSigHndlrNewData: %08lX",
1240 (unsigned long)pShbCirBuff->m_pfnSigHndlrNewData);
1241 TRACE1("\nBufferLocked: %d", pShbCirBuff->m_fBufferLocked);
1242 TRACE1("\nSigHndlrReset: %08lX",
1243 (unsigned long)pShbCirBuff->m_pfnSigHndlrReset);
1245 ShbTraceDump(&pShbCirBuff->m_Data,
1246 pShbCirBuff->m_ulBufferDataSize, 0x00000000L,
1249 ulDataReadable = pShbCirBuff->m_ulDataReadable;
1251 ulBlockIndex = pShbCirBuff->m_ulRdIndex;
1253 while (ulDataReadable > 0) {
1254 TRACE1("\n\n--- Block #%u ---", nBlockCount);
1256 // get pointer to start of data area and current read index
1257 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
1258 ulRdIndex = ulBlockIndex;
1260 // get real size of current block (incl. alignment fill bytes)
1262 *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
1263 ulRdIndex += sizeof(tShbCirBlockSize);
1264 ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
1266 // get size of user data inside the current block
1268 ShbCirBlockSize.m_uiFullBlockSize -
1269 ShbCirBlockSize.m_uiAlignFillBytes;
1270 ulDataSize -= sizeof(tShbCirBlockSize);
1273 ("\nFull Data Size: %4u [Bytes] (incl. header and alignment fill bytes)",
1274 ShbCirBlockSize.m_uiFullBlockSize);
1275 TRACE1("\nUser Data Size: %4lu [Bytes]",
1277 TRACE1("\nAlignment Fill Bytes: %4u [Bytes]",
1278 ShbCirBlockSize.m_uiAlignFillBytes);
1280 if (ulRdIndex + ulDataSize <=
1281 pShbCirBuff->m_ulBufferDataSize) {
1282 // linear data buffer
1283 ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1284 ulDataSize, 0x00000000L, NULL);
1286 // wrap-around data buffer
1288 pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
1289 ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1290 ulChunkSize, 0x00000000L, NULL);
1291 ShbTraceDump(pShbCirDataPtr,
1292 ulDataSize - ulChunkSize,
1298 ulBlockIndex += ShbCirBlockSize.m_uiFullBlockSize;
1299 ulBlockIndex %= pShbCirBuff->m_ulBufferDataSize;
1301 ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
1304 ASSERT(pShbCirBuff->m_ulBlocksReadable == nBlockCount - 1);
1306 ShbIpcLeaveAtomicSection(pShbInstance_p);
1315 //-------------------------------------------------------------------------//
1317 // L i n e a r S h a r e d B u f f e r //
1319 //-------------------------------------------------------------------------//
1321 //---------------------------------------------------------------------------
1322 // Allocate Linear Shared Buffer
1323 //---------------------------------------------------------------------------
1325 tShbError ShbLinAllocBuffer(unsigned long ulBufferSize_p,
1326 const char *pszBufferID_p,
1327 tShbInstance * ppShbInstance_p,
1328 unsigned int *pfShbNewCreated_p)
1331 tShbInstance pShbInstance;
1332 tShbLinBuff *pShbLinBuff;
1333 unsigned int fShbNewCreated;
1334 unsigned long ulBufferDataSize;
1335 unsigned long ulBufferTotalSize;
1339 if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
1340 return (kShbInvalidArg);
1343 // calculate length of memory to allocate
1346 (SBL_BLOCK_ALIGNMENT - 1)) & ~(SBL_BLOCK_ALIGNMENT - 1);
1347 ulBufferTotalSize = ulBufferDataSize + sizeof(tShbLinBuff);
1349 // allocate a new or open an existing shared buffer
1350 ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
1351 &pShbInstance, &fShbNewCreated);
1352 if (ShbError != kShbOk) {
1356 if (pShbInstance == NULL) {
1357 ShbError = kShbOutOfMem;
1361 // get pointer to shared buffer
1362 pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance);
1364 // if the shared buffer was new created, than this process has
1365 // to initialize it, otherwise the buffer is already in use
1366 // and *must not* be reseted
1367 if (fShbNewCreated) {
1370 memset(pShbLinBuff, 0xCC, ulBufferTotalSize);
1374 pShbLinBuff->m_ShbLinMagicID = SBL_MAGIC_ID;
1375 pShbLinBuff->m_ulBufferTotalSize = ulBufferTotalSize;
1376 pShbLinBuff->m_ulBufferDataSize = ulBufferDataSize;
1378 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1379 ShbError = kShbInvalidBufferType;
1386 *ppShbInstance_p = pShbInstance;
1387 *pfShbNewCreated_p = fShbNewCreated;
1393 //---------------------------------------------------------------------------
1394 // Release Linear Shared Buffer
1395 //---------------------------------------------------------------------------
1397 tShbError ShbLinReleaseBuffer(tShbInstance pShbInstance_p)
1403 if (pShbInstance_p == NULL) {
1408 ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
1416 #endif // !defined(INLINE_ENABLED)
1418 #if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
1420 //---------------------------------------------------------------------------
1421 // Write data block to Linear Shared Buffer
1422 //---------------------------------------------------------------------------
1424 INLINE_FUNCTION tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p,
1425 unsigned long ulDstBufferOffs_p,
1426 const void *pSrcDataBlock_p,
1427 unsigned long ulDataBlockSize_p)
1430 tShbLinBuff *pShbLinBuff;
1431 unsigned char *pShbLinDataPtr;
1432 unsigned char *pScrDataPtr;
1433 unsigned long ulBufferDataSize;
1437 if (pShbInstance_p == NULL) {
1438 ShbError = kShbInvalidArg;
1442 if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1443 // nothing to do here
1448 if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1449 ShbError = kShbExceedDataSizeLimit;
1453 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1454 pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
1457 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1458 ShbError = kShbInvalidBufferType;
1462 // check if offeset and size for the write operation matches with
1463 // the size of the shared buffer
1464 ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
1465 if ((ulDstBufferOffs_p > ulBufferDataSize) ||
1466 (ulDataBlockSize_p > ulBufferDataSize) ||
1467 ((ulDstBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
1468 ShbError = kShbDataOutsideBufferArea;
1472 // copy the data to the linear buffer
1473 // (the copy process will be done inside of any critical/locked section)
1474 pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
1475 pShbLinDataPtr += ulDstBufferOffs_p;
1477 ShbIpcEnterAtomicSection(pShbInstance_p);
1479 memcpy(pShbLinDataPtr, pScrDataPtr, ulDataBlockSize_p);
1481 ShbIpcLeaveAtomicSection(pShbInstance_p);
1489 //---------------------------------------------------------------------------
1490 // Read data block from Linear Shared Buffer
1491 //---------------------------------------------------------------------------
1493 INLINE_FUNCTION tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p,
1494 void *pDstDataBlock_p,
1495 unsigned long ulSrcBufferOffs_p,
1496 unsigned long ulDataBlockSize_p)
1499 tShbLinBuff *pShbLinBuff;
1500 unsigned char *pShbLinDataPtr;
1501 unsigned char *pDstDataPtr;
1502 unsigned long ulBufferDataSize;
1506 if (pShbInstance_p == NULL) {
1507 ShbError = kShbInvalidArg;
1511 if ((pDstDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1512 // nothing to do here
1517 if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1518 ShbError = kShbExceedDataSizeLimit;
1522 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1523 pDstDataPtr = (unsigned char *)pDstDataBlock_p;
1526 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1527 ShbError = kShbInvalidBufferType;
1531 // check if offeset and size for the read operation matches with
1532 // the size of the shared buffer
1533 ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
1534 if ((ulSrcBufferOffs_p > ulBufferDataSize) ||
1535 (ulDataBlockSize_p > ulBufferDataSize) ||
1536 ((ulSrcBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
1537 ShbError = kShbDataOutsideBufferArea;
1541 // copy the data to the linear buffer
1542 // (the copy process will be done inside of any critical/locked section)
1543 pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
1544 pShbLinDataPtr += ulSrcBufferOffs_p;
1546 ShbIpcEnterAtomicSection(pShbInstance_p);
1548 memcpy(pDstDataPtr, pShbLinDataPtr, ulDataBlockSize_p);
1550 ShbIpcLeaveAtomicSection(pShbInstance_p);
1560 #if !defined(INLINE_ENABLED)
1562 //---------------------------------------------------------------------------
1563 // DEBUG: Trace Linear Shared Buffer
1564 //---------------------------------------------------------------------------
1567 tShbError ShbLinTraceBuffer(tShbInstance pShbInstance_p)
1570 tShbLinBuff *pShbLinBuff;
1571 char szMagigID[sizeof(SBL_MAGIC_ID) + 1];
1574 TRACE0("\n\n##### Linear Shared Buffer #####\n");
1577 if (pShbInstance_p == NULL) {
1578 TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1579 (unsigned long)pShbInstance_p);
1580 ShbError = kShbInvalidArg;
1584 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1587 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1588 ShbError = kShbInvalidBufferType;
1592 *(unsigned int *)&szMagigID[0] = pShbLinBuff->m_ShbLinMagicID;
1593 szMagigID[sizeof(SBL_MAGIC_ID)] = '\0';
1595 ShbIpcEnterAtomicSection(pShbInstance_p);
1597 TRACE1("\nBuffer Address: 0x%08lX\n",
1598 (unsigned long)pShbLinBuff);
1600 TRACE0("\nHeader Info:");
1601 TRACE2("\nMagigID: '%s' (%08X)", szMagigID,
1602 pShbLinBuff->m_ShbLinMagicID);
1603 TRACE1("\nBufferTotalSize: %4lu [Bytes]",
1604 pShbLinBuff->m_ulBufferTotalSize);
1605 TRACE1("\nBufferDataSize: %4lu [Bytes]",
1606 pShbLinBuff->m_ulBufferDataSize);
1608 ShbTraceDump(&pShbLinBuff->m_Data,
1609 pShbLinBuff->m_ulBufferDataSize, 0x00000000L,
1612 ShbIpcLeaveAtomicSection(pShbInstance_p);
1621 //---------------------------------------------------------------------------
1622 // Dump buffer contents
1623 //---------------------------------------------------------------------------
1626 tShbError ShbTraceDump(const unsigned char *pabStartAddr_p,
1627 unsigned long ulDataSize_p,
1628 unsigned long ulAddrOffset_p, const char *pszInfoText_p)
1631 const unsigned char *pabBuffData;
1632 unsigned long ulBuffSize;
1633 unsigned char bData;
1637 // get pointer to buffer and length of buffer
1638 pabBuffData = pabStartAddr_p;
1639 ulBuffSize = ulDataSize_p;
1641 if (pszInfoText_p != NULL) {
1642 TRACE0(pszInfoText_p);
1644 // dump buffer contents
1645 for (nRow = 0;; nRow++) {
1647 (unsigned long)(nRow * 0x10) + ulAddrOffset_p);
1649 for (nCol = 0; nCol < 16; nCol++) {
1650 if ((unsigned long)nCol < ulBuffSize) {
1652 (unsigned int)*(pabBuffData + nCol));
1660 for (nCol = 0; nCol < 16; nCol++) {
1661 bData = *pabBuffData++;
1662 if ((unsigned long)nCol < ulBuffSize) {
1663 if ((bData >= 0x20) && (bData < 0x7F)) {
1664 TRACE1("%c", bData);
1673 if (ulBuffSize > 16) {
1683 #endif // #ifndef NDEBUG
1685 //=========================================================================//
1687 // P R I V A T E F U N C T I O N S //
1689 //=========================================================================//
1691 //---------------------------------------------------------------------------
1692 // Handler to signal new data event for Circular Shared Buffer
1693 //---------------------------------------------------------------------------
1695 int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p)
1698 tShbCirBuff *pShbCirBuff;
1699 unsigned long ulDataSize;
1700 unsigned long ulBlockCount;
1704 if (pShbInstance_p == NULL) {
1708 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1711 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1715 // call application handler
1716 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1719 ShbError = ShbCirGetReadDataSize(pShbInstance_p, &ulDataSize);
1720 if ((ulDataSize > 0) && (ShbError == kShbOk)) {
1721 pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p,
1726 ShbCirGetReadBlockCount(pShbInstance_p, &ulBlockCount);
1728 while ((ulBlockCount > 0) && (ShbError == kShbOk));*/
1730 // Return TRUE if there are pending blocks.
1731 // In that case ShbIpc tries to call this function again immediately if there
1732 // is no other filled shared buffer with higher priority.
1733 return ((ulBlockCount > 0) && (ShbError == kShbOk));
1737 //---------------------------------------------------------------------------
1738 // Handler to reset Circular Shared Buffer
1739 //---------------------------------------------------------------------------
1741 void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
1742 unsigned int fTimeOut_p)
1745 tShbCirBuff *pShbCirBuff;
1748 if (pShbInstance_p == NULL) {
1752 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1753 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1757 // reset buffer header
1759 ShbIpcEnterAtomicSection(pShbInstance_p);
1761 pShbCirBuff->m_ulWrIndex = 0;
1762 pShbCirBuff->m_ulRdIndex = 0;
1763 pShbCirBuff->m_ulNumOfWriteJobs = 0;
1764 pShbCirBuff->m_ulDataInUse = 0;
1765 pShbCirBuff->m_ulDataApended = 0;
1766 pShbCirBuff->m_ulBlocksApended = 0;
1767 pShbCirBuff->m_ulDataReadable = 0;
1768 pShbCirBuff->m_ulBlocksReadable = 0;
1770 ShbIpcLeaveAtomicSection(pShbInstance_p);
1774 memset(&pShbCirBuff->m_Data, 0xCC,
1775 pShbCirBuff->m_ulBufferDataSize);
1780 // call application handler
1781 if (pShbCirBuff->m_pfnSigHndlrReset != NULL) {
1782 pShbCirBuff->m_pfnSigHndlrReset(pShbInstance_p, fTimeOut_p);
1786 ShbIpcEnterAtomicSection(pShbInstance_p);
1788 pShbCirBuff->m_fBufferLocked = FALSE;
1789 pShbCirBuff->m_pfnSigHndlrReset = NULL;
1791 ShbIpcLeaveAtomicSection(pShbInstance_p);