at v2.6.29 966 lines 32 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 specific part for the 9 shared buffer 10 (Implementation for Linux KernelSpace) 11 12 License: 13 14 Redistribution and use in source and binary forms, with or without 15 modification, are permitted provided that the following conditions 16 are met: 17 18 1. Redistributions of source code must retain the above copyright 19 notice, this list of conditions and the following disclaimer. 20 21 2. Redistributions in binary form must reproduce the above copyright 22 notice, this list of conditions and the following disclaimer in the 23 documentation and/or other materials provided with the distribution. 24 25 3. Neither the name of SYSTEC electronic GmbH nor the names of its 26 contributors may be used to endorse or promote products derived 27 from this software without prior written permission. For written 28 permission, please contact info@systec-electronic.com. 29 30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 31 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 32 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 33 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 34 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 35 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 36 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 37 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 38 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 40 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 POSSIBILITY OF SUCH DAMAGE. 42 43 Severability Clause: 44 45 If a provision of this License is or becomes illegal, invalid or 46 unenforceable in any jurisdiction, that shall not affect: 47 1. the validity or enforceability in that jurisdiction of any other 48 provision of this License; or 49 2. the validity or enforceability in other jurisdictions of that or 50 any other provision of this License. 51 52 ------------------------------------------------------------------------- 53 54 2006/06/28 -rs: V 1.00 (initial version) 55 56****************************************************************************/ 57 58#include "global.h" 59#include "SharedBuff.h" 60#include "ShbIpc.h" 61#include "ShbLinuxKernel.h" 62#include "Debug.h" 63 64#include <linux/string.h> 65#include <linux/module.h> 66#include <asm/processor.h> 67//#include <linux/vmalloc.h> 68#include <linux/sched.h> 69#include <linux/param.h> 70#include <linux/spinlock.h> 71#include <linux/wait.h> 72#include <linux/completion.h> 73 74/***************************************************************************/ 75/* */ 76/* */ 77/* G L O B A L D E F I N I T I O N S */ 78/* */ 79/* */ 80/***************************************************************************/ 81 82#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED) 83 84//--------------------------------------------------------------------------- 85// Configuration 86//--------------------------------------------------------------------------- 87 88//--------------------------------------------------------------------------- 89// Constant definitions 90//--------------------------------------------------------------------------- 91 92#define MAX_LEN_BUFFER_ID 256 93 94#define TIMEOUT_ENTER_ATOMIC 1000 // (ms) for debgging: INFINITE 95#define TIMEOUT_TERM_THREAD 1000 96#define INFINITE 3600 97 98#define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+") 99#define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*") 100 101#define INVALID_ID -1 102 103#define TABLE_SIZE 10 104 105//--------------------------------------------------------------------------- 106// Local types 107//--------------------------------------------------------------------------- 108 109// This structure is the common header for the shared memory region used 110// by all processes attached this shared memory. It includes common 111// information to administrate/manage the shared buffer from a couple of 112// separated processes (e.g. the refernce counter). This structure is 113// located at the start of the shared memory region itself and exists 114// consequently only one times per shared memory instance. 115typedef struct { 116 117 unsigned long m_ulShMemSize; 118 unsigned long m_ulRefCount; 119 int m_iBufferId; 120// int m_iUserSpaceMem; //0 for userspace mem !=0 kernelspace mem 121 spinlock_t m_SpinlockBuffAccess; 122 BOOL m_fNewData; 123 BOOL m_fJobReady; 124 wait_queue_head_t m_WaitQueueNewData; 125 wait_queue_head_t m_WaitQueueJobReady; 126 127#ifndef NDEBUG 128 unsigned long m_ulOwnerProcID; 129#endif 130 131} tShbMemHeader; 132 133// This structure is the "external entry point" from a separate process 134// to get access to a shared buffer. This structure includes all platform 135// resp. target specific information to administrate/manage the shared 136// buffer from a separate process. Every process attached to the shared 137// buffer has its own runtime instance of this structure with its individual 138// runtime data (e.g. the scope of an event handle is limitted to the 139// owner process only). The structure member <m_pShbMemHeader> points 140// to the (process specific) start address of the shared memory region 141// itself. 142typedef struct { 143 unsigned long m_SbiMagicID; // magic ID ("SBI+") 144// void* m_pSharedMem; 145 int m_tThreadNewDataId; 146 long m_lThreadNewDataNice; // nice value of the new data thread 147 int m_tThreadJobReadyId; 148 unsigned long m_ulFlagsBuffAccess; // d.k. moved from tShbMemHeader, because each 149 // process needs to store the interrupt flags separately 150 tSigHndlrNewData m_pfnSigHndlrNewData; 151 unsigned long m_ulTimeOutJobReady; 152 tSigHndlrJobReady m_pfnSigHndlrJobReady; 153 tShbMemHeader *m_pShbMemHeader; 154 int m_iThreadTermFlag; 155 struct completion m_CompletionNewData; 156/* 157 struct semaphore *m_pSemBuffAccess; 158 struct semaphore *m_pSemNewData; 159 struct semaphore *m_pSemStopSignalingNewData; 160 struct semaphore *m_pSemJobReady; 161*/ 162#ifndef NDEBUG 163 unsigned long m_ulThreadIDNewData; 164 unsigned long m_ulThreadIDJobReady; 165#endif 166} tShbMemInst; 167 168//--------------------------------------------------------------------------- 169// Prototypes of internal functions 170//--------------------------------------------------------------------------- 171 172//tShbMemInst* ShbIpcGetShbMemInst (tShbInstance pShbInstance_p); 173//tShbMemHeader* ShbIpcGetShbMemHeader (tShbMemInst* pShbMemInst_p); 174 175//--------------------------------------------------------------------------- 176// Get pointer to process local information structure 177//--------------------------------------------------------------------------- 178 179static inline tShbMemInst *ShbIpcGetShbMemInst(tShbInstance pShbInstance_p) 180{ 181 182 tShbMemInst *pShbMemInst; 183 184 pShbMemInst = (tShbMemInst *) pShbInstance_p; 185 186 return (pShbMemInst); 187 188} 189 190//--------------------------------------------------------------------------- 191// Get pointer to shared memory header 192//--------------------------------------------------------------------------- 193 194static inline tShbMemHeader *ShbIpcGetShbMemHeader(tShbMemInst * pShbMemInst_p) 195{ 196 197 tShbMemHeader *pShbMemHeader; 198 199 pShbMemHeader = pShbMemInst_p->m_pShbMemHeader; 200 201 return (pShbMemHeader); 202 203} 204 205// Get pointer to process local information structure 206//#define ShbIpcGetShbMemInst(pShbInstance_p) ((tShbMemInst*)pShbInstance_p) 207 208// Get pointer to shared memory header 209//#define ShbIpcGetShbMemHeader(pShbMemInst_p) (pShbMemInst_p->m_pShbMemHeader) 210 211// not inlined internal functions 212int ShbIpcThreadSignalNewData(void *pvThreadParam_p); 213int ShbIpcThreadSignalJobReady(void *pvThreadParam_p); 214#endif 215 216//--------------------------------------------------------------------------- 217// modul globale vars 218//--------------------------------------------------------------------------- 219 220#if !defined(SHBIPC_INLINE_ENABLED) 221struct sShbMemTable *psMemTableElementFirst_g; 222 223static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p); 224static int ShbIpcFindListElement(int iBufferId, 225 struct sShbMemTable 226 **ppsReturnMemTableElement); 227static void ShbIpcAppendListElement(struct sShbMemTable *sNewMemTableElement); 228static void ShbIpcDeleteListElement(int iBufferId); 229static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256]); 230static unsigned long ShbIpcCrc32GetCrc(const char *pcString, 231 unsigned long aulCrcTable[256]); 232 233#endif 234 235//=========================================================================// 236// // 237// P U B L I C F U N C T I O N S // 238// // 239//=========================================================================// 240 241#if !defined(SHBIPC_INLINE_ENABLED) 242// not inlined external functions 243 244//--------------------------------------------------------------------------- 245// Initialize IPC for Shared Buffer Module 246//--------------------------------------------------------------------------- 247 248tShbError ShbIpcInit(void) 249{ 250 psMemTableElementFirst_g = NULL; 251 return (kShbOk); 252 253} 254 255//--------------------------------------------------------------------------- 256// Deinitialize IPC for Shared Buffer Module 257//--------------------------------------------------------------------------- 258 259tShbError ShbIpcExit(void) 260{ 261 262 return (kShbOk); 263 264} 265 266//--------------------------------------------------------------------------- 267// Allocate Shared Buffer 268//--------------------------------------------------------------------------- 269 270tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p, 271 const char *pszBufferID_p, 272 tShbInstance * ppShbInstance_p, 273 unsigned int *pfShbNewCreated_p) 274{ 275 tShbError ShbError; 276 int iBufferId = 0; 277 unsigned long ulCrc32 = 0; 278 unsigned int uiFirstProcess = 0; 279 unsigned long ulShMemSize; 280 tShbMemHeader *pShbMemHeader; 281 tShbMemInst *pShbMemInst = NULL; 282 tShbInstance pShbInstance; 283 unsigned int fShMemNewCreated = FALSE; 284 void *pSharedMem = NULL; 285 unsigned long aulCrcTable[256]; 286 struct sShbMemTable *psMemTableElement; 287 288 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer \n"); 289 ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader); 290 291 //create Buffer ID 292 ShbIpcCrc32GenTable(aulCrcTable); 293 ulCrc32 = ShbIpcCrc32GetCrc(pszBufferID_p, aulCrcTable); 294 iBufferId = ulCrc32; 295 DEBUG_LVL_29_TRACE2 296 ("ShbIpcAllocBuffer BufferSize:%d sizeof(tShb..):%d\n", 297 ulBufferSize_p, sizeof(tShbMemHeader)); 298 DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferId:%d MemSize:%d\n", 299 iBufferId, ulShMemSize); 300 //--------------------------------------------------------------- 301 // (1) open an existing or create a new shared memory 302 //--------------------------------------------------------------- 303 //test if buffer already exists 304 if (ShbIpcFindListElement(iBufferId, &psMemTableElement) == 0) { 305 //Buffer already exists 306 fShMemNewCreated = FALSE; 307 pSharedMem = psMemTableElement->m_pBuffer; 308 DEBUG_LVL_29_TRACE1 309 ("ShbIpcAllocBuffer attach Buffer at:%p Id:%d\n", 310 pSharedMem); 311 uiFirstProcess = 1; 312 } else { 313 //create new Buffer 314 fShMemNewCreated = TRUE; 315 uiFirstProcess = 0; 316 pSharedMem = kmalloc(ulShMemSize, GFP_KERNEL); 317 DEBUG_LVL_29_TRACE2 318 ("ShbIpcAllocBuffer Create New Buffer at:%p Id:%d\n", 319 pSharedMem, iBufferId); 320 if (pSharedMem == NULL) { 321 //unable to create mem 322 ShbError = kShbOutOfMem; 323 goto Exit; 324 } 325 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer create semas\n"); 326 // append Element to Mem Table 327 psMemTableElement = 328 kmalloc(sizeof(struct sShbMemTable), GFP_KERNEL); 329 psMemTableElement->m_iBufferId = iBufferId; 330 psMemTableElement->m_pBuffer = pSharedMem; 331 psMemTableElement->m_psNextMemTableElement = NULL; 332 ShbIpcAppendListElement(psMemTableElement); 333 } 334 335 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer update header\n"); 336 //update header 337 pShbMemHeader = (tShbMemHeader *) pSharedMem; 338 DEBUG_LVL_29_TRACE1 339 ("ShbIpcAllocBuffer 0 pShbMemHeader->m_ulShMemSize: %d\n", 340 pShbMemHeader->m_ulShMemSize); 341 // allocate a memory block from process specific mempool to save 342 // process local information to administrate/manage the shared buffer 343 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer alloc private mem\n"); 344 pShbMemInst = 345 (tShbMemInst *) ShbIpcAllocPrivateMem(sizeof(tShbMemInst)); 346 if (pShbMemInst == NULL) { 347 ShbError = kShbOutOfMem; 348 goto Exit; 349 } 350 // reset complete header to default values 351 //pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID; 352// pShbMemInst->m_pSharedMem = pSharedMem; 353 pShbMemInst->m_tThreadNewDataId = INVALID_ID; 354 pShbMemInst->m_tThreadJobReadyId = INVALID_ID; 355 pShbMemInst->m_pfnSigHndlrNewData = NULL; 356 pShbMemInst->m_ulTimeOutJobReady = 0; 357 pShbMemInst->m_pfnSigHndlrJobReady = NULL; 358 pShbMemInst->m_pShbMemHeader = pShbMemHeader; 359 pShbMemInst->m_iThreadTermFlag = 0; 360 361 // initialize completion etc. 362 init_completion(&pShbMemInst->m_CompletionNewData); 363 364 ShbError = kShbOk; 365 if (fShMemNewCreated) { 366 // this process was the first who wanted to use the shared memory, 367 // so a new shared memory was created 368 // -> setup new header information inside the shared memory region 369 // itself 370 pShbMemHeader->m_ulShMemSize = ulShMemSize; 371 pShbMemHeader->m_ulRefCount = 1; 372 pShbMemHeader->m_iBufferId = iBufferId; 373 // initialize spinlock 374 spin_lock_init(&pShbMemHeader->m_SpinlockBuffAccess); 375 // initialize wait queues 376 init_waitqueue_head(&pShbMemHeader->m_WaitQueueNewData); 377 init_waitqueue_head(&pShbMemHeader->m_WaitQueueJobReady); 378 } else { 379 // any other process has created the shared memory and this 380 // process only has to attach to it 381 // -> check and update existing header information inside the 382 // shared memory region itself 383 if (pShbMemHeader->m_ulShMemSize != ulShMemSize) { 384 ShbError = kShbOpenMismatch; 385 goto Exit; 386 } 387 pShbMemHeader->m_ulRefCount++; 388 } 389 390 Exit: 391 pShbInstance = (tShbInstance *) pShbMemInst; 392 *pfShbNewCreated_p = fShMemNewCreated; 393 *ppShbInstance_p = pShbInstance; 394 return (ShbError); 395 396} 397 398//--------------------------------------------------------------------------- 399// Release Shared Buffer 400//--------------------------------------------------------------------------- 401 402tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p) 403{ 404 tShbMemInst *pShbMemInst; 405 tShbMemHeader *pShbMemHeader; 406 tShbError ShbError; 407 tShbError ShbError2; 408 409 DEBUG_LVL_26_TRACE1("ShbIpcReleaseBuffer(%p)\n", pShbInstance_p); 410 if (pShbInstance_p == NULL) { 411 return (kShbOk); 412 } 413 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); 414 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst); 415 416 // stop threads in any case, because they are bound to that specific instance 417 ShbError2 = ShbIpcStopSignalingNewData(pShbInstance_p); 418 // d.k.: Whats up with JobReady thread? 419 // Just wake it up, but without setting the semaphore variable 420 wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady); 421 422 if (!--pShbMemHeader->m_ulRefCount) { 423 ShbError = kShbOk; 424 // delete mem table element 425 ShbIpcDeleteListElement(pShbMemHeader->m_iBufferId); 426 // delete shared mem 427 kfree(pShbMemInst->m_pShbMemHeader); 428 } else { 429 ShbError = kShbMemUsedByOtherProcs; 430 } 431 //delete privat mem 432 kfree(pShbMemInst); 433 return (ShbError); 434} 435 436#endif // !defined(SHBIPC_INLINE_ENABLED) 437 438#if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED) 439 440//--------------------------------------------------------------------------- 441// Enter atomic section for Shared Buffer access 442//--------------------------------------------------------------------------- 443 444INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p) 445{ 446 447 tShbMemInst *pShbMemInst; 448 tShbMemHeader *pShbMemHeader; 449 tShbError ShbError = kShbOk; 450 451 if (pShbInstance_p == NULL) { 452 ShbError = kShbInvalidArg; 453 goto Exit; 454 } 455 DEBUG_LVL_29_TRACE0("enter atomic\n"); 456 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); 457 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst); 458 459 // lock interrupts 460 spin_lock_irqsave(&pShbMemHeader->m_SpinlockBuffAccess, 461 pShbMemInst->m_ulFlagsBuffAccess); 462 463 Exit: 464 return ShbError; 465 466} 467 468//--------------------------------------------------------------------------- 469// Leave atomic section for Shared Buffer access 470//--------------------------------------------------------------------------- 471 472INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p) 473{ 474 475 tShbMemInst *pShbMemInst; 476 tShbMemHeader *pShbMemHeader; 477 tShbError ShbError = kShbOk; 478 479 if (pShbInstance_p == NULL) { 480 ShbError = kShbInvalidArg; 481 goto Exit; 482 } 483 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); 484 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst); 485 // unlock interrupts 486 spin_unlock_irqrestore(&pShbMemHeader->m_SpinlockBuffAccess, 487 pShbMemInst->m_ulFlagsBuffAccess); 488 489 Exit: 490 DEBUG_LVL_29_TRACE0("Leave Atomic \n"); 491 return ShbError; 492 493} 494 495//--------------------------------------------------------------------------- 496// Start signaling of new data (called from reading process) 497//--------------------------------------------------------------------------- 498 499INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance 500 pShbInstance_p, 501 tSigHndlrNewData 502 pfnSignalHandlerNewData_p, 503 tShbPriority 504 ShbPriority_p) 505{ 506 tShbMemInst *pShbMemInst; 507 tShbMemHeader *pShbMemHeader; 508 tShbError ShbError; 509 510 DEBUG_LVL_29_TRACE0("------->ShbIpcStartSignalingNewData\n"); 511 if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) { 512 return (kShbInvalidArg); 513 } 514 515 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); 516 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst); 517 ShbError = kShbOk; 518 519 if ((pShbMemInst->m_tThreadNewDataId != INVALID_ID) 520 || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) { 521 ShbError = kShbAlreadySignaling; 522 goto Exit; 523 } 524 DEBUG_LVL_26_TRACE2 525 ("ShbIpcStartSignalingNewData(%p) m_pfnSigHndlrNewData = %p\n", 526 pShbInstance_p, pfnSignalHandlerNewData_p); 527 pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p; 528 pShbMemHeader->m_fNewData = FALSE; 529 pShbMemInst->m_iThreadTermFlag = 0; 530 531 switch (ShbPriority_p) { 532 case kShbPriorityLow: 533 pShbMemInst->m_lThreadNewDataNice = -2; 534 break; 535 536 case kShbPriorityNormal: 537 pShbMemInst->m_lThreadNewDataNice = -9; 538 break; 539 540 case kshbPriorityHigh: 541 pShbMemInst->m_lThreadNewDataNice = -20; 542 break; 543 544 } 545 546 //create thread for signalling new data 547 pShbMemInst->m_tThreadNewDataId = 548 kernel_thread(ShbIpcThreadSignalNewData, pShbInstance_p, 549 CLONE_KERNEL); 550 551 Exit: 552 return ShbError; 553 554} 555 556//--------------------------------------------------------------------------- 557// Stop signaling of new data (called from reading process) 558//--------------------------------------------------------------------------- 559 560INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance 561 pShbInstance_p) 562{ 563 tShbMemInst *pShbMemInst; 564 tShbMemHeader *pShbMemHeader; 565 tShbError ShbError; 566 567 DEBUG_LVL_29_TRACE0("------->ShbIpcStopSignalingNewData\n"); 568 if (pShbInstance_p == NULL) { 569 return (kShbInvalidArg); 570 } 571 ShbError = kShbOk; 572 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); 573 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst); 574 575 DEBUG_LVL_26_TRACE2 576 ("ShbIpcStopSignalingNewData(%p) pfnSignHndlrNewData=%p\n", 577 pShbInstance_p, pShbMemInst->m_pfnSigHndlrNewData); 578 if (pShbMemInst->m_pfnSigHndlrNewData != NULL) { // signal handler was set before 579 int iErr; 580 //set termination flag in mem header 581 pShbMemInst->m_iThreadTermFlag = 1; 582 583 // check if thread is still running at all by sending the null-signal to this thread 584 /* iErr = kill_proc(pShbMemInst->m_tThreadNewDataId, 0, 1); */ 585 iErr = send_sig(0, pShbMemInst->m_tThreadNewDataId, 1); 586 if (iErr == 0) { 587 // wake up thread, because it is still running 588 wake_up_interruptible(&pShbMemHeader-> 589 m_WaitQueueNewData); 590 591 //wait for termination of thread 592 wait_for_completion(&pShbMemInst->m_CompletionNewData); 593 } 594 595 pShbMemInst->m_pfnSigHndlrNewData = NULL; 596 pShbMemInst->m_tThreadNewDataId = INVALID_ID; 597 } 598 599 return ShbError; 600 601} 602 603//--------------------------------------------------------------------------- 604// Signal new data (called from writing process) 605//--------------------------------------------------------------------------- 606 607INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p) 608{ 609 tShbMemHeader *pShbMemHeader; 610 611 if (pShbInstance_p == NULL) { 612 return (kShbInvalidArg); 613 } 614 pShbMemHeader = 615 ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p)); 616 //set semaphore 617 pShbMemHeader->m_fNewData = TRUE; 618 DEBUG_LVL_29_TRACE0("ShbIpcSignalNewData set Sem -> New Data\n"); 619 620 wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData); 621 return (kShbOk); 622} 623 624//--------------------------------------------------------------------------- 625// Start signaling for job ready (called from waiting process) 626//--------------------------------------------------------------------------- 627 628INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance 629 pShbInstance_p, 630 unsigned long 631 ulTimeOut_p, 632 tSigHndlrJobReady 633 pfnSignalHandlerJobReady_p) 634{ 635 tShbMemInst *pShbMemInst; 636 tShbMemHeader *pShbMemHeader; 637 tShbError ShbError; 638 639 if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) { 640 return (kShbInvalidArg); 641 } 642 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p); 643 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst); 644 645 ShbError = kShbOk; 646 if ((pShbMemInst->m_tThreadJobReadyId != INVALID_ID) 647 || (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) { 648 ShbError = kShbAlreadySignaling; 649 goto Exit; 650 } 651 pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p; 652 pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p; 653 pShbMemHeader->m_fJobReady = FALSE; 654 //create thread for signalling new data 655 pShbMemInst->m_tThreadJobReadyId = 656 kernel_thread(ShbIpcThreadSignalJobReady, pShbInstance_p, 657 CLONE_KERNEL); 658 Exit: 659 return ShbError; 660} 661 662//--------------------------------------------------------------------------- 663// Signal job ready (called from executing process) 664//--------------------------------------------------------------------------- 665 666INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p) 667{ 668 tShbMemHeader *pShbMemHeader; 669 670 DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady\n"); 671 if (pShbInstance_p == NULL) { 672 return (kShbInvalidArg); 673 } 674 pShbMemHeader = 675 ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p)); 676 //set semaphore 677 pShbMemHeader->m_fJobReady = TRUE; 678 DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady set Sem -> Job Ready \n"); 679 680 wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady); 681 return (kShbOk); 682} 683 684//--------------------------------------------------------------------------- 685// Get pointer to common used share memory area 686//--------------------------------------------------------------------------- 687 688INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p) 689{ 690 691 tShbMemHeader *pShbMemHeader; 692 void *pShbShMemPtr; 693 694 pShbMemHeader = 695 ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p)); 696 if (pShbMemHeader != NULL) { 697 pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader); 698 } else { 699 pShbShMemPtr = NULL; 700 } 701 702 return (pShbShMemPtr); 703 704} 705 706#endif 707 708//=========================================================================// 709// // 710// P R I V A T E F U N C T I O N S // 711// // 712//=========================================================================// 713 714#if !defined(SHBIPC_INLINE_ENABLED) 715 716//--------------------------------------------------------------------------- 717// Get pointer to process local information structure 718//--------------------------------------------------------------------------- 719 720/*tShbMemInst* ShbIpcGetShbMemInst ( 721 tShbInstance pShbInstance_p) 722{ 723 724tShbMemInst* pShbMemInst; 725 726 pShbMemInst = (tShbMemInst*)pShbInstance_p; 727 728 return (pShbMemInst); 729 730} 731*/ 732 733//--------------------------------------------------------------------------- 734// Get pointer to shared memory header 735//--------------------------------------------------------------------------- 736 737/*tShbMemHeader* ShbIpcGetShbMemHeader ( 738 tShbMemInst* pShbMemInst_p) 739{ 740 741tShbMemHeader* pShbMemHeader; 742 743 pShbMemHeader = pShbMemInst_p->m_pShbMemHeader; 744 745 return (pShbMemHeader); 746 747} 748*/ 749 750//--------------------------------------------------------------------------- 751// Allocate a memory block from process specific mempool 752//--------------------------------------------------------------------------- 753 754static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p) 755{ 756 tShbError ShbError; 757 void *pMem; 758 759 DEBUG_LVL_29_TRACE0("ShbIpcAllocPrivateMem \n"); 760 //get private mem 761 pMem = kmalloc(ulMemSize_p, GFP_KERNEL); 762 if (pMem == NULL) { 763 //unable to create mem 764 ShbError = kShbOutOfMem; 765 goto Exit; 766 } 767 Exit: 768 return (pMem); 769 770} 771 772//--------------------------------------------------------------------------- 773// Thread for new data signaling 774//--------------------------------------------------------------------------- 775 776int ShbIpcThreadSignalNewData(void *pvThreadParam_p) 777{ 778 tShbInstance pShbInstance; 779 tShbMemInst *pShbMemInst; 780 tShbMemHeader *pShbMemHeader; 781 int iRetVal = -1; 782 int fCallAgain; 783 784 daemonize("ShbND%p", pvThreadParam_p); 785 allow_signal(SIGTERM); 786 pShbInstance = (tShbMemInst *) pvThreadParam_p; 787 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance); 788 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst); 789 790 DEBUG_LVL_26_TRACE1("ShbIpcThreadSignalNewData(%p)\n", pvThreadParam_p); 791 792 set_user_nice(current, pShbMemInst->m_lThreadNewDataNice); 793 794// DEBUG_LVL_29_TRACE1("ShbIpcThreadSignalNewData wait for New Data Sem %p\n",pShbMemInst->m_pSemNewData); 795 do { 796 iRetVal = 797 wait_event_interruptible(pShbMemHeader->m_WaitQueueNewData, 798 (pShbMemInst->m_iThreadTermFlag != 799 0) 800 || (pShbMemHeader->m_fNewData != 801 FALSE)); 802 803 if (iRetVal != 0) { // signal pending 804 break; 805 } 806 807 if (pShbMemHeader->m_fNewData != FALSE) { 808 pShbMemHeader->m_fNewData = FALSE; 809 do { 810 fCallAgain = 811 pShbMemInst-> 812 m_pfnSigHndlrNewData(pShbInstance); 813 // call scheduler, which will execute any task with higher priority 814 schedule(); 815 } while (fCallAgain != FALSE); 816 } 817 } while (pShbMemInst->m_iThreadTermFlag == 0); 818 DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalNewData terminated \n"); 819 //set thread completed 820 complete_and_exit(&pShbMemInst->m_CompletionNewData, 0); 821 return 0; 822} 823 824//--------------------------------------------------------------------------- 825// Thread for new data Job Ready signaling 826//--------------------------------------------------------------------------- 827 828int ShbIpcThreadSignalJobReady(void *pvThreadParam_p) 829{ 830 tShbInstance pShbInstance; 831 tShbMemInst *pShbMemInst; 832 tShbMemHeader *pShbMemHeader; 833 long lTimeOut; 834 int iRetVal = -1; 835 836 daemonize("ShbJR%p", pvThreadParam_p); 837 allow_signal(SIGTERM); 838 pShbInstance = (tShbMemInst *) pvThreadParam_p; 839 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance); 840 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst); 841 842 DEBUG_LVL_29_TRACE0 843 ("ShbIpcThreadSignalJobReady wait for job ready Sem\n"); 844 if (pShbMemInst->m_ulTimeOutJobReady != 0) { 845 lTimeOut = (long)pShbMemInst->m_ulTimeOutJobReady; 846 //wait for job ready semaphore 847 iRetVal = 848 wait_event_interruptible_timeout(pShbMemHeader-> 849 m_WaitQueueJobReady, 850 (pShbMemHeader-> 851 m_fJobReady != FALSE), 852 lTimeOut); 853 } else { 854 //wait for job ready semaphore 855 iRetVal = 856 wait_event_interruptible(pShbMemHeader->m_WaitQueueJobReady, 857 (pShbMemHeader->m_fJobReady != 858 FALSE)); 859 } 860 861 if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) { 862 //call Handler 863 pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, 864 !pShbMemHeader->m_fJobReady); 865 } 866 867 pShbMemInst->m_pfnSigHndlrJobReady = NULL; 868 return 0; 869} 870 871//Build the crc table 872static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256]) 873{ 874 unsigned long ulCrc, ulPoly; 875 int iIndexI, iIndexJ; 876 877 ulPoly = 0xEDB88320L; 878 for (iIndexI = 0; iIndexI < 256; iIndexI++) { 879 ulCrc = iIndexI; 880 for (iIndexJ = 8; iIndexJ > 0; iIndexJ--) { 881 if (ulCrc & 1) { 882 ulCrc = (ulCrc >> 1) ^ ulPoly; 883 } else { 884 ulCrc >>= 1; 885 } 886 } 887 aulCrcTable[iIndexI] = ulCrc; 888 } 889} 890 891//Calculate the crc value 892static unsigned long ShbIpcCrc32GetCrc(const char *pcString, 893 unsigned long aulCrcTable[256]) 894{ 895 unsigned long ulCrc; 896 int iIndex; 897 898 ulCrc = 0xFFFFFFFF; 899 for (iIndex = 0; iIndex < strlen(pcString); iIndex++) { 900 ulCrc = 901 ((ulCrc >> 8) & 0x00FFFFFF) ^ 902 aulCrcTable[(ulCrc ^ pcString[iIndex]) & 0xFF]; 903 } 904 return (ulCrc ^ 0xFFFFFFFF); 905 906} 907 908static void ShbIpcAppendListElement(struct sShbMemTable *psNewMemTableElement) 909{ 910 struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g; 911 psNewMemTableElement->m_psNextMemTableElement = NULL; 912 913 if (psMemTableElementFirst_g != NULL) { /* sind Elemente vorhanden */ 914 while (psMemTableElement->m_psNextMemTableElement != NULL) { /* suche das letzte Element */ 915 psMemTableElement = 916 psMemTableElement->m_psNextMemTableElement; 917 } 918 psMemTableElement->m_psNextMemTableElement = psNewMemTableElement; /* Haenge das Element hinten an */ 919 } else { /* wenn die liste leer ist, bin ich das erste Element */ 920 psMemTableElementFirst_g = psNewMemTableElement; 921 } 922} 923 924static int ShbIpcFindListElement(int iBufferId, 925 struct sShbMemTable **ppsReturnMemTableElement) 926{ 927 struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g; 928 while (psMemTableElement != NULL) { 929 if (psMemTableElement->m_iBufferId == iBufferId) { 930//printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",psMemTableElement->m_pBuffer,psMemTableElement->m_iBufferId); 931 *ppsReturnMemTableElement = psMemTableElement; 932//printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",(*ppsReturnMemTableElement)->m_pBuffer,(*ppsReturnMemTableElement)->m_iBufferId); 933 return 0; 934 } 935 psMemTableElement = psMemTableElement->m_psNextMemTableElement; 936 } 937 return -1; 938} 939 940static void ShbIpcDeleteListElement(int iBufferId) 941{ 942 struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g; 943 struct sShbMemTable *psMemTableElementOld = psMemTableElementFirst_g; 944 if (psMemTableElement != NULL) { 945 while ((psMemTableElement != NULL) 946 && (psMemTableElement->m_iBufferId != iBufferId)) { 947 psMemTableElementOld = psMemTableElement; 948 psMemTableElement = 949 psMemTableElement->m_psNextMemTableElement; 950 } 951 if (psMemTableElement != NULL) { 952 if (psMemTableElement != psMemTableElementFirst_g) { 953 psMemTableElementOld->m_psNextMemTableElement = 954 psMemTableElement->m_psNextMemTableElement; 955 kfree(psMemTableElement); 956 } else { 957 kfree(psMemTableElement); 958 psMemTableElementFirst_g = NULL; 959 } 960 961 } 962 } 963 964} 965 966#endif