• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2 
3   (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4       www.systec-electronic.com
5 
6   Project:      Project independend shared buffer (linear + circular)
7 
8   Description:  Implementation of platform independend part for the
9                 shared buffer
10 
11   License:
12 
13     Redistribution and use in source and binary forms, with or without
14     modification, are permitted provided that the following conditions
15     are met:
16 
17     1. Redistributions of source code must retain the above copyright
18        notice, this list of conditions and the following disclaimer.
19 
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.
23 
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.
28 
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.
41 
42     Severability Clause:
43 
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.
50 
51   -------------------------------------------------------------------------
52 
53   2006/06/27 -rs:   V 1.00 (initial version)
54 
55 ****************************************************************************/
56 
57 #if defined(WIN32) || defined(_WIN32)
58 
59 #ifdef UNDER_RTSS
60 	// RTX header
61 #include <windows.h>
62 #include <process.h>
63 #include <rtapi.h>
64 
65 #elif __BORLANDC__
66 	// borland C header
67 #include <windows.h>
68 #include <process.h>
69 
70 #elif WINCE
71 #include <windows.h>
72 
73 #else
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
78 #include <windows.h>
79 #include <process.h>
80 #endif
81 
82 #endif
83 
84 #include "global.h"
85 #include "SharedBuff.h"
86 #include "ShbIpc.h"
87 
88 // d.k. Linux kernel modules needs other header files for memcpy()
89 #if (TARGET_SYSTEM == _LINUX_) && defined(__KERNEL__)
90 #include <linux/string.h>
91 #else
92 #include <stdio.h>
93 #include <stdlib.h>
94 #include <string.h>
95 #endif
96 
97 /***************************************************************************/
98 /*                                                                         */
99 /*                                                                         */
100 /*          G L O B A L   D E F I N I T I O N S                            */
101 /*                                                                         */
102 /*                                                                         */
103 /***************************************************************************/
104 
105 #if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
106 
107 //---------------------------------------------------------------------------
108 //  Configuration
109 //---------------------------------------------------------------------------
110 
111 //---------------------------------------------------------------------------
112 //  Constant definitions
113 //---------------------------------------------------------------------------
114 
115 #define SBC_MAGIC_ID    0x53424323	// magic ID ("SBC#")
116 #define SBL_MAGIC_ID    0x53424C23	// magic ID ("SBL#")
117 
118 //---------------------------------------------------------------------------
119 //  Local types
120 //---------------------------------------------------------------------------
121 
122 // structure to administrate circular shared buffer head
123 typedef struct {
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)
139 
140 } tShbCirBuff;
141 
142 // structure to administrate linear shared buffer head
143 typedef struct {
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)
148 
149 } tShbLinBuff;
150 
151 // type to save size of a single data block inside the circular shared buffer
152 typedef struct {
153 	unsigned int m_uiFullBlockSize:28;	// a single block must not exceed a length of 256MByte :-)
154 	unsigned int m_uiAlignFillBytes:4;
155 
156 } tShbCirBlockSize;
157 
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 :-)
160 
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 :-)
163 
164 //---------------------------------------------------------------------------
165 //  Global variables
166 //---------------------------------------------------------------------------
167 
168 //---------------------------------------------------------------------------
169 //  Local variables
170 //---------------------------------------------------------------------------
171 
172 //---------------------------------------------------------------------------
173 //  Prototypes of internal functions
174 //---------------------------------------------------------------------------
175 
176 //---------------------------------------------------------------------------
177 //  Get pointer to Circular Shared Buffer
178 //---------------------------------------------------------------------------
179 
ShbCirGetBuffer(tShbInstance pShbInstance_p)180 INLINE_FUNCTION tShbCirBuff *ShbCirGetBuffer(tShbInstance pShbInstance_p)
181 {
182 
183 	tShbCirBuff *pShbCirBuff;
184 
185 	pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
186 	ASSERT(pShbCirBuff->m_ShbCirMagicID == SBC_MAGIC_ID);
187 
188 	return (pShbCirBuff);
189 
190 }
191 
192 //---------------------------------------------------------------------------
193 //  Get pointer to Linear Shared Buffer
194 //---------------------------------------------------------------------------
195 
ShbLinGetBuffer(tShbInstance pShbInstance_p)196 INLINE_FUNCTION tShbLinBuff *ShbLinGetBuffer(tShbInstance pShbInstance_p)
197 {
198 
199 	tShbLinBuff *pShbLinBuff;
200 
201 	pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
202 	ASSERT(pShbLinBuff->m_ShbLinMagicID == SBL_MAGIC_ID);
203 
204 	return (pShbLinBuff);
205 
206 }
207 
208 // not inlined internal functions
209 int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p);
210 void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
211 			      unsigned int fTimeOut_p);
212 
213 #endif
214 
215 //=========================================================================//
216 //                                                                         //
217 //          P U B L I C   F U N C T I O N S                                //
218 //                                                                         //
219 //=========================================================================//
220 
221 #if !defined(INLINE_ENABLED)
222 // not inlined external functions
223 
224 //---------------------------------------------------------------------------
225 //  Initialize Shared Buffer Module
226 //---------------------------------------------------------------------------
227 
ShbInit(void)228 tShbError ShbInit(void)
229 {
230 
231 	tShbError ShbError;
232 
233 	ShbError = ShbIpcInit();
234 
235 	return (ShbError);
236 
237 }
238 
239 //---------------------------------------------------------------------------
240 //  Deinitialize Shared Buffer Module
241 //---------------------------------------------------------------------------
242 
ShbExit(void)243 tShbError ShbExit(void)
244 {
245 
246 	tShbError ShbError;
247 
248 	ShbError = ShbIpcExit();
249 
250 	return (ShbError);
251 
252 }
253 
254 //-------------------------------------------------------------------------//
255 //                                                                         //
256 //          C i r c u l a r   S h a r e d   B u f f e r                    //
257 //                                                                         //
258 //-------------------------------------------------------------------------//
259 
260 //---------------------------------------------------------------------------
261 //  Allocate Circular Shared Buffer
262 //---------------------------------------------------------------------------
263 
ShbCirAllocBuffer(unsigned long ulBufferSize_p,const char * pszBufferID_p,tShbInstance * ppShbInstance_p,unsigned int * pfShbNewCreated_p)264 tShbError ShbCirAllocBuffer(unsigned long ulBufferSize_p,
265 			    const char *pszBufferID_p,
266 			    tShbInstance * ppShbInstance_p,
267 			    unsigned int *pfShbNewCreated_p)
268 {
269 
270 	tShbInstance pShbInstance;
271 	tShbCirBuff *pShbCirBuff;
272 	unsigned int fShbNewCreated;
273 	unsigned long ulBufferDataSize;
274 	unsigned long ulBufferTotalSize;
275 	tShbError ShbError;
276 
277 	// check arguments
278 	if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
279 		return (kShbInvalidArg);
280 	}
281 
282 	// calculate length of memory to allocate
283 	ulBufferDataSize =
284 	    (ulBufferSize_p +
285 	     (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
286 	ulBufferTotalSize = ulBufferDataSize + sizeof(tShbCirBuff);
287 
288 	// allocate a new or open an existing shared buffer
289 	ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
290 				     &pShbInstance, &fShbNewCreated);
291 	if (ShbError != kShbOk) {
292 		goto Exit;
293 	}
294 
295 	if (pShbInstance == NULL) {
296 		ShbError = kShbOutOfMem;
297 		goto Exit;
298 	}
299 
300 	// get pointer to shared buffer
301 	pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance);
302 
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) {
307 #ifndef NDEBUG
308 		{
309 			memset(pShbCirBuff, 0xCC, ulBufferTotalSize);
310 		}
311 #endif
312 
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;
327 	} else {
328 		if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
329 			ShbError = kShbInvalidBufferType;
330 			goto Exit;
331 		}
332 	}
333 
334       Exit:
335 
336 	*ppShbInstance_p = pShbInstance;
337 	*pfShbNewCreated_p = fShbNewCreated;
338 
339 	return (ShbError);
340 
341 }
342 
343 //---------------------------------------------------------------------------
344 //  Release Circular Shared Buffer
345 //---------------------------------------------------------------------------
346 
ShbCirReleaseBuffer(tShbInstance pShbInstance_p)347 tShbError ShbCirReleaseBuffer(tShbInstance pShbInstance_p)
348 {
349 
350 	tShbError ShbError;
351 
352 	// check arguments
353 	if (pShbInstance_p == NULL) {
354 		ShbError = kShbOk;
355 		goto Exit;
356 	}
357 
358 	ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
359 
360       Exit:
361 
362 	return (ShbError);
363 
364 }
365 
366 #endif // !defined(INLINE_ENABLED)
367 
368 #if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
369 
370 //---------------------------------------------------------------------------
371 //  Reset Circular Shared Buffer
372 //---------------------------------------------------------------------------
373 
ShbCirResetBuffer(tShbInstance pShbInstance_p,unsigned long ulTimeOut_p,tShbCirSigHndlrReset pfnSignalHandlerReset_p)374 INLINE_FUNCTION tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p,
375 					    unsigned long ulTimeOut_p,
376 					    tShbCirSigHndlrReset
377 					    pfnSignalHandlerReset_p)
378 {
379 
380 	tShbCirBuff *pShbCirBuff;
381 	unsigned long ulNumOfWriteJobs = 0;	// d.k. GCC complains about uninitialized variable otherwise
382 	tShbError ShbError;
383 
384 	// check arguments
385 	if (pShbInstance_p == NULL) {
386 		ShbError = kShbInvalidArg;
387 		goto Exit;
388 	}
389 
390 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
391 	ShbError = kShbOk;
392 
393 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
394 		ShbError = kShbInvalidBufferType;
395 		goto Exit;
396 	}
397 
398 	// start reset job by setting request request in buffer header
399 	ShbIpcEnterAtomicSection(pShbInstance_p);
400 	{
401 		if (!pShbCirBuff->m_fBufferLocked) {
402 			ulNumOfWriteJobs = pShbCirBuff->m_ulNumOfWriteJobs;
403 
404 			pShbCirBuff->m_fBufferLocked = TRUE;
405 			pShbCirBuff->m_pfnSigHndlrReset =
406 			    pfnSignalHandlerReset_p;
407 		} else {
408 			ShbError = kShbAlreadyReseting;
409 		}
410 	}
411 	ShbIpcLeaveAtomicSection(pShbInstance_p);
412 
413 	if (ShbError != kShbOk) {
414 		goto Exit;
415 	}
416 
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);
424 		ShbError = kShbOk;
425 	} else {
426 		// there is currently at least one running write operation
427 		// -> starting signal process to wait until the last write job is ready
428 		ShbError =
429 		    ShbIpcStartSignalingJobReady(pShbInstance_p, ulTimeOut_p,
430 						 ShbCirSignalHandlerReset);
431 	}
432 
433       Exit:
434 
435 	return (ShbError);
436 
437 }
438 
439 //---------------------------------------------------------------------------
440 //  Write data block to Circular Shared Buffer
441 //---------------------------------------------------------------------------
442 
ShbCirWriteDataBlock(tShbInstance pShbInstance_p,const void * pSrcDataBlock_p,unsigned long ulDataBlockSize_p)443 INLINE_FUNCTION tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p,
444 					       const void *pSrcDataBlock_p,
445 					       unsigned long ulDataBlockSize_p)
446 {
447 
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;
459 	tShbError ShbError;
460 	tShbError ShbError2;
461 	int fRes;
462 
463 	// check arguments
464 	if (pShbInstance_p == NULL) {
465 		ShbError = kShbInvalidArg;
466 		goto Exit;
467 	}
468 
469 	if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
470 		// nothing to do here
471 		ShbError = kShbOk;
472 		goto Exit;
473 	}
474 
475 	if (ulDataBlockSize_p > SBC_MAX_BLOCK_SIZE) {
476 		ShbError = kShbExceedDataSizeLimit;
477 		goto Exit;
478 	}
479 
480 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
481 	pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
482 	fSignalNewData = FALSE;
483 	fSignalReset = FALSE;
484 	ShbError = kShbOk;
485 
486 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
487 		ShbError = kShbInvalidBufferType;
488 		goto Exit;
489 	}
490 
491 	// calculate data block size in circular buffer
492 	ulDataSize =
493 	    (ulDataBlockSize_p +
494 	     (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
495 	uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize);	// data size + header
496 	uiAlignFillBytes = ulDataSize - ulDataBlockSize_p;
497 
498 	ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
499 	ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
500 
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);
504 	{
505 		// check if there is sufficient memory available to store
506 		// the new data
507 		fRes =
508 		    uiFullBlockSize <=
509 		    (pShbCirBuff->m_ulBufferDataSize -
510 		     pShbCirBuff->m_ulDataInUse);
511 		if (fRes) {
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;
515 
516 			// reserve the needed memory for the write operation to do now
517 			pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
518 
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;
524 
525 			// increment number of currently (parallel running)
526 			// write operations
527 			pShbCirBuff->m_ulNumOfWriteJobs++;
528 		}
529 	}
530 	ShbIpcLeaveAtomicSection(pShbInstance_p);
531 
532 	if (!fRes) {
533 		ShbError = kShbBufferFull;
534 		goto Exit;
535 	}
536 
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
541 
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;
546 
547 	if (ulWrIndex + ulDataBlockSize_p <= pShbCirBuff->m_ulBufferDataSize) {
548 		// linear write operation
549 		memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
550 		       ulDataBlockSize_p);
551 	} else {
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);
557 	}
558 
559 	// adjust header information for circular buffer with properties
560 	// of the wiritten data block
561 	ShbIpcEnterAtomicSection(pShbInstance_p);
562 	{
563 		pShbCirBuff->m_ulDataApended += uiFullBlockSize;
564 		pShbCirBuff->m_ulBlocksApended++;
565 
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;
575 
576 			pShbCirBuff->m_ulDataApended = 0;
577 			pShbCirBuff->m_ulBlocksApended = 0;
578 
579 			fSignalNewData = TRUE;
580 			fSignalReset = pShbCirBuff->m_fBufferLocked;
581 		}
582 	}
583 	ShbIpcLeaveAtomicSection(pShbInstance_p);
584 
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;
590 		}
591 	}
592 	// signal that the last write job has been finished to allow
593 	// a waiting application to reset the buffer now
594 	if (fSignalReset) {
595 		ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
596 		if (ShbError == kShbOk) {
597 			ShbError = ShbError2;
598 		}
599 	}
600 
601       Exit:
602 
603 	return (ShbError);
604 
605 }
606 
607 //---------------------------------------------------------------------------
608 //  Allocate block within the Circular Shared Buffer for chunk writing
609 //---------------------------------------------------------------------------
610 
ShbCirAllocDataBlock(tShbInstance pShbInstance_p,tShbCirChunk * pShbCirChunk_p,unsigned long ulDataBufferSize_p)611 INLINE_FUNCTION tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p,
612 					       tShbCirChunk * pShbCirChunk_p,
613 					       unsigned long ulDataBufferSize_p)
614 {
615 
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
623 	tShbError ShbError;
624 	int fRes;
625 
626 	// check arguments
627 	if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)) {
628 		ShbError = kShbInvalidArg;
629 		goto Exit;
630 	}
631 
632 	if (ulDataBufferSize_p == 0) {
633 		ShbError = kShbInvalidArg;
634 		goto Exit;
635 	}
636 
637 	if (ulDataBufferSize_p > SBC_MAX_BLOCK_SIZE) {
638 		ShbError = kShbExceedDataSizeLimit;
639 		goto Exit;
640 	}
641 
642 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
643 	ShbError = kShbOk;
644 
645 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
646 		ShbError = kShbInvalidBufferType;
647 		goto Exit;
648 	}
649 
650 	// calculate data block size in circular buffer
651 	ulDataSize =
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;
656 
657 	ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
658 	ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
659 
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);
663 	{
664 		// check if there is sufficient memory available to store
665 		// the new data
666 		fRes =
667 		    (uiFullBlockSize <=
668 		     (pShbCirBuff->m_ulBufferDataSize -
669 		      pShbCirBuff->m_ulDataInUse));
670 		if (fRes) {
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;
674 
675 			// reserve the needed memory for the write operation to do now
676 			pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
677 
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;
683 
684 			// increment number of currently (parallel running)
685 			// write operations
686 			pShbCirBuff->m_ulNumOfWriteJobs++;
687 		}
688 	}
689 	ShbIpcLeaveAtomicSection(pShbInstance_p);
690 
691 	if (!fRes) {
692 		ShbError = kShbBufferFull;
693 		goto Exit;
694 	}
695 
696 	// setup header information for allocated buffer
697 	pShbCirDataPtr = &pShbCirBuff->m_Data;	// ptr to start of data area
698 
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;
703 
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;
709 
710       Exit:
711 
712 	return (ShbError);
713 
714 }
715 
716 //---------------------------------------------------------------------------
717 //  Write data chunk into an allocated buffer of the Circular Shared Buffer
718 //---------------------------------------------------------------------------
719 
ShbCirWriteDataChunk(tShbInstance pShbInstance_p,tShbCirChunk * pShbCirChunk_p,const void * pSrcDataChunk_p,unsigned long ulDataChunkSize_p,unsigned int * pfBufferCompleted_p)720 INLINE_FUNCTION tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p,
721 					       tShbCirChunk * pShbCirChunk_p,
722 					       const void *pSrcDataChunk_p,
723 					       unsigned long ulDataChunkSize_p,
724 					       unsigned int
725 					       *pfBufferCompleted_p)
726 {
727 
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;
736 	tShbError ShbError;
737 	tShbError ShbError2;
738 
739 	// check arguments
740 	if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)
741 	    || (pfBufferCompleted_p == NULL)) {
742 		ShbError = kShbInvalidArg;
743 		goto Exit;
744 	}
745 
746 	if ((pSrcDataChunk_p == NULL) || (ulDataChunkSize_p == 0)) {
747 		// nothing to do here
748 		ShbError = kShbOk;
749 		goto Exit;
750 	}
751 
752 	if (pShbCirChunk_p->m_fBufferCompleted) {
753 		ShbError = kShbBufferAlreadyCompleted;
754 		goto Exit;
755 	}
756 
757 	if (ulDataChunkSize_p > pShbCirChunk_p->m_ulAvailableSize) {
758 		ShbError = kShbExceedDataSizeLimit;
759 		goto Exit;
760 	}
761 
762 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
763 	pScrDataPtr = (unsigned char *)pSrcDataChunk_p;
764 	fSignalNewData = FALSE;
765 	fSignalReset = FALSE;
766 	ShbError = kShbOk;
767 
768 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
769 		ShbError = kShbInvalidBufferType;
770 		goto Exit;
771 	}
772 
773 	ulWrIndex = pShbCirChunk_p->m_ulWrIndex;
774 
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
779 
780 	if (ulWrIndex + ulDataChunkSize_p <= pShbCirBuff->m_ulBufferDataSize) {
781 		// linear write operation
782 		memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
783 		       ulDataChunkSize_p);
784 	} else {
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);
790 	}
791 
792 	// adjust chunk descriptor
793 	ulWrIndex += ulDataChunkSize_p;
794 	ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
795 
796 	pShbCirChunk_p->m_ulAvailableSize -= ulDataChunkSize_p;
797 	pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
798 
799 	fBufferCompleted = (pShbCirChunk_p->m_ulAvailableSize == 0);
800 	pShbCirChunk_p->m_fBufferCompleted = fBufferCompleted;
801 
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);
807 		{
808 			pShbCirBuff->m_ulDataApended +=
809 			    pShbCirChunk_p->m_uiFullBlockSize;
810 			pShbCirBuff->m_ulBlocksApended++;
811 
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;
821 
822 				pShbCirBuff->m_ulDataApended = 0;
823 				pShbCirBuff->m_ulBlocksApended = 0;
824 
825 				fSignalNewData = TRUE;
826 				fSignalReset = pShbCirBuff->m_fBufferLocked;
827 			}
828 		}
829 		ShbIpcLeaveAtomicSection(pShbInstance_p);
830 	}
831 
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;
837 		}
838 	}
839 	// signal that the last write job has been finished to allow
840 	// a waiting application to reset the buffer now
841 	if (fSignalReset) {
842 		ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
843 		if (ShbError == kShbOk) {
844 			ShbError = ShbError2;
845 		}
846 	}
847 
848 	*pfBufferCompleted_p = fBufferCompleted;
849 
850       Exit:
851 
852 	return (ShbError);
853 
854 }
855 
856 //---------------------------------------------------------------------------
857 //  Read data block from Circular Shared Buffer
858 //---------------------------------------------------------------------------
859 
ShbCirReadDataBlock(tShbInstance pShbInstance_p,void * pDstDataBlock_p,unsigned long ulRdBuffSize_p,unsigned long * pulDataBlockSize_p)860 INLINE_FUNCTION tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p,
861 					      void *pDstDataBlock_p,
862 					      unsigned long ulRdBuffSize_p,
863 					      unsigned long *pulDataBlockSize_p)
864 {
865 
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;
874 	tShbError ShbError;
875 
876 	// check arguments
877 	if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
878 		return (kShbInvalidArg);
879 	}
880 
881 	if ((pDstDataBlock_p == NULL) || (ulRdBuffSize_p == 0)) {
882 		// nothing to do here
883 		ShbError = kShbOk;
884 		goto Exit;
885 	}
886 
887 	ShbError = kShbOk;
888 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
889 	pDstDataPtr = (unsigned char *)pDstDataBlock_p;
890 	ulDataSize = 0;
891 
892 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
893 		ShbError = kShbInvalidBufferType;
894 		goto Exit;
895 	}
896 
897 	// get total number of readable bytes for the whole circular buffer
898 	ShbIpcEnterAtomicSection(pShbInstance_p);
899 	{
900 		ulDataReadable = pShbCirBuff->m_ulDataReadable;
901 	}
902 	ShbIpcLeaveAtomicSection(pShbInstance_p);
903 
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;
910 
911 		// get real size of current block (incl. alignment fill bytes)
912 		ShbCirBlockSize =
913 		    *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
914 		ulRdIndex += sizeof(tShbCirBlockSize);
915 		ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
916 
917 		// get size of user data inside the current block
918 		ulDataSize =
919 		    ShbCirBlockSize.m_uiFullBlockSize -
920 		    ShbCirBlockSize.m_uiAlignFillBytes;
921 		ulDataSize -= sizeof(tShbCirBlockSize);
922 	}
923 
924 	// ulDataSize = MIN(ulDataSize, ulRdBuffSize_p);
925 	if (ulDataSize > ulRdBuffSize_p) {
926 		ulDataSize = ulRdBuffSize_p;
927 		ShbError = kShbDataTruncated;
928 	}
929 
930 	if (ulDataSize == 0) {
931 		// nothing to do here
932 		ShbError = kShbNoReadableData;
933 		goto Exit;
934 	}
935 
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);
942 	} else {
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);
948 	}
949 
950 #ifndef NDEBUG
951 	{
952 		tShbCirBlockSize ClrShbCirBlockSize;
953 
954 		if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
955 			// linear buffer
956 			memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulDataSize);
957 		} else {
958 			// wrap-around read operation
959 			ulChunkSize =
960 			    pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
961 			memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulChunkSize);
962 			memset(pShbCirDataPtr, 0xDD, ulDataSize - ulChunkSize);
963 		}
964 
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) =
969 		    ClrShbCirBlockSize;
970 	}
971 #endif // #ifndef NDEBUG
972 
973 	// set new size of readable data, data in use, new read index
974 	// and adjust number of readable blocks
975 	ShbIpcEnterAtomicSection(pShbInstance_p);
976 	{
977 		pShbCirBuff->m_ulDataInUse -= ShbCirBlockSize.m_uiFullBlockSize;
978 		pShbCirBuff->m_ulDataReadable -=
979 		    ShbCirBlockSize.m_uiFullBlockSize;
980 		pShbCirBuff->m_ulBlocksReadable--;
981 
982 		//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
983 		if ((pShbCirBuff->m_ulDataInUse == 0)
984 		    && (pShbCirBuff->m_ulDataReadable == 0)) {
985 			ASSERT(pShbCirBuff->m_ulBlocksReadable == 0);
986 
987 			pShbCirBuff->m_ulWrIndex = 0;
988 			pShbCirBuff->m_ulRdIndex = 0;
989 		} else
990 			//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
991 		{
992 			pShbCirBuff->m_ulRdIndex +=
993 			    ShbCirBlockSize.m_uiFullBlockSize;
994 			pShbCirBuff->m_ulRdIndex %=
995 			    pShbCirBuff->m_ulBufferDataSize;
996 		}
997 	}
998 	ShbIpcLeaveAtomicSection(pShbInstance_p);
999 
1000       Exit:
1001 
1002 	*pulDataBlockSize_p = ulDataSize;
1003 
1004 	return (ShbError);
1005 
1006 }
1007 
1008 //---------------------------------------------------------------------------
1009 //  Get data size of next readable block from Circular Shared Buffer
1010 //---------------------------------------------------------------------------
1011 
ShbCirGetReadDataSize(tShbInstance pShbInstance_p,unsigned long * pulDataBlockSize_p)1012 INLINE_FUNCTION tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p,
1013 						unsigned long
1014 						*pulDataBlockSize_p)
1015 {
1016 
1017 	tShbCirBuff *pShbCirBuff;
1018 	unsigned long ulDataReadable;
1019 	unsigned char *pShbCirDataPtr;
1020 	tShbCirBlockSize ShbCirBlockSize;
1021 	unsigned long ulDataSize;
1022 	tShbError ShbError;
1023 
1024 	// check arguments
1025 	if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
1026 		return (kShbInvalidArg);
1027 	}
1028 
1029 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1030 	ulDataSize = 0;
1031 	ShbError = kShbOk;
1032 
1033 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1034 		ShbError = kShbInvalidBufferType;
1035 		goto Exit;
1036 	}
1037 
1038 	// get total number of readable bytes for the whole circular buffer
1039 	ShbIpcEnterAtomicSection(pShbInstance_p);
1040 	{
1041 		ulDataReadable = pShbCirBuff->m_ulDataReadable;
1042 	}
1043 	ShbIpcLeaveAtomicSection(pShbInstance_p);
1044 
1045 	// if there are readable data available, then there must be at least
1046 	// one complete readable data block
1047 	if (ulDataReadable > 0) {
1048 		pShbCirDataPtr =
1049 		    &pShbCirBuff->m_Data + pShbCirBuff->m_ulRdIndex;
1050 
1051 		// get real size of current block (incl. alignment fill bytes)
1052 		ShbCirBlockSize = *(tShbCirBlockSize *) pShbCirDataPtr;
1053 
1054 		// get size of user data inside the current block
1055 		ulDataSize =
1056 		    ShbCirBlockSize.m_uiFullBlockSize -
1057 		    ShbCirBlockSize.m_uiAlignFillBytes;
1058 		ulDataSize -= sizeof(tShbCirBlockSize);
1059 	}
1060 
1061       Exit:
1062 
1063 	*pulDataBlockSize_p = ulDataSize;
1064 
1065 	return (ShbError);
1066 
1067 }
1068 
1069 //---------------------------------------------------------------------------
1070 //  Get number of readable blocks from Circular Shared Buffer
1071 //---------------------------------------------------------------------------
1072 
ShbCirGetReadBlockCount(tShbInstance pShbInstance_p,unsigned long * pulDataBlockCount_p)1073 INLINE_FUNCTION tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p,
1074 						  unsigned long
1075 						  *pulDataBlockCount_p)
1076 {
1077 
1078 	tShbCirBuff *pShbCirBuff;
1079 	unsigned long ulBlockCount;
1080 	tShbError ShbError;
1081 
1082 	// check arguments
1083 	if ((pShbInstance_p == NULL) || (pulDataBlockCount_p == NULL)) {
1084 		ShbError = kShbInvalidArg;
1085 		goto Exit;
1086 	}
1087 
1088 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1089 	ulBlockCount = 0;
1090 	ShbError = kShbOk;
1091 
1092 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1093 		ShbError = kShbInvalidBufferType;
1094 		goto Exit;
1095 	}
1096 
1097 	ShbIpcEnterAtomicSection(pShbInstance_p);
1098 	{
1099 		ulBlockCount = pShbCirBuff->m_ulBlocksReadable;
1100 	}
1101 	ShbIpcLeaveAtomicSection(pShbInstance_p);
1102 
1103 	*pulDataBlockCount_p = ulBlockCount;
1104 
1105       Exit:
1106 
1107 	return (ShbError);
1108 
1109 }
1110 
1111 //---------------------------------------------------------------------------
1112 //  Set application handler to signal new data for Circular Shared Buffer
1113 //  d.k.: new parameter priority as enum
1114 //---------------------------------------------------------------------------
1115 
ShbCirSetSignalHandlerNewData(tShbInstance pShbInstance_p,tShbCirSigHndlrNewData pfnSignalHandlerNewData_p,tShbPriority ShbPriority_p)1116 INLINE_FUNCTION tShbError ShbCirSetSignalHandlerNewData(tShbInstance
1117 							pShbInstance_p,
1118 							tShbCirSigHndlrNewData
1119 							pfnSignalHandlerNewData_p,
1120 							tShbPriority
1121 							ShbPriority_p)
1122 {
1123 
1124 	tShbCirBuff *pShbCirBuff;
1125 	tShbError ShbError;
1126 
1127 	// check arguments
1128 	if (pShbInstance_p == NULL) {
1129 		ShbError = kShbInvalidArg;
1130 		goto Exit;
1131 	}
1132 
1133 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1134 	ShbError = kShbOk;
1135 
1136 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1137 		ShbError = kShbInvalidBufferType;
1138 		goto Exit;
1139 	}
1140 
1141 	if (pfnSignalHandlerNewData_p != NULL) {
1142 		// set a new signal handler
1143 		if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1144 			ShbError = kShbAlreadySignaling;
1145 			goto Exit;
1146 		}
1147 
1148 		pShbCirBuff->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
1149 		ShbError =
1150 		    ShbIpcStartSignalingNewData(pShbInstance_p,
1151 						ShbCirSignalHandlerNewData,
1152 						ShbPriority_p);
1153 	} else {
1154 		// remove existing signal handler
1155 		ShbError = ShbIpcStopSignalingNewData(pShbInstance_p);
1156 		if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1157 			pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p, 0);
1158 		}
1159 		pShbCirBuff->m_pfnSigHndlrNewData = NULL;
1160 	}
1161 
1162       Exit:
1163 
1164 	return (ShbError);
1165 
1166 }
1167 
1168 #endif
1169 
1170 #if !defined(INLINE_ENABLED)
1171 
1172 //---------------------------------------------------------------------------
1173 //  DEBUG: Trace Circular Shared Buffer
1174 //---------------------------------------------------------------------------
1175 
1176 #ifndef NDEBUG
ShbCirTraceBuffer(tShbInstance pShbInstance_p)1177 tShbError ShbCirTraceBuffer(tShbInstance pShbInstance_p)
1178 {
1179 
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;
1190 	tShbError ShbError;
1191 
1192 	TRACE0("\n\n##### Circular Shared Buffer #####\n");
1193 
1194 	// check arguments
1195 	if (pShbInstance_p == NULL) {
1196 		TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1197 		       (unsigned long)pShbInstance_p);
1198 		ShbError = kShbInvalidArg;
1199 		goto Exit;
1200 	}
1201 
1202 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1203 	ShbError = kShbOk;
1204 
1205 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1206 		ShbError = kShbInvalidBufferType;
1207 		goto Exit;
1208 	}
1209 
1210 	*(unsigned long *)&szMagigID[0] = pShbCirBuff->m_ShbCirMagicID;
1211 	szMagigID[sizeof(SBC_MAGIC_ID)] = '\0';
1212 
1213 	ShbIpcEnterAtomicSection(pShbInstance_p);
1214 	{
1215 		TRACE1("\nBuffer Address:   0x%08lX\n",
1216 		       (unsigned long)pShbCirBuff);
1217 
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);
1244 
1245 		ShbTraceDump(&pShbCirBuff->m_Data,
1246 			     pShbCirBuff->m_ulBufferDataSize, 0x00000000L,
1247 			     "\nData Area:");
1248 
1249 		ulDataReadable = pShbCirBuff->m_ulDataReadable;
1250 		nBlockCount = 1;
1251 		ulBlockIndex = pShbCirBuff->m_ulRdIndex;
1252 
1253 		while (ulDataReadable > 0) {
1254 			TRACE1("\n\n--- Block #%u ---", nBlockCount);
1255 
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;
1259 
1260 			// get real size of current block (incl. alignment fill bytes)
1261 			ShbCirBlockSize =
1262 			    *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
1263 			ulRdIndex += sizeof(tShbCirBlockSize);
1264 			ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
1265 
1266 			// get size of user data inside the current block
1267 			ulDataSize =
1268 			    ShbCirBlockSize.m_uiFullBlockSize -
1269 			    ShbCirBlockSize.m_uiAlignFillBytes;
1270 			ulDataSize -= sizeof(tShbCirBlockSize);
1271 
1272 			TRACE1
1273 			    ("\nFull Data Size:       %4u [Bytes] (incl. header and alignment fill bytes)",
1274 			     ShbCirBlockSize.m_uiFullBlockSize);
1275 			TRACE1("\nUser Data Size:       %4lu [Bytes]",
1276 			       ulDataSize);
1277 			TRACE1("\nAlignment Fill Bytes: %4u [Bytes]",
1278 			       ShbCirBlockSize.m_uiAlignFillBytes);
1279 
1280 			if (ulRdIndex + ulDataSize <=
1281 			    pShbCirBuff->m_ulBufferDataSize) {
1282 				// linear data buffer
1283 				ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1284 					     ulDataSize, 0x00000000L, NULL);
1285 			} else {
1286 				// wrap-around data buffer
1287 				ulChunkSize =
1288 				    pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
1289 				ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1290 					     ulChunkSize, 0x00000000L, NULL);
1291 				ShbTraceDump(pShbCirDataPtr,
1292 					     ulDataSize - ulChunkSize,
1293 					     ulChunkSize, NULL);
1294 			}
1295 
1296 			nBlockCount++;
1297 
1298 			ulBlockIndex += ShbCirBlockSize.m_uiFullBlockSize;
1299 			ulBlockIndex %= pShbCirBuff->m_ulBufferDataSize;
1300 
1301 			ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
1302 		}
1303 
1304 		ASSERT(pShbCirBuff->m_ulBlocksReadable == nBlockCount - 1);
1305 	}
1306 	ShbIpcLeaveAtomicSection(pShbInstance_p);
1307 
1308       Exit:
1309 
1310 	return (ShbError);
1311 
1312 }
1313 #endif
1314 
1315 //-------------------------------------------------------------------------//
1316 //                                                                         //
1317 //          L i n e a r   S h a r e d   B u f f e r                        //
1318 //                                                                         //
1319 //-------------------------------------------------------------------------//
1320 
1321 //---------------------------------------------------------------------------
1322 //  Allocate Linear Shared Buffer
1323 //---------------------------------------------------------------------------
1324 
ShbLinAllocBuffer(unsigned long ulBufferSize_p,const char * pszBufferID_p,tShbInstance * ppShbInstance_p,unsigned int * pfShbNewCreated_p)1325 tShbError ShbLinAllocBuffer(unsigned long ulBufferSize_p,
1326 			    const char *pszBufferID_p,
1327 			    tShbInstance * ppShbInstance_p,
1328 			    unsigned int *pfShbNewCreated_p)
1329 {
1330 
1331 	tShbInstance pShbInstance;
1332 	tShbLinBuff *pShbLinBuff;
1333 	unsigned int fShbNewCreated;
1334 	unsigned long ulBufferDataSize;
1335 	unsigned long ulBufferTotalSize;
1336 	tShbError ShbError;
1337 
1338 	// check arguments
1339 	if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
1340 		return (kShbInvalidArg);
1341 	}
1342 
1343 	// calculate length of memory to allocate
1344 	ulBufferDataSize =
1345 	    (ulBufferSize_p +
1346 	     (SBL_BLOCK_ALIGNMENT - 1)) & ~(SBL_BLOCK_ALIGNMENT - 1);
1347 	ulBufferTotalSize = ulBufferDataSize + sizeof(tShbLinBuff);
1348 
1349 	// allocate a new or open an existing shared buffer
1350 	ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
1351 				     &pShbInstance, &fShbNewCreated);
1352 	if (ShbError != kShbOk) {
1353 		goto Exit;
1354 	}
1355 
1356 	if (pShbInstance == NULL) {
1357 		ShbError = kShbOutOfMem;
1358 		goto Exit;
1359 	}
1360 
1361 	// get pointer to shared buffer
1362 	pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance);
1363 
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) {
1368 #ifndef NDEBUG
1369 		{
1370 			memset(pShbLinBuff, 0xCC, ulBufferTotalSize);
1371 		}
1372 #endif
1373 
1374 		pShbLinBuff->m_ShbLinMagicID = SBL_MAGIC_ID;
1375 		pShbLinBuff->m_ulBufferTotalSize = ulBufferTotalSize;
1376 		pShbLinBuff->m_ulBufferDataSize = ulBufferDataSize;
1377 	} else {
1378 		if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1379 			ShbError = kShbInvalidBufferType;
1380 			goto Exit;
1381 		}
1382 	}
1383 
1384       Exit:
1385 
1386 	*ppShbInstance_p = pShbInstance;
1387 	*pfShbNewCreated_p = fShbNewCreated;
1388 
1389 	return (ShbError);
1390 
1391 }
1392 
1393 //---------------------------------------------------------------------------
1394 //  Release Linear Shared Buffer
1395 //---------------------------------------------------------------------------
1396 
ShbLinReleaseBuffer(tShbInstance pShbInstance_p)1397 tShbError ShbLinReleaseBuffer(tShbInstance pShbInstance_p)
1398 {
1399 
1400 	tShbError ShbError;
1401 
1402 	// check arguments
1403 	if (pShbInstance_p == NULL) {
1404 		ShbError = kShbOk;
1405 		goto Exit;
1406 	}
1407 
1408 	ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
1409 
1410       Exit:
1411 
1412 	return (ShbError);
1413 
1414 }
1415 
1416 #endif // !defined(INLINE_ENABLED)
1417 
1418 #if (!defined(SHAREDBUFF_INLINED)) || defined(INLINE_ENABLED)
1419 
1420 //---------------------------------------------------------------------------
1421 //  Write data block to Linear Shared Buffer
1422 //---------------------------------------------------------------------------
1423 
ShbLinWriteDataBlock(tShbInstance pShbInstance_p,unsigned long ulDstBufferOffs_p,const void * pSrcDataBlock_p,unsigned long ulDataBlockSize_p)1424 INLINE_FUNCTION tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p,
1425 					       unsigned long ulDstBufferOffs_p,
1426 					       const void *pSrcDataBlock_p,
1427 					       unsigned long ulDataBlockSize_p)
1428 {
1429 
1430 	tShbLinBuff *pShbLinBuff;
1431 	unsigned char *pShbLinDataPtr;
1432 	unsigned char *pScrDataPtr;
1433 	unsigned long ulBufferDataSize;
1434 	tShbError ShbError;
1435 
1436 	// check arguments
1437 	if (pShbInstance_p == NULL) {
1438 		ShbError = kShbInvalidArg;
1439 		goto Exit;
1440 	}
1441 
1442 	if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1443 		// nothing to do here
1444 		ShbError = kShbOk;
1445 		goto Exit;
1446 	}
1447 
1448 	if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1449 		ShbError = kShbExceedDataSizeLimit;
1450 		goto Exit;
1451 	}
1452 
1453 	pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1454 	pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
1455 	ShbError = kShbOk;
1456 
1457 	if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1458 		ShbError = kShbInvalidBufferType;
1459 		goto Exit;
1460 	}
1461 
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;
1469 		goto Exit;
1470 	}
1471 
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;
1476 
1477 	ShbIpcEnterAtomicSection(pShbInstance_p);
1478 	{
1479 		memcpy(pShbLinDataPtr, pScrDataPtr, ulDataBlockSize_p);
1480 	}
1481 	ShbIpcLeaveAtomicSection(pShbInstance_p);
1482 
1483       Exit:
1484 
1485 	return (ShbError);
1486 
1487 }
1488 
1489 //---------------------------------------------------------------------------
1490 //  Read data block from Linear Shared Buffer
1491 //---------------------------------------------------------------------------
1492 
ShbLinReadDataBlock(tShbInstance pShbInstance_p,void * pDstDataBlock_p,unsigned long ulSrcBufferOffs_p,unsigned long ulDataBlockSize_p)1493 INLINE_FUNCTION tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p,
1494 					      void *pDstDataBlock_p,
1495 					      unsigned long ulSrcBufferOffs_p,
1496 					      unsigned long ulDataBlockSize_p)
1497 {
1498 
1499 	tShbLinBuff *pShbLinBuff;
1500 	unsigned char *pShbLinDataPtr;
1501 	unsigned char *pDstDataPtr;
1502 	unsigned long ulBufferDataSize;
1503 	tShbError ShbError;
1504 
1505 	// check arguments
1506 	if (pShbInstance_p == NULL) {
1507 		ShbError = kShbInvalidArg;
1508 		goto Exit;
1509 	}
1510 
1511 	if ((pDstDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1512 		// nothing to do here
1513 		ShbError = kShbOk;
1514 		goto Exit;
1515 	}
1516 
1517 	if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1518 		ShbError = kShbExceedDataSizeLimit;
1519 		goto Exit;
1520 	}
1521 
1522 	pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1523 	pDstDataPtr = (unsigned char *)pDstDataBlock_p;
1524 	ShbError = kShbOk;
1525 
1526 	if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1527 		ShbError = kShbInvalidBufferType;
1528 		goto Exit;
1529 	}
1530 
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;
1538 		goto Exit;
1539 	}
1540 
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;
1545 
1546 	ShbIpcEnterAtomicSection(pShbInstance_p);
1547 	{
1548 		memcpy(pDstDataPtr, pShbLinDataPtr, ulDataBlockSize_p);
1549 	}
1550 	ShbIpcLeaveAtomicSection(pShbInstance_p);
1551 
1552       Exit:
1553 
1554 	return (ShbError);
1555 
1556 }
1557 
1558 #endif
1559 
1560 #if !defined(INLINE_ENABLED)
1561 
1562 //---------------------------------------------------------------------------
1563 //  DEBUG: Trace Linear Shared Buffer
1564 //---------------------------------------------------------------------------
1565 
1566 #ifndef NDEBUG
ShbLinTraceBuffer(tShbInstance pShbInstance_p)1567 tShbError ShbLinTraceBuffer(tShbInstance pShbInstance_p)
1568 {
1569 
1570 	tShbLinBuff *pShbLinBuff;
1571 	char szMagigID[sizeof(SBL_MAGIC_ID) + 1];
1572 	tShbError ShbError;
1573 
1574 	TRACE0("\n\n##### Linear Shared Buffer #####\n");
1575 
1576 	// check arguments
1577 	if (pShbInstance_p == NULL) {
1578 		TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1579 		       (unsigned long)pShbInstance_p);
1580 		ShbError = kShbInvalidArg;
1581 		goto Exit;
1582 	}
1583 
1584 	pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1585 	ShbError = kShbOk;
1586 
1587 	if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1588 		ShbError = kShbInvalidBufferType;
1589 		goto Exit;
1590 	}
1591 
1592 	*(unsigned int *)&szMagigID[0] = pShbLinBuff->m_ShbLinMagicID;
1593 	szMagigID[sizeof(SBL_MAGIC_ID)] = '\0';
1594 
1595 	ShbIpcEnterAtomicSection(pShbInstance_p);
1596 	{
1597 		TRACE1("\nBuffer Address:   0x%08lX\n",
1598 		       (unsigned long)pShbLinBuff);
1599 
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);
1607 
1608 		ShbTraceDump(&pShbLinBuff->m_Data,
1609 			     pShbLinBuff->m_ulBufferDataSize, 0x00000000L,
1610 			     "\nData Area:");
1611 	}
1612 	ShbIpcLeaveAtomicSection(pShbInstance_p);
1613 
1614       Exit:
1615 
1616 	return (ShbError);
1617 
1618 }
1619 #endif
1620 
1621 //---------------------------------------------------------------------------
1622 //  Dump buffer contents
1623 //---------------------------------------------------------------------------
1624 
1625 #ifndef NDEBUG
ShbTraceDump(const unsigned char * pabStartAddr_p,unsigned long ulDataSize_p,unsigned long ulAddrOffset_p,const char * pszInfoText_p)1626 tShbError ShbTraceDump(const unsigned char *pabStartAddr_p,
1627 		       unsigned long ulDataSize_p,
1628 		       unsigned long ulAddrOffset_p, const char *pszInfoText_p)
1629 {
1630 
1631 	const unsigned char *pabBuffData;
1632 	unsigned long ulBuffSize;
1633 	unsigned char bData;
1634 	int nRow;
1635 	int nCol;
1636 
1637 	// get pointer to buffer and length of buffer
1638 	pabBuffData = pabStartAddr_p;
1639 	ulBuffSize = ulDataSize_p;
1640 
1641 	if (pszInfoText_p != NULL) {
1642 		TRACE0(pszInfoText_p);
1643 	}
1644 	// dump buffer contents
1645 	for (nRow = 0;; nRow++) {
1646 		TRACE1("\n%08lX:   ",
1647 		       (unsigned long)(nRow * 0x10) + ulAddrOffset_p);
1648 
1649 		for (nCol = 0; nCol < 16; nCol++) {
1650 			if ((unsigned long)nCol < ulBuffSize) {
1651 				TRACE1("%02X ",
1652 				       (unsigned int)*(pabBuffData + nCol));
1653 			} else {
1654 				TRACE0("   ");
1655 			}
1656 		}
1657 
1658 		TRACE0(" ");
1659 
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);
1665 				} else {
1666 					TRACE0(".");
1667 				}
1668 			} else {
1669 				TRACE0(" ");
1670 			}
1671 		}
1672 
1673 		if (ulBuffSize > 16) {
1674 			ulBuffSize -= 16;
1675 		} else {
1676 			break;
1677 		}
1678 	}
1679 
1680 	return (kShbOk);
1681 
1682 }
1683 #endif // #ifndef NDEBUG
1684 
1685 //=========================================================================//
1686 //                                                                         //
1687 //          P R I V A T E   F U N C T I O N S                              //
1688 //                                                                         //
1689 //=========================================================================//
1690 
1691 //---------------------------------------------------------------------------
1692 //  Handler to signal new data event for Circular Shared Buffer
1693 //---------------------------------------------------------------------------
1694 
ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p)1695 int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p)
1696 {
1697 
1698 	tShbCirBuff *pShbCirBuff;
1699 	unsigned long ulDataSize;
1700 	unsigned long ulBlockCount;
1701 	tShbError ShbError;
1702 
1703 	// check arguments
1704 	if (pShbInstance_p == NULL) {
1705 		return FALSE;
1706 	}
1707 
1708 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1709 	ShbError = kShbOk;
1710 
1711 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1712 		return FALSE;
1713 	}
1714 
1715 	// call application handler
1716 	if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1717 /*        do
1718         {*/
1719 		ShbError = ShbCirGetReadDataSize(pShbInstance_p, &ulDataSize);
1720 		if ((ulDataSize > 0) && (ShbError == kShbOk)) {
1721 			pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p,
1722 							  ulDataSize);
1723 		}
1724 
1725 		ShbError =
1726 		    ShbCirGetReadBlockCount(pShbInstance_p, &ulBlockCount);
1727 /*        }
1728         while ((ulBlockCount > 0) && (ShbError == kShbOk));*/
1729 	}
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));
1734 
1735 }
1736 
1737 //---------------------------------------------------------------------------
1738 //  Handler to reset Circular Shared Buffer
1739 //---------------------------------------------------------------------------
1740 
ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,unsigned int fTimeOut_p)1741 void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
1742 			      unsigned int fTimeOut_p)
1743 {
1744 
1745 	tShbCirBuff *pShbCirBuff;
1746 
1747 	// check arguments
1748 	if (pShbInstance_p == NULL) {
1749 		return;
1750 	}
1751 
1752 	pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1753 	if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1754 		return;
1755 	}
1756 
1757 	// reset buffer header
1758 	if (!fTimeOut_p) {
1759 		ShbIpcEnterAtomicSection(pShbInstance_p);
1760 		{
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;
1769 		}
1770 		ShbIpcLeaveAtomicSection(pShbInstance_p);
1771 
1772 #ifndef NDEBUG
1773 		{
1774 			memset(&pShbCirBuff->m_Data, 0xCC,
1775 			       pShbCirBuff->m_ulBufferDataSize);
1776 		}
1777 #endif
1778 	}
1779 
1780 	// call application handler
1781 	if (pShbCirBuff->m_pfnSigHndlrReset != NULL) {
1782 		pShbCirBuff->m_pfnSigHndlrReset(pShbInstance_p, fTimeOut_p);
1783 	}
1784 
1785 	// unlock buffer
1786 	ShbIpcEnterAtomicSection(pShbInstance_p);
1787 	{
1788 		pShbCirBuff->m_fBufferLocked = FALSE;
1789 		pShbCirBuff->m_pfnSigHndlrReset = NULL;
1790 	}
1791 	ShbIpcLeaveAtomicSection(pShbInstance_p);
1792 
1793 	return;
1794 
1795 }
1796 
1797 #endif
1798 
1799 // EOF
1800