Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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#include <linux/string.h>
89#include <linux/kernel.h>
90
91/***************************************************************************/
92/* */
93/* */
94/* G L O B A L D E F I N I T I O N S */
95/* */
96/* */
97/***************************************************************************/
98
99//---------------------------------------------------------------------------
100// Configuration
101//---------------------------------------------------------------------------
102
103//---------------------------------------------------------------------------
104// Constant definitions
105//---------------------------------------------------------------------------
106
107#define SBC_MAGIC_ID 0x53424323 // magic ID ("SBC#")
108#define SBL_MAGIC_ID 0x53424C23 // magic ID ("SBL#")
109
110//---------------------------------------------------------------------------
111// Local types
112//---------------------------------------------------------------------------
113
114// structure to administrate circular shared buffer head
115typedef struct {
116 unsigned long m_ShbCirMagicID; // magic ID ("SBC#")
117 unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
118 unsigned long m_ulBufferDataSize; // size of complete data area
119 unsigned long m_ulWrIndex; // current write index (set bevore write)
120 unsigned long m_ulRdIndex; // current read index (set after read)
121 unsigned long m_ulNumOfWriteJobs; // number of currently (parallel running) write operations
122 unsigned long m_ulDataInUse; // currently used buffer size (incl. uncompleted write operations)
123 unsigned long m_ulDataApended; // buffer size of complete new written but not yet readable data (in case of m_ulNumOfWriteJobs>1)
124 unsigned long m_ulBlocksApended; // number of complete new written but not yet readable data blocks (in case of m_ulNumOfWriteJobs>1)
125 unsigned long m_ulDataReadable; // buffer size with readable (complete written) data
126 unsigned long m_ulBlocksReadable; // number of readable (complete written) data blocks
127 tShbCirSigHndlrNewData m_pfnSigHndlrNewData; // application handler to signal new data
128 unsigned int m_fBufferLocked; // TRUE if buffer is locked (because of pending reset request)
129 tShbCirSigHndlrReset m_pfnSigHndlrReset; // application handler to signal buffer reset is done
130 unsigned char m_Data; // start of data area (the real data size is unknown at this time)
131
132} tShbCirBuff;
133
134// structure to administrate linear shared buffer head
135typedef struct {
136 unsigned int m_ShbLinMagicID; // magic ID ("SBL#")
137 unsigned long m_ulBufferTotalSize; // over-all size of complete buffer
138 unsigned long m_ulBufferDataSize; // size of complete data area
139 unsigned char m_Data; // start of data area (the real data size is unknown at this time)
140
141} tShbLinBuff;
142
143// type to save size of a single data block inside the circular shared buffer
144typedef struct {
145 unsigned int m_uiFullBlockSize:28; // a single block must not exceed a length of 256MByte :-)
146 unsigned int m_uiAlignFillBytes:4;
147
148} tShbCirBlockSize;
149
150#define SBC_BLOCK_ALIGNMENT 4 // alignment must *not* be lower than sizeof(tShbCirBlockSize)!
151#define SBC_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
152
153#define SBL_BLOCK_ALIGNMENT 4
154#define SBL_MAX_BLOCK_SIZE ((1<<28)-1) // = (2^28 - 1) = (256MByte - 1) -> should be enought for real life :-)
155
156//---------------------------------------------------------------------------
157// Global variables
158//---------------------------------------------------------------------------
159
160//---------------------------------------------------------------------------
161// Local variables
162//---------------------------------------------------------------------------
163
164//---------------------------------------------------------------------------
165// Prototypes of internal functions
166//---------------------------------------------------------------------------
167
168//---------------------------------------------------------------------------
169// Get pointer to Circular Shared Buffer
170//---------------------------------------------------------------------------
171
172tShbCirBuff *ShbCirGetBuffer(tShbInstance pShbInstance_p)
173{
174
175 tShbCirBuff *pShbCirBuff;
176
177 pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
178 ASSERT(pShbCirBuff->m_ShbCirMagicID == SBC_MAGIC_ID);
179
180 return (pShbCirBuff);
181
182}
183
184//---------------------------------------------------------------------------
185// Get pointer to Linear Shared Buffer
186//---------------------------------------------------------------------------
187
188tShbLinBuff *ShbLinGetBuffer(tShbInstance pShbInstance_p)
189{
190
191 tShbLinBuff *pShbLinBuff;
192
193 pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance_p);
194 ASSERT(pShbLinBuff->m_ShbLinMagicID == SBL_MAGIC_ID);
195
196 return (pShbLinBuff);
197
198}
199
200// not inlined internal functions
201int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p);
202void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
203 unsigned int fTimeOut_p);
204
205
206//=========================================================================//
207// //
208// P U B L I C F U N C T I O N S //
209// //
210//=========================================================================//
211
212// not inlined external functions
213
214//---------------------------------------------------------------------------
215// Initialize Shared Buffer Module
216//---------------------------------------------------------------------------
217
218tShbError ShbInit(void)
219{
220
221 tShbError ShbError;
222
223 ShbError = ShbIpcInit();
224
225 return (ShbError);
226
227}
228
229//---------------------------------------------------------------------------
230// Deinitialize Shared Buffer Module
231//---------------------------------------------------------------------------
232
233tShbError ShbExit(void)
234{
235
236 tShbError ShbError;
237
238 ShbError = ShbIpcExit();
239
240 return (ShbError);
241
242}
243
244//-------------------------------------------------------------------------//
245// //
246// C i r c u l a r S h a r e d B u f f e r //
247// //
248//-------------------------------------------------------------------------//
249
250//---------------------------------------------------------------------------
251// Allocate Circular Shared Buffer
252//---------------------------------------------------------------------------
253
254tShbError ShbCirAllocBuffer(unsigned long ulBufferSize_p,
255 const char *pszBufferID_p,
256 tShbInstance * ppShbInstance_p,
257 unsigned int *pfShbNewCreated_p)
258{
259
260 tShbInstance pShbInstance;
261 tShbCirBuff *pShbCirBuff;
262 unsigned int fShbNewCreated;
263 unsigned long ulBufferDataSize;
264 unsigned long ulBufferTotalSize;
265 tShbError ShbError;
266
267 // check arguments
268 if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
269 return (kShbInvalidArg);
270 }
271
272 // calculate length of memory to allocate
273 ulBufferDataSize =
274 (ulBufferSize_p +
275 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
276 ulBufferTotalSize = ulBufferDataSize + sizeof(tShbCirBuff);
277
278 // allocate a new or open an existing shared buffer
279 ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
280 &pShbInstance, &fShbNewCreated);
281 if (ShbError != kShbOk) {
282 goto Exit;
283 }
284
285 if (pShbInstance == NULL) {
286 ShbError = kShbOutOfMem;
287 goto Exit;
288 }
289
290 // get pointer to shared buffer
291 pShbCirBuff = (tShbCirBuff *) ShbIpcGetShMemPtr(pShbInstance);
292
293 // if the shared buffer was new created, than this process has
294 // to initialize it, otherwise the buffer is already in use
295 // and *must not* be reseted
296 if (fShbNewCreated) {
297#ifndef NDEBUG
298 {
299 memset(pShbCirBuff, 0xCC, ulBufferTotalSize);
300 }
301#endif
302
303 pShbCirBuff->m_ShbCirMagicID = SBC_MAGIC_ID;
304 pShbCirBuff->m_ulBufferTotalSize = ulBufferTotalSize;
305 pShbCirBuff->m_ulBufferDataSize = ulBufferDataSize;
306 pShbCirBuff->m_ulWrIndex = 0;
307 pShbCirBuff->m_ulRdIndex = 0;
308 pShbCirBuff->m_ulNumOfWriteJobs = 0;
309 pShbCirBuff->m_ulDataInUse = 0;
310 pShbCirBuff->m_ulDataApended = 0;
311 pShbCirBuff->m_ulBlocksApended = 0;
312 pShbCirBuff->m_ulDataReadable = 0;
313 pShbCirBuff->m_ulBlocksReadable = 0;
314 pShbCirBuff->m_pfnSigHndlrNewData = NULL;
315 pShbCirBuff->m_fBufferLocked = FALSE;
316 pShbCirBuff->m_pfnSigHndlrReset = NULL;
317 } else {
318 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
319 ShbError = kShbInvalidBufferType;
320 goto Exit;
321 }
322 }
323
324 Exit:
325
326 *ppShbInstance_p = pShbInstance;
327 *pfShbNewCreated_p = fShbNewCreated;
328
329 return (ShbError);
330
331}
332
333//---------------------------------------------------------------------------
334// Release Circular Shared Buffer
335//---------------------------------------------------------------------------
336
337tShbError ShbCirReleaseBuffer(tShbInstance pShbInstance_p)
338{
339
340 tShbError ShbError;
341
342 // check arguments
343 if (pShbInstance_p == NULL) {
344 ShbError = kShbOk;
345 goto Exit;
346 }
347
348 ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
349
350 Exit:
351
352 return (ShbError);
353
354}
355
356//---------------------------------------------------------------------------
357// Reset Circular Shared Buffer
358//---------------------------------------------------------------------------
359
360tShbError ShbCirResetBuffer(tShbInstance pShbInstance_p,
361 unsigned long ulTimeOut_p,
362 tShbCirSigHndlrReset pfnSignalHandlerReset_p)
363{
364
365 tShbCirBuff *pShbCirBuff;
366 unsigned long ulNumOfWriteJobs = 0; // d.k. GCC complains about uninitialized variable otherwise
367 tShbError ShbError;
368
369 // check arguments
370 if (pShbInstance_p == NULL) {
371 ShbError = kShbInvalidArg;
372 goto Exit;
373 }
374
375 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
376 ShbError = kShbOk;
377
378 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
379 ShbError = kShbInvalidBufferType;
380 goto Exit;
381 }
382
383 // start reset job by setting request request in buffer header
384 ShbIpcEnterAtomicSection(pShbInstance_p);
385 {
386 if (!pShbCirBuff->m_fBufferLocked) {
387 ulNumOfWriteJobs = pShbCirBuff->m_ulNumOfWriteJobs;
388
389 pShbCirBuff->m_fBufferLocked = TRUE;
390 pShbCirBuff->m_pfnSigHndlrReset =
391 pfnSignalHandlerReset_p;
392 } else {
393 ShbError = kShbAlreadyReseting;
394 }
395 }
396 ShbIpcLeaveAtomicSection(pShbInstance_p);
397
398 if (ShbError != kShbOk) {
399 goto Exit;
400 }
401
402 // if there is currently no running write operation then reset buffer
403 // immediately, otherwise wait until the last write job is ready by
404 // starting a signal process
405 if (ulNumOfWriteJobs == 0) {
406 // there is currently no running write operation
407 // -> reset buffer immediately
408 ShbCirSignalHandlerReset(pShbInstance_p, FALSE);
409 ShbError = kShbOk;
410 } else {
411 // there is currently at least one running write operation
412 // -> starting signal process to wait until the last write job is ready
413 ShbError =
414 ShbIpcStartSignalingJobReady(pShbInstance_p, ulTimeOut_p,
415 ShbCirSignalHandlerReset);
416 }
417
418 Exit:
419
420 return (ShbError);
421
422}
423
424//---------------------------------------------------------------------------
425// Write data block to Circular Shared Buffer
426//---------------------------------------------------------------------------
427
428tShbError ShbCirWriteDataBlock(tShbInstance pShbInstance_p,
429 const void *pSrcDataBlock_p,
430 unsigned long ulDataBlockSize_p)
431{
432
433 tShbCirBuff *pShbCirBuff;
434 tShbCirBlockSize ShbCirBlockSize;
435 unsigned int uiFullBlockSize;
436 unsigned int uiAlignFillBytes;
437 unsigned char *pShbCirDataPtr;
438 unsigned char *pScrDataPtr;
439 unsigned long ulDataSize;
440 unsigned long ulChunkSize;
441 unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
442 unsigned int fSignalNewData;
443 unsigned int fSignalReset;
444 tShbError ShbError;
445 tShbError ShbError2;
446 int fRes;
447
448 // check arguments
449 if (pShbInstance_p == NULL) {
450 ShbError = kShbInvalidArg;
451 goto Exit;
452 }
453
454 if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
455 // nothing to do here
456 ShbError = kShbOk;
457 goto Exit;
458 }
459
460 if (ulDataBlockSize_p > SBC_MAX_BLOCK_SIZE) {
461 ShbError = kShbExceedDataSizeLimit;
462 goto Exit;
463 }
464
465 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
466 pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
467 fSignalNewData = FALSE;
468 fSignalReset = FALSE;
469 ShbError = kShbOk;
470
471 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
472 ShbError = kShbInvalidBufferType;
473 goto Exit;
474 }
475
476 // calculate data block size in circular buffer
477 ulDataSize =
478 (ulDataBlockSize_p +
479 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
480 uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
481 uiAlignFillBytes = ulDataSize - ulDataBlockSize_p;
482
483 ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
484 ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
485
486 // reserve the needed memory for the write operation to do now
487 // and make necessary adjustments in the circular buffer header
488 ShbIpcEnterAtomicSection(pShbInstance_p);
489 {
490 // check if there is sufficient memory available to store
491 // the new data
492 fRes =
493 uiFullBlockSize <=
494 (pShbCirBuff->m_ulBufferDataSize -
495 pShbCirBuff->m_ulDataInUse);
496 if (fRes) {
497 // set write pointer for the write operation to do now
498 // to the current write pointer of the circular buffer
499 ulWrIndex = pShbCirBuff->m_ulWrIndex;
500
501 // reserve the needed memory for the write operation to do now
502 pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
503
504 // set new write pointer behind the reserved memory
505 // for the write operation to do now
506 pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
507 pShbCirBuff->m_ulWrIndex %=
508 pShbCirBuff->m_ulBufferDataSize;
509
510 // increment number of currently (parallel running)
511 // write operations
512 pShbCirBuff->m_ulNumOfWriteJobs++;
513 }
514 }
515 ShbIpcLeaveAtomicSection(pShbInstance_p);
516
517 if (!fRes) {
518 ShbError = kShbBufferFull;
519 goto Exit;
520 }
521
522 // copy the data to the circular buffer
523 // (the copy process itself will be done outside of any
524 // critical/locked section)
525 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
526
527 // write real size of current block (incl. alignment fill bytes)
528 *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
529 ulWrIndex += sizeof(tShbCirBlockSize);
530 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
531
532 if (ulWrIndex + ulDataBlockSize_p <= pShbCirBuff->m_ulBufferDataSize) {
533 // linear write operation
534 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
535 ulDataBlockSize_p);
536 } else {
537 // wrap-around write operation
538 ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
539 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulChunkSize);
540 memcpy(pShbCirDataPtr, pScrDataPtr + ulChunkSize,
541 ulDataBlockSize_p - ulChunkSize);
542 }
543
544 // adjust header information for circular buffer with properties
545 // of the wiritten data block
546 ShbIpcEnterAtomicSection(pShbInstance_p);
547 {
548 pShbCirBuff->m_ulDataApended += uiFullBlockSize;
549 pShbCirBuff->m_ulBlocksApended++;
550
551 // decrement number of currently (parallel running) write operations
552 if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
553 // if there is no other write process running then
554 // set new size of readable (complete written) data and
555 // adjust number of readable blocks
556 pShbCirBuff->m_ulDataReadable +=
557 pShbCirBuff->m_ulDataApended;
558 pShbCirBuff->m_ulBlocksReadable +=
559 pShbCirBuff->m_ulBlocksApended;
560
561 pShbCirBuff->m_ulDataApended = 0;
562 pShbCirBuff->m_ulBlocksApended = 0;
563
564 fSignalNewData = TRUE;
565 fSignalReset = pShbCirBuff->m_fBufferLocked;
566 }
567 }
568 ShbIpcLeaveAtomicSection(pShbInstance_p);
569
570 // signal new data event to a potentially reading application
571 if (fSignalNewData) {
572 ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
573 if (ShbError == kShbOk) {
574 ShbError = ShbError2;
575 }
576 }
577 // signal that the last write job has been finished to allow
578 // a waiting application to reset the buffer now
579 if (fSignalReset) {
580 ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
581 if (ShbError == kShbOk) {
582 ShbError = ShbError2;
583 }
584 }
585
586 Exit:
587
588 return (ShbError);
589
590}
591
592//---------------------------------------------------------------------------
593// Allocate block within the Circular Shared Buffer for chunk writing
594//---------------------------------------------------------------------------
595
596tShbError ShbCirAllocDataBlock(tShbInstance pShbInstance_p,
597 tShbCirChunk * pShbCirChunk_p,
598 unsigned long ulDataBufferSize_p)
599{
600
601 tShbCirBuff *pShbCirBuff;
602 tShbCirBlockSize ShbCirBlockSize;
603 unsigned int uiFullBlockSize;
604 unsigned int uiAlignFillBytes;
605 unsigned char *pShbCirDataPtr;
606 unsigned long ulDataSize;
607 unsigned long ulWrIndex = 0; // d.k. GCC complains about uninitialized variable otherwise
608 tShbError ShbError;
609 int fRes;
610
611 // check arguments
612 if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)) {
613 ShbError = kShbInvalidArg;
614 goto Exit;
615 }
616
617 if (ulDataBufferSize_p == 0) {
618 ShbError = kShbInvalidArg;
619 goto Exit;
620 }
621
622 if (ulDataBufferSize_p > SBC_MAX_BLOCK_SIZE) {
623 ShbError = kShbExceedDataSizeLimit;
624 goto Exit;
625 }
626
627 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
628 ShbError = kShbOk;
629
630 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
631 ShbError = kShbInvalidBufferType;
632 goto Exit;
633 }
634
635 // calculate data block size in circular buffer
636 ulDataSize =
637 (ulDataBufferSize_p +
638 (SBC_BLOCK_ALIGNMENT - 1)) & ~(SBC_BLOCK_ALIGNMENT - 1);
639 uiFullBlockSize = ulDataSize + sizeof(tShbCirBlockSize); // data size + header
640 uiAlignFillBytes = ulDataSize - ulDataBufferSize_p;
641
642 ShbCirBlockSize.m_uiFullBlockSize = uiFullBlockSize;
643 ShbCirBlockSize.m_uiAlignFillBytes = uiAlignFillBytes;
644
645 // reserve the needed memory for the write operation to do now
646 // and make necessary adjustments in the circular buffer header
647 ShbIpcEnterAtomicSection(pShbInstance_p);
648 {
649 // check if there is sufficient memory available to store
650 // the new data
651 fRes =
652 (uiFullBlockSize <=
653 (pShbCirBuff->m_ulBufferDataSize -
654 pShbCirBuff->m_ulDataInUse));
655 if (fRes) {
656 // set write pointer for the write operation to do now
657 // to the current write pointer of the circular buffer
658 ulWrIndex = pShbCirBuff->m_ulWrIndex;
659
660 // reserve the needed memory for the write operation to do now
661 pShbCirBuff->m_ulDataInUse += uiFullBlockSize;
662
663 // set new write pointer behind the reserved memory
664 // for the write operation to do now
665 pShbCirBuff->m_ulWrIndex += uiFullBlockSize;
666 pShbCirBuff->m_ulWrIndex %=
667 pShbCirBuff->m_ulBufferDataSize;
668
669 // increment number of currently (parallel running)
670 // write operations
671 pShbCirBuff->m_ulNumOfWriteJobs++;
672 }
673 }
674 ShbIpcLeaveAtomicSection(pShbInstance_p);
675
676 if (!fRes) {
677 ShbError = kShbBufferFull;
678 goto Exit;
679 }
680
681 // setup header information for allocated buffer
682 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
683
684 // write real size of current block (incl. alignment fill bytes)
685 *(tShbCirBlockSize *) (pShbCirDataPtr + ulWrIndex) = ShbCirBlockSize;
686 ulWrIndex += sizeof(tShbCirBlockSize);
687 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
688
689 // setup chunk descriptor
690 pShbCirChunk_p->m_uiFullBlockSize = uiFullBlockSize;
691 pShbCirChunk_p->m_ulAvailableSize = ulDataBufferSize_p;
692 pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
693 pShbCirChunk_p->m_fBufferCompleted = FALSE;
694
695 Exit:
696
697 return (ShbError);
698
699}
700
701//---------------------------------------------------------------------------
702// Write data chunk into an allocated buffer of the Circular Shared Buffer
703//---------------------------------------------------------------------------
704
705tShbError ShbCirWriteDataChunk(tShbInstance pShbInstance_p,
706 tShbCirChunk *pShbCirChunk_p,
707 const void *pSrcDataChunk_p,
708 unsigned long ulDataChunkSize_p,
709 unsigned int *pfBufferCompleted_p)
710{
711
712 tShbCirBuff *pShbCirBuff;
713 unsigned char *pShbCirDataPtr;
714 unsigned char *pScrDataPtr;
715 unsigned long ulSubChunkSize;
716 unsigned long ulWrIndex;
717 unsigned int fBufferCompleted;
718 unsigned int fSignalNewData;
719 unsigned int fSignalReset;
720 tShbError ShbError;
721 tShbError ShbError2;
722
723 // check arguments
724 if ((pShbInstance_p == NULL) || (pShbCirChunk_p == NULL)
725 || (pfBufferCompleted_p == NULL)) {
726 ShbError = kShbInvalidArg;
727 goto Exit;
728 }
729
730 if ((pSrcDataChunk_p == NULL) || (ulDataChunkSize_p == 0)) {
731 // nothing to do here
732 ShbError = kShbOk;
733 goto Exit;
734 }
735
736 if (pShbCirChunk_p->m_fBufferCompleted) {
737 ShbError = kShbBufferAlreadyCompleted;
738 goto Exit;
739 }
740
741 if (ulDataChunkSize_p > pShbCirChunk_p->m_ulAvailableSize) {
742 ShbError = kShbExceedDataSizeLimit;
743 goto Exit;
744 }
745
746 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
747 pScrDataPtr = (unsigned char *)pSrcDataChunk_p;
748 fSignalNewData = FALSE;
749 fSignalReset = FALSE;
750 ShbError = kShbOk;
751
752 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
753 ShbError = kShbInvalidBufferType;
754 goto Exit;
755 }
756
757 ulWrIndex = pShbCirChunk_p->m_ulWrIndex;
758
759 // copy the data to the circular buffer
760 // (the copy process itself will be done outside of any
761 // critical/locked section)
762 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
763
764 if (ulWrIndex + ulDataChunkSize_p <= pShbCirBuff->m_ulBufferDataSize) {
765 // linear write operation
766 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr,
767 ulDataChunkSize_p);
768 } else {
769 // wrap-around write operation
770 ulSubChunkSize = pShbCirBuff->m_ulBufferDataSize - ulWrIndex;
771 memcpy(pShbCirDataPtr + ulWrIndex, pScrDataPtr, ulSubChunkSize);
772 memcpy(pShbCirDataPtr, pScrDataPtr + ulSubChunkSize,
773 ulDataChunkSize_p - ulSubChunkSize);
774 }
775
776 // adjust chunk descriptor
777 ulWrIndex += ulDataChunkSize_p;
778 ulWrIndex %= pShbCirBuff->m_ulBufferDataSize;
779
780 pShbCirChunk_p->m_ulAvailableSize -= ulDataChunkSize_p;
781 pShbCirChunk_p->m_ulWrIndex = ulWrIndex;
782
783 fBufferCompleted = (pShbCirChunk_p->m_ulAvailableSize == 0);
784 pShbCirChunk_p->m_fBufferCompleted = fBufferCompleted;
785
786 // if the complete allocated buffer is filled with data then
787 // adjust header information for circular buffer with properties
788 // of the wiritten data block
789 if (fBufferCompleted) {
790 ShbIpcEnterAtomicSection(pShbInstance_p);
791 {
792 pShbCirBuff->m_ulDataApended +=
793 pShbCirChunk_p->m_uiFullBlockSize;
794 pShbCirBuff->m_ulBlocksApended++;
795
796 // decrement number of currently (parallel running) write operations
797 if (!--pShbCirBuff->m_ulNumOfWriteJobs) {
798 // if there is no other write process running then
799 // set new size of readable (complete written) data and
800 // adjust number of readable blocks
801 pShbCirBuff->m_ulDataReadable +=
802 pShbCirBuff->m_ulDataApended;
803 pShbCirBuff->m_ulBlocksReadable +=
804 pShbCirBuff->m_ulBlocksApended;
805
806 pShbCirBuff->m_ulDataApended = 0;
807 pShbCirBuff->m_ulBlocksApended = 0;
808
809 fSignalNewData = TRUE;
810 fSignalReset = pShbCirBuff->m_fBufferLocked;
811 }
812 }
813 ShbIpcLeaveAtomicSection(pShbInstance_p);
814 }
815
816 // signal new data event to a potentially reading application
817 if (fSignalNewData) {
818 ShbError2 = ShbIpcSignalNewData(pShbInstance_p);
819 if (ShbError == kShbOk) {
820 ShbError = ShbError2;
821 }
822 }
823 // signal that the last write job has been finished to allow
824 // a waiting application to reset the buffer now
825 if (fSignalReset) {
826 ShbError2 = ShbIpcSignalJobReady(pShbInstance_p);
827 if (ShbError == kShbOk) {
828 ShbError = ShbError2;
829 }
830 }
831
832 *pfBufferCompleted_p = fBufferCompleted;
833
834 Exit:
835
836 return (ShbError);
837
838}
839
840//---------------------------------------------------------------------------
841// Read data block from Circular Shared Buffer
842//---------------------------------------------------------------------------
843
844tShbError ShbCirReadDataBlock(tShbInstance pShbInstance_p,
845 void *pDstDataBlock_p,
846 unsigned long ulRdBuffSize_p,
847 unsigned long *pulDataBlockSize_p)
848{
849
850 tShbCirBuff *pShbCirBuff;
851 tShbCirBlockSize ShbCirBlockSize;
852 unsigned long ulDataReadable;
853 unsigned char *pShbCirDataPtr;
854 unsigned char *pDstDataPtr;
855 unsigned long ulDataSize = 0; // d.k. GCC complains about uninitialized variable otherwise
856 unsigned long ulChunkSize;
857 unsigned long ulRdIndex;
858 tShbError ShbError;
859
860 // check arguments
861 if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
862 return (kShbInvalidArg);
863 }
864
865 if ((pDstDataBlock_p == NULL) || (ulRdBuffSize_p == 0)) {
866 // nothing to do here
867 ShbError = kShbOk;
868 goto Exit;
869 }
870
871 ShbError = kShbOk;
872 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
873 pDstDataPtr = (unsigned char *)pDstDataBlock_p;
874 ulDataSize = 0;
875
876 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
877 ShbError = kShbInvalidBufferType;
878 goto Exit;
879 }
880
881 // get total number of readable bytes for the whole circular buffer
882 ShbIpcEnterAtomicSection(pShbInstance_p);
883 {
884 ulDataReadable = pShbCirBuff->m_ulDataReadable;
885 }
886 ShbIpcLeaveAtomicSection(pShbInstance_p);
887
888 // if there are readable data available, then there must be at least
889 // one complete readable data block
890 if (ulDataReadable > 0) {
891 // get pointer to start of data area and current read index
892 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
893 ulRdIndex = pShbCirBuff->m_ulRdIndex;
894
895 // get real size of current block (incl. alignment fill bytes)
896 ShbCirBlockSize =
897 *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
898 ulRdIndex += sizeof(tShbCirBlockSize);
899 ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
900
901 // get size of user data inside the current block
902 ulDataSize =
903 ShbCirBlockSize.m_uiFullBlockSize -
904 ShbCirBlockSize.m_uiAlignFillBytes;
905 ulDataSize -= sizeof(tShbCirBlockSize);
906 }
907
908 // ulDataSize = MIN(ulDataSize, ulRdBuffSize_p);
909 if (ulDataSize > ulRdBuffSize_p) {
910 ulDataSize = ulRdBuffSize_p;
911 ShbError = kShbDataTruncated;
912 }
913
914 if (ulDataSize == 0) {
915 // nothing to do here
916 ShbError = kShbNoReadableData;
917 goto Exit;
918 }
919
920 // copy the data from the circular buffer
921 // (the copy process itself will be done outside of any
922 // critical/locked section)
923 if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
924 // linear read operation
925 memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulDataSize);
926 } else {
927 // wrap-around read operation
928 ulChunkSize = pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
929 memcpy(pDstDataPtr, pShbCirDataPtr + ulRdIndex, ulChunkSize);
930 memcpy(pDstDataPtr + ulChunkSize, pShbCirDataPtr,
931 ulDataSize - ulChunkSize);
932 }
933
934#ifndef NDEBUG
935 {
936 tShbCirBlockSize ClrShbCirBlockSize;
937
938 if (ulRdIndex + ulDataSize <= pShbCirBuff->m_ulBufferDataSize) {
939 // linear buffer
940 memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulDataSize);
941 } else {
942 // wrap-around read operation
943 ulChunkSize =
944 pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
945 memset(pShbCirDataPtr + ulRdIndex, 0xDD, ulChunkSize);
946 memset(pShbCirDataPtr, 0xDD, ulDataSize - ulChunkSize);
947 }
948
949 ClrShbCirBlockSize.m_uiFullBlockSize = /*(unsigned int) */ -1; // -1 = xFFFFFFF
950 ClrShbCirBlockSize.m_uiAlignFillBytes = /*(unsigned int) */ -1; // -1 = Fxxxxxxx
951 *(tShbCirBlockSize *) (pShbCirDataPtr +
952 pShbCirBuff->m_ulRdIndex) =
953 ClrShbCirBlockSize;
954 }
955#endif // #ifndef NDEBUG
956
957 // set new size of readable data, data in use, new read index
958 // and adjust number of readable blocks
959 ShbIpcEnterAtomicSection(pShbInstance_p);
960 {
961 pShbCirBuff->m_ulDataInUse -= ShbCirBlockSize.m_uiFullBlockSize;
962 pShbCirBuff->m_ulDataReadable -=
963 ShbCirBlockSize.m_uiFullBlockSize;
964 pShbCirBuff->m_ulBlocksReadable--;
965
966 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
967 if ((pShbCirBuff->m_ulDataInUse == 0)
968 && (pShbCirBuff->m_ulDataReadable == 0)) {
969 ASSERT(pShbCirBuff->m_ulBlocksReadable == 0);
970
971 pShbCirBuff->m_ulWrIndex = 0;
972 pShbCirBuff->m_ulRdIndex = 0;
973 } else
974 //$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
975 {
976 pShbCirBuff->m_ulRdIndex +=
977 ShbCirBlockSize.m_uiFullBlockSize;
978 pShbCirBuff->m_ulRdIndex %=
979 pShbCirBuff->m_ulBufferDataSize;
980 }
981 }
982 ShbIpcLeaveAtomicSection(pShbInstance_p);
983
984 Exit:
985
986 *pulDataBlockSize_p = ulDataSize;
987
988 return (ShbError);
989
990}
991
992//---------------------------------------------------------------------------
993// Get data size of next readable block from Circular Shared Buffer
994//---------------------------------------------------------------------------
995
996tShbError ShbCirGetReadDataSize(tShbInstance pShbInstance_p,
997 unsigned long *pulDataBlockSize_p)
998{
999
1000 tShbCirBuff *pShbCirBuff;
1001 unsigned long ulDataReadable;
1002 unsigned char *pShbCirDataPtr;
1003 tShbCirBlockSize ShbCirBlockSize;
1004 unsigned long ulDataSize;
1005 tShbError ShbError;
1006
1007 // check arguments
1008 if ((pShbInstance_p == NULL) || (pulDataBlockSize_p == NULL)) {
1009 return (kShbInvalidArg);
1010 }
1011
1012 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1013 ulDataSize = 0;
1014 ShbError = kShbOk;
1015
1016 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1017 ShbError = kShbInvalidBufferType;
1018 goto Exit;
1019 }
1020
1021 // get total number of readable bytes for the whole circular buffer
1022 ShbIpcEnterAtomicSection(pShbInstance_p);
1023 {
1024 ulDataReadable = pShbCirBuff->m_ulDataReadable;
1025 }
1026 ShbIpcLeaveAtomicSection(pShbInstance_p);
1027
1028 // if there are readable data available, then there must be at least
1029 // one complete readable data block
1030 if (ulDataReadable > 0) {
1031 pShbCirDataPtr =
1032 &pShbCirBuff->m_Data + pShbCirBuff->m_ulRdIndex;
1033
1034 // get real size of current block (incl. alignment fill bytes)
1035 ShbCirBlockSize = *(tShbCirBlockSize *) pShbCirDataPtr;
1036
1037 // get size of user data inside the current block
1038 ulDataSize =
1039 ShbCirBlockSize.m_uiFullBlockSize -
1040 ShbCirBlockSize.m_uiAlignFillBytes;
1041 ulDataSize -= sizeof(tShbCirBlockSize);
1042 }
1043
1044 Exit:
1045
1046 *pulDataBlockSize_p = ulDataSize;
1047
1048 return (ShbError);
1049
1050}
1051
1052//---------------------------------------------------------------------------
1053// Get number of readable blocks from Circular Shared Buffer
1054//---------------------------------------------------------------------------
1055
1056tShbError ShbCirGetReadBlockCount(tShbInstance pShbInstance_p,
1057 unsigned long *pulDataBlockCount_p)
1058{
1059
1060 tShbCirBuff *pShbCirBuff;
1061 unsigned long ulBlockCount;
1062 tShbError ShbError;
1063
1064 // check arguments
1065 if ((pShbInstance_p == NULL) || (pulDataBlockCount_p == NULL)) {
1066 ShbError = kShbInvalidArg;
1067 goto Exit;
1068 }
1069
1070 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1071 ulBlockCount = 0;
1072 ShbError = kShbOk;
1073
1074 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1075 ShbError = kShbInvalidBufferType;
1076 goto Exit;
1077 }
1078
1079 ShbIpcEnterAtomicSection(pShbInstance_p);
1080 {
1081 ulBlockCount = pShbCirBuff->m_ulBlocksReadable;
1082 }
1083 ShbIpcLeaveAtomicSection(pShbInstance_p);
1084
1085 *pulDataBlockCount_p = ulBlockCount;
1086
1087 Exit:
1088
1089 return (ShbError);
1090
1091}
1092
1093//---------------------------------------------------------------------------
1094// Set application handler to signal new data for Circular Shared Buffer
1095// d.k.: new parameter priority as enum
1096//---------------------------------------------------------------------------
1097
1098tShbError ShbCirSetSignalHandlerNewData(tShbInstance pShbInstance_p,
1099 tShbCirSigHndlrNewData pfnSignalHandlerNewData_p,
1100 tShbPriority ShbPriority_p)
1101{
1102
1103 tShbCirBuff *pShbCirBuff;
1104 tShbError ShbError;
1105
1106 // check arguments
1107 if (pShbInstance_p == NULL) {
1108 ShbError = kShbInvalidArg;
1109 goto Exit;
1110 }
1111
1112 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1113 ShbError = kShbOk;
1114
1115 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1116 ShbError = kShbInvalidBufferType;
1117 goto Exit;
1118 }
1119
1120 if (pfnSignalHandlerNewData_p != NULL) {
1121 // set a new signal handler
1122 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1123 ShbError = kShbAlreadySignaling;
1124 goto Exit;
1125 }
1126
1127 pShbCirBuff->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
1128 ShbError =
1129 ShbIpcStartSignalingNewData(pShbInstance_p,
1130 ShbCirSignalHandlerNewData,
1131 ShbPriority_p);
1132 } else {
1133 // remove existing signal handler
1134 ShbError = ShbIpcStopSignalingNewData(pShbInstance_p);
1135 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1136 pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p, 0);
1137 }
1138 pShbCirBuff->m_pfnSigHndlrNewData = NULL;
1139 }
1140
1141 Exit:
1142
1143 return (ShbError);
1144
1145}
1146
1147//---------------------------------------------------------------------------
1148// DEBUG: Trace Circular Shared Buffer
1149//---------------------------------------------------------------------------
1150
1151#ifndef NDEBUG
1152tShbError ShbCirTraceBuffer(tShbInstance pShbInstance_p)
1153{
1154
1155 tShbCirBuff *pShbCirBuff;
1156 char szMagigID[sizeof(SBC_MAGIC_ID) + 1];
1157 tShbCirBlockSize ShbCirBlockSize;
1158 unsigned long ulDataReadable;
1159 unsigned char *pShbCirDataPtr;
1160 unsigned long ulBlockIndex;
1161 unsigned int nBlockCount;
1162 unsigned long ulDataSize;
1163 unsigned long ulChunkSize;
1164 unsigned long ulRdIndex;
1165 tShbError ShbError;
1166
1167 TRACE0("\n\n##### Circular Shared Buffer #####\n");
1168
1169 // check arguments
1170 if (pShbInstance_p == NULL) {
1171 TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1172 (unsigned long)pShbInstance_p);
1173 ShbError = kShbInvalidArg;
1174 goto Exit;
1175 }
1176
1177 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1178 ShbError = kShbOk;
1179
1180 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1181 ShbError = kShbInvalidBufferType;
1182 goto Exit;
1183 }
1184
1185 *(unsigned long *)&szMagigID[0] = pShbCirBuff->m_ShbCirMagicID;
1186 szMagigID[sizeof(SBC_MAGIC_ID)] = '\0';
1187
1188 ShbIpcEnterAtomicSection(pShbInstance_p);
1189 {
1190 TRACE1("\nBuffer Address: 0x%08lX\n",
1191 (unsigned long)pShbCirBuff);
1192
1193 TRACE0("\nHeader Info:");
1194 TRACE2("\nMagigID: '%s' (%08lX)", szMagigID,
1195 pShbCirBuff->m_ShbCirMagicID);
1196 TRACE1("\nBufferTotalSize: %4lu [Bytes]",
1197 pShbCirBuff->m_ulBufferTotalSize);
1198 TRACE1("\nBufferDataSize: %4lu [Bytes]",
1199 pShbCirBuff->m_ulBufferDataSize);
1200 TRACE1("\nWrIndex: %4lu", pShbCirBuff->m_ulWrIndex);
1201 TRACE1("\nRdIndex: %4lu", pShbCirBuff->m_ulRdIndex);
1202 TRACE1("\nNumOfWriteJobs: %4lu",
1203 pShbCirBuff->m_ulNumOfWriteJobs);
1204 TRACE1("\nDataInUse: %4lu [Bytes]",
1205 pShbCirBuff->m_ulDataInUse);
1206 TRACE1("\nDataApended: %4lu [Bytes]",
1207 pShbCirBuff->m_ulDataApended);
1208 TRACE1("\nBlocksApended: %4lu",
1209 pShbCirBuff->m_ulBlocksApended);
1210 TRACE1("\nDataReadable: %4lu [Bytes]",
1211 pShbCirBuff->m_ulDataReadable);
1212 TRACE1("\nBlocksReadable: %4lu",
1213 pShbCirBuff->m_ulBlocksReadable);
1214 TRACE1("\nSigHndlrNewData: %08lX",
1215 (unsigned long)pShbCirBuff->m_pfnSigHndlrNewData);
1216 TRACE1("\nBufferLocked: %d", pShbCirBuff->m_fBufferLocked);
1217 TRACE1("\nSigHndlrReset: %08lX",
1218 (unsigned long)pShbCirBuff->m_pfnSigHndlrReset);
1219
1220 ShbTraceDump(&pShbCirBuff->m_Data,
1221 pShbCirBuff->m_ulBufferDataSize, 0x00000000L,
1222 "\nData Area:");
1223
1224 ulDataReadable = pShbCirBuff->m_ulDataReadable;
1225 nBlockCount = 1;
1226 ulBlockIndex = pShbCirBuff->m_ulRdIndex;
1227
1228 while (ulDataReadable > 0) {
1229 TRACE1("\n\n--- Block #%u ---", nBlockCount);
1230
1231 // get pointer to start of data area and current read index
1232 pShbCirDataPtr = &pShbCirBuff->m_Data; // ptr to start of data area
1233 ulRdIndex = ulBlockIndex;
1234
1235 // get real size of current block (incl. alignment fill bytes)
1236 ShbCirBlockSize =
1237 *(tShbCirBlockSize *) (pShbCirDataPtr + ulRdIndex);
1238 ulRdIndex += sizeof(tShbCirBlockSize);
1239 ulRdIndex %= pShbCirBuff->m_ulBufferDataSize;
1240
1241 // get size of user data inside the current block
1242 ulDataSize =
1243 ShbCirBlockSize.m_uiFullBlockSize -
1244 ShbCirBlockSize.m_uiAlignFillBytes;
1245 ulDataSize -= sizeof(tShbCirBlockSize);
1246
1247 TRACE1
1248 ("\nFull Data Size: %4u [Bytes] (incl. header and alignment fill bytes)",
1249 ShbCirBlockSize.m_uiFullBlockSize);
1250 TRACE1("\nUser Data Size: %4lu [Bytes]",
1251 ulDataSize);
1252 TRACE1("\nAlignment Fill Bytes: %4u [Bytes]",
1253 ShbCirBlockSize.m_uiAlignFillBytes);
1254
1255 if (ulRdIndex + ulDataSize <=
1256 pShbCirBuff->m_ulBufferDataSize) {
1257 // linear data buffer
1258 ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1259 ulDataSize, 0x00000000L, NULL);
1260 } else {
1261 // wrap-around data buffer
1262 ulChunkSize =
1263 pShbCirBuff->m_ulBufferDataSize - ulRdIndex;
1264 ShbTraceDump(pShbCirDataPtr + ulRdIndex,
1265 ulChunkSize, 0x00000000L, NULL);
1266 ShbTraceDump(pShbCirDataPtr,
1267 ulDataSize - ulChunkSize,
1268 ulChunkSize, NULL);
1269 }
1270
1271 nBlockCount++;
1272
1273 ulBlockIndex += ShbCirBlockSize.m_uiFullBlockSize;
1274 ulBlockIndex %= pShbCirBuff->m_ulBufferDataSize;
1275
1276 ulDataReadable -= ShbCirBlockSize.m_uiFullBlockSize;
1277 }
1278
1279 ASSERT(pShbCirBuff->m_ulBlocksReadable == nBlockCount - 1);
1280 }
1281 ShbIpcLeaveAtomicSection(pShbInstance_p);
1282
1283 Exit:
1284
1285 return (ShbError);
1286
1287}
1288#endif
1289
1290//-------------------------------------------------------------------------//
1291// //
1292// L i n e a r S h a r e d B u f f e r //
1293// //
1294//-------------------------------------------------------------------------//
1295
1296//---------------------------------------------------------------------------
1297// Allocate Linear Shared Buffer
1298//---------------------------------------------------------------------------
1299
1300tShbError ShbLinAllocBuffer(unsigned long ulBufferSize_p,
1301 const char *pszBufferID_p,
1302 tShbInstance * ppShbInstance_p,
1303 unsigned int *pfShbNewCreated_p)
1304{
1305
1306 tShbInstance pShbInstance;
1307 tShbLinBuff *pShbLinBuff;
1308 unsigned int fShbNewCreated;
1309 unsigned long ulBufferDataSize;
1310 unsigned long ulBufferTotalSize;
1311 tShbError ShbError;
1312
1313 // check arguments
1314 if ((ulBufferSize_p == 0) || (ppShbInstance_p == NULL)) {
1315 return (kShbInvalidArg);
1316 }
1317
1318 // calculate length of memory to allocate
1319 ulBufferDataSize =
1320 (ulBufferSize_p +
1321 (SBL_BLOCK_ALIGNMENT - 1)) & ~(SBL_BLOCK_ALIGNMENT - 1);
1322 ulBufferTotalSize = ulBufferDataSize + sizeof(tShbLinBuff);
1323
1324 // allocate a new or open an existing shared buffer
1325 ShbError = ShbIpcAllocBuffer(ulBufferTotalSize, pszBufferID_p,
1326 &pShbInstance, &fShbNewCreated);
1327 if (ShbError != kShbOk) {
1328 goto Exit;
1329 }
1330
1331 if (pShbInstance == NULL) {
1332 ShbError = kShbOutOfMem;
1333 goto Exit;
1334 }
1335
1336 // get pointer to shared buffer
1337 pShbLinBuff = (tShbLinBuff *) ShbIpcGetShMemPtr(pShbInstance);
1338
1339 // if the shared buffer was new created, than this process has
1340 // to initialize it, otherwise the buffer is already in use
1341 // and *must not* be reseted
1342 if (fShbNewCreated) {
1343#ifndef NDEBUG
1344 {
1345 memset(pShbLinBuff, 0xCC, ulBufferTotalSize);
1346 }
1347#endif
1348
1349 pShbLinBuff->m_ShbLinMagicID = SBL_MAGIC_ID;
1350 pShbLinBuff->m_ulBufferTotalSize = ulBufferTotalSize;
1351 pShbLinBuff->m_ulBufferDataSize = ulBufferDataSize;
1352 } else {
1353 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1354 ShbError = kShbInvalidBufferType;
1355 goto Exit;
1356 }
1357 }
1358
1359 Exit:
1360
1361 *ppShbInstance_p = pShbInstance;
1362 *pfShbNewCreated_p = fShbNewCreated;
1363
1364 return (ShbError);
1365
1366}
1367
1368//---------------------------------------------------------------------------
1369// Release Linear Shared Buffer
1370//---------------------------------------------------------------------------
1371
1372tShbError ShbLinReleaseBuffer(tShbInstance pShbInstance_p)
1373{
1374
1375 tShbError ShbError;
1376
1377 // check arguments
1378 if (pShbInstance_p == NULL) {
1379 ShbError = kShbOk;
1380 goto Exit;
1381 }
1382
1383 ShbError = ShbIpcReleaseBuffer(pShbInstance_p);
1384
1385 Exit:
1386
1387 return (ShbError);
1388
1389}
1390
1391//---------------------------------------------------------------------------
1392// Write data block to Linear Shared Buffer
1393//---------------------------------------------------------------------------
1394tShbError ShbLinWriteDataBlock(tShbInstance pShbInstance_p,
1395 unsigned long ulDstBufferOffs_p,
1396 const void *pSrcDataBlock_p,
1397 unsigned long ulDataBlockSize_p)
1398{
1399
1400 tShbLinBuff *pShbLinBuff;
1401 unsigned char *pShbLinDataPtr;
1402 unsigned char *pScrDataPtr;
1403 unsigned long ulBufferDataSize;
1404 tShbError ShbError;
1405
1406 // check arguments
1407 if (pShbInstance_p == NULL) {
1408 ShbError = kShbInvalidArg;
1409 goto Exit;
1410 }
1411
1412 if ((pSrcDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1413 // nothing to do here
1414 ShbError = kShbOk;
1415 goto Exit;
1416 }
1417
1418 if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1419 ShbError = kShbExceedDataSizeLimit;
1420 goto Exit;
1421 }
1422
1423 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1424 pScrDataPtr = (unsigned char *)pSrcDataBlock_p;
1425 ShbError = kShbOk;
1426
1427 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1428 ShbError = kShbInvalidBufferType;
1429 goto Exit;
1430 }
1431
1432 // check if offeset and size for the write operation matches with
1433 // the size of the shared buffer
1434 ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
1435 if ((ulDstBufferOffs_p > ulBufferDataSize) ||
1436 (ulDataBlockSize_p > ulBufferDataSize) ||
1437 ((ulDstBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
1438 ShbError = kShbDataOutsideBufferArea;
1439 goto Exit;
1440 }
1441
1442 // copy the data to the linear buffer
1443 // (the copy process will be done inside of any critical/locked section)
1444 pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
1445 pShbLinDataPtr += ulDstBufferOffs_p;
1446
1447 ShbIpcEnterAtomicSection(pShbInstance_p);
1448 {
1449 memcpy(pShbLinDataPtr, pScrDataPtr, ulDataBlockSize_p);
1450 }
1451 ShbIpcLeaveAtomicSection(pShbInstance_p);
1452
1453 Exit:
1454
1455 return (ShbError);
1456
1457}
1458
1459//---------------------------------------------------------------------------
1460// Read data block from Linear Shared Buffer
1461//---------------------------------------------------------------------------
1462tShbError ShbLinReadDataBlock(tShbInstance pShbInstance_p,
1463 void *pDstDataBlock_p,
1464 unsigned long ulSrcBufferOffs_p,
1465 unsigned long ulDataBlockSize_p)
1466{
1467
1468 tShbLinBuff *pShbLinBuff;
1469 unsigned char *pShbLinDataPtr;
1470 unsigned char *pDstDataPtr;
1471 unsigned long ulBufferDataSize;
1472 tShbError ShbError;
1473
1474 // check arguments
1475 if (pShbInstance_p == NULL) {
1476 ShbError = kShbInvalidArg;
1477 goto Exit;
1478 }
1479
1480 if ((pDstDataBlock_p == NULL) || (ulDataBlockSize_p == 0)) {
1481 // nothing to do here
1482 ShbError = kShbOk;
1483 goto Exit;
1484 }
1485
1486 if (ulDataBlockSize_p > SBL_MAX_BLOCK_SIZE) {
1487 ShbError = kShbExceedDataSizeLimit;
1488 goto Exit;
1489 }
1490
1491 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1492 pDstDataPtr = (unsigned char *)pDstDataBlock_p;
1493 ShbError = kShbOk;
1494
1495 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1496 ShbError = kShbInvalidBufferType;
1497 goto Exit;
1498 }
1499
1500 // check if offeset and size for the read operation matches with
1501 // the size of the shared buffer
1502 ulBufferDataSize = pShbLinBuff->m_ulBufferDataSize;
1503 if ((ulSrcBufferOffs_p > ulBufferDataSize) ||
1504 (ulDataBlockSize_p > ulBufferDataSize) ||
1505 ((ulSrcBufferOffs_p + ulDataBlockSize_p) > ulBufferDataSize)) {
1506 ShbError = kShbDataOutsideBufferArea;
1507 goto Exit;
1508 }
1509
1510 // copy the data to the linear buffer
1511 // (the copy process will be done inside of any critical/locked section)
1512 pShbLinDataPtr = &pShbLinBuff->m_Data; // ptr to start of data area
1513 pShbLinDataPtr += ulSrcBufferOffs_p;
1514
1515 ShbIpcEnterAtomicSection(pShbInstance_p);
1516 {
1517 memcpy(pDstDataPtr, pShbLinDataPtr, ulDataBlockSize_p);
1518 }
1519 ShbIpcLeaveAtomicSection(pShbInstance_p);
1520
1521 Exit:
1522
1523 return (ShbError);
1524
1525}
1526
1527//---------------------------------------------------------------------------
1528// DEBUG: Trace Linear Shared Buffer
1529//---------------------------------------------------------------------------
1530
1531#ifndef NDEBUG
1532tShbError ShbLinTraceBuffer(tShbInstance pShbInstance_p)
1533{
1534
1535 tShbLinBuff *pShbLinBuff;
1536 char szMagigID[sizeof(SBL_MAGIC_ID) + 1];
1537 tShbError ShbError;
1538
1539 TRACE0("\n\n##### Linear Shared Buffer #####\n");
1540
1541 // check arguments
1542 if (pShbInstance_p == NULL) {
1543 TRACE1("\nERROR: invalid buffer address (0x%08lX)\n",
1544 (unsigned long)pShbInstance_p);
1545 ShbError = kShbInvalidArg;
1546 goto Exit;
1547 }
1548
1549 pShbLinBuff = ShbLinGetBuffer(pShbInstance_p);
1550 ShbError = kShbOk;
1551
1552 if (pShbLinBuff->m_ShbLinMagicID != SBL_MAGIC_ID) {
1553 ShbError = kShbInvalidBufferType;
1554 goto Exit;
1555 }
1556
1557 *(unsigned int *)&szMagigID[0] = pShbLinBuff->m_ShbLinMagicID;
1558 szMagigID[sizeof(SBL_MAGIC_ID)] = '\0';
1559
1560 ShbIpcEnterAtomicSection(pShbInstance_p);
1561 {
1562 TRACE1("\nBuffer Address: 0x%08lX\n",
1563 (unsigned long)pShbLinBuff);
1564
1565 TRACE0("\nHeader Info:");
1566 TRACE2("\nMagigID: '%s' (%08X)", szMagigID,
1567 pShbLinBuff->m_ShbLinMagicID);
1568 TRACE1("\nBufferTotalSize: %4lu [Bytes]",
1569 pShbLinBuff->m_ulBufferTotalSize);
1570 TRACE1("\nBufferDataSize: %4lu [Bytes]",
1571 pShbLinBuff->m_ulBufferDataSize);
1572
1573 ShbTraceDump(&pShbLinBuff->m_Data,
1574 pShbLinBuff->m_ulBufferDataSize, 0x00000000L,
1575 "\nData Area:");
1576 }
1577 ShbIpcLeaveAtomicSection(pShbInstance_p);
1578
1579 Exit:
1580
1581 return (ShbError);
1582
1583}
1584#endif
1585
1586//---------------------------------------------------------------------------
1587// Dump buffer contents
1588//---------------------------------------------------------------------------
1589
1590#ifndef NDEBUG
1591tShbError ShbTraceDump(const unsigned char *pabStartAddr_p,
1592 unsigned long ulDataSize_p,
1593 unsigned long ulAddrOffset_p, const char *pszInfoText_p)
1594{
1595
1596 const unsigned char *pabBuffData;
1597 unsigned long ulBuffSize;
1598 unsigned char bData;
1599 int nRow;
1600 int nCol;
1601
1602 // get pointer to buffer and length of buffer
1603 pabBuffData = pabStartAddr_p;
1604 ulBuffSize = ulDataSize_p;
1605
1606 if (pszInfoText_p != NULL) {
1607 TRACE1("%s", pszInfoText_p);
1608 }
1609 // dump buffer contents
1610 for (nRow = 0;; nRow++) {
1611 TRACE1("\n%08lX: ",
1612 (unsigned long)(nRow * 0x10) + ulAddrOffset_p);
1613
1614 for (nCol = 0; nCol < 16; nCol++) {
1615 if ((unsigned long)nCol < ulBuffSize) {
1616 TRACE1("%02X ",
1617 (unsigned int)*(pabBuffData + nCol));
1618 } else {
1619 TRACE0(" ");
1620 }
1621 }
1622
1623 TRACE0(" ");
1624
1625 for (nCol = 0; nCol < 16; nCol++) {
1626 bData = *pabBuffData++;
1627 if ((unsigned long)nCol < ulBuffSize) {
1628 if ((bData >= 0x20) && (bData < 0x7F)) {
1629 TRACE1("%c", bData);
1630 } else {
1631 TRACE0(".");
1632 }
1633 } else {
1634 TRACE0(" ");
1635 }
1636 }
1637
1638 if (ulBuffSize > 16) {
1639 ulBuffSize -= 16;
1640 } else {
1641 break;
1642 }
1643 }
1644
1645 return (kShbOk);
1646
1647}
1648#endif // #ifndef NDEBUG
1649
1650//=========================================================================//
1651// //
1652// P R I V A T E F U N C T I O N S //
1653// //
1654//=========================================================================//
1655
1656//---------------------------------------------------------------------------
1657// Handler to signal new data event for Circular Shared Buffer
1658//---------------------------------------------------------------------------
1659
1660int ShbCirSignalHandlerNewData(tShbInstance pShbInstance_p)
1661{
1662
1663 tShbCirBuff *pShbCirBuff;
1664 unsigned long ulDataSize;
1665 unsigned long ulBlockCount;
1666 tShbError ShbError;
1667
1668 // check arguments
1669 if (pShbInstance_p == NULL) {
1670 return FALSE;
1671 }
1672
1673 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1674 ShbError = kShbOk;
1675
1676 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1677 return FALSE;
1678 }
1679
1680 // call application handler
1681 if (pShbCirBuff->m_pfnSigHndlrNewData != NULL) {
1682/* do
1683 {*/
1684 ShbError = ShbCirGetReadDataSize(pShbInstance_p, &ulDataSize);
1685 if ((ulDataSize > 0) && (ShbError == kShbOk)) {
1686 pShbCirBuff->m_pfnSigHndlrNewData(pShbInstance_p,
1687 ulDataSize);
1688 }
1689
1690 ShbError =
1691 ShbCirGetReadBlockCount(pShbInstance_p, &ulBlockCount);
1692/* }
1693 while ((ulBlockCount > 0) && (ShbError == kShbOk));*/
1694 }
1695 // Return TRUE if there are pending blocks.
1696 // In that case ShbIpc tries to call this function again immediately if there
1697 // is no other filled shared buffer with higher priority.
1698 return ((ulBlockCount > 0) && (ShbError == kShbOk));
1699
1700}
1701
1702//---------------------------------------------------------------------------
1703// Handler to reset Circular Shared Buffer
1704//---------------------------------------------------------------------------
1705
1706void ShbCirSignalHandlerReset(tShbInstance pShbInstance_p,
1707 unsigned int fTimeOut_p)
1708{
1709
1710 tShbCirBuff *pShbCirBuff;
1711
1712 // check arguments
1713 if (pShbInstance_p == NULL) {
1714 return;
1715 }
1716
1717 pShbCirBuff = ShbCirGetBuffer(pShbInstance_p);
1718 if (pShbCirBuff->m_ShbCirMagicID != SBC_MAGIC_ID) {
1719 return;
1720 }
1721
1722 // reset buffer header
1723 if (!fTimeOut_p) {
1724 ShbIpcEnterAtomicSection(pShbInstance_p);
1725 {
1726 pShbCirBuff->m_ulWrIndex = 0;
1727 pShbCirBuff->m_ulRdIndex = 0;
1728 pShbCirBuff->m_ulNumOfWriteJobs = 0;
1729 pShbCirBuff->m_ulDataInUse = 0;
1730 pShbCirBuff->m_ulDataApended = 0;
1731 pShbCirBuff->m_ulBlocksApended = 0;
1732 pShbCirBuff->m_ulDataReadable = 0;
1733 pShbCirBuff->m_ulBlocksReadable = 0;
1734 }
1735 ShbIpcLeaveAtomicSection(pShbInstance_p);
1736
1737#ifndef NDEBUG
1738 {
1739 memset(&pShbCirBuff->m_Data, 0xCC,
1740 pShbCirBuff->m_ulBufferDataSize);
1741 }
1742#endif
1743 }
1744
1745 // call application handler
1746 if (pShbCirBuff->m_pfnSigHndlrReset != NULL) {
1747 pShbCirBuff->m_pfnSigHndlrReset(pShbInstance_p, fTimeOut_p);
1748 }
1749
1750 // unlock buffer
1751 ShbIpcEnterAtomicSection(pShbInstance_p);
1752 {
1753 pShbCirBuff->m_fBufferLocked = FALSE;
1754 pShbCirBuff->m_pfnSigHndlrReset = NULL;
1755 }
1756 ShbIpcLeaveAtomicSection(pShbInstance_p);
1757
1758 return;
1759
1760}
1761
1762// EOF