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