at v2.6.30 1762 lines 52 kB view raw
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