Staging: epl: run Lindent on *.c files
[deliverable/linux.git] / drivers / staging / epl / SharedBuff.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
This page took 0.068615 seconds and 5 git commands to generate.