1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: Project independend shared buffer (linear + circular)
8 Description: Implementation of platform specific part for the
10 (Implementation for Linux KernelSpace)
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions
18 1. Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
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.
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.
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.
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.
52 -------------------------------------------------------------------------
54 2006/06/28 -rs: V 1.00 (initial version)
56 ****************************************************************************/
59 #include "SharedBuff.h"
61 #include "ShbLinuxKernel.h"
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>
74 /***************************************************************************/
77 /* G L O B A L D E F I N I T I O N S */
80 /***************************************************************************/
82 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
84 //---------------------------------------------------------------------------
86 //---------------------------------------------------------------------------
88 //---------------------------------------------------------------------------
89 // Constant definitions
90 //---------------------------------------------------------------------------
92 #define MAX_LEN_BUFFER_ID 256
94 #define TIMEOUT_ENTER_ATOMIC 1000 // (ms) for debgging: INFINITE
95 #define TIMEOUT_TERM_THREAD 1000
98 #define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+")
99 #define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*")
101 #define INVALID_ID -1
103 #define TABLE_SIZE 10
105 //---------------------------------------------------------------------------
107 //---------------------------------------------------------------------------
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.
117 unsigned long m_ulShMemSize;
118 unsigned long m_ulRefCount;
120 // int m_iUserSpaceMem; //0 for userspace mem !=0 kernelspace mem
121 spinlock_t m_SpinlockBuffAccess;
124 wait_queue_head_t m_WaitQueueNewData;
125 wait_queue_head_t m_WaitQueueJobReady;
128 unsigned long m_ulOwnerProcID;
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
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;
157 struct semaphore *m_pSemBuffAccess;
158 struct semaphore *m_pSemNewData;
159 struct semaphore *m_pSemStopSignalingNewData;
160 struct semaphore *m_pSemJobReady;
163 unsigned long m_ulThreadIDNewData;
164 unsigned long m_ulThreadIDJobReady;
168 //---------------------------------------------------------------------------
169 // Prototypes of internal functions
170 //---------------------------------------------------------------------------
172 //tShbMemInst* ShbIpcGetShbMemInst (tShbInstance pShbInstance_p);
173 //tShbMemHeader* ShbIpcGetShbMemHeader (tShbMemInst* pShbMemInst_p);
175 //---------------------------------------------------------------------------
176 // Get pointer to process local information structure
177 //---------------------------------------------------------------------------
179 static inline tShbMemInst *ShbIpcGetShbMemInst(tShbInstance pShbInstance_p)
182 tShbMemInst *pShbMemInst;
184 pShbMemInst = (tShbMemInst *) pShbInstance_p;
186 return (pShbMemInst);
190 //---------------------------------------------------------------------------
191 // Get pointer to shared memory header
192 //---------------------------------------------------------------------------
194 static inline tShbMemHeader *ShbIpcGetShbMemHeader(tShbMemInst * pShbMemInst_p)
197 tShbMemHeader *pShbMemHeader;
199 pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
201 return (pShbMemHeader);
205 // Get pointer to process local information structure
206 //#define ShbIpcGetShbMemInst(pShbInstance_p) ((tShbMemInst*)pShbInstance_p)
208 // Get pointer to shared memory header
209 //#define ShbIpcGetShbMemHeader(pShbMemInst_p) (pShbMemInst_p->m_pShbMemHeader)
211 // not inlined internal functions
212 int ShbIpcThreadSignalNewData(void *pvThreadParam_p);
213 int ShbIpcThreadSignalJobReady(void *pvThreadParam_p);
216 //---------------------------------------------------------------------------
217 // modul globale vars
218 //---------------------------------------------------------------------------
220 #if !defined(SHBIPC_INLINE_ENABLED)
221 struct sShbMemTable *psMemTableElementFirst_g;
223 static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p);
224 static int ShbIpcFindListElement(int iBufferId,
226 **ppsReturnMemTableElement);
227 static void ShbIpcAppendListElement(struct sShbMemTable *sNewMemTableElement);
228 static void ShbIpcDeleteListElement(int iBufferId);
229 static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256]);
230 static unsigned long ShbIpcCrc32GetCrc(const char *pcString,
231 unsigned long aulCrcTable[256]);
235 //=========================================================================//
237 // P U B L I C F U N C T I O N S //
239 //=========================================================================//
241 #if !defined(SHBIPC_INLINE_ENABLED)
242 // not inlined external functions
244 //---------------------------------------------------------------------------
245 // Initialize IPC for Shared Buffer Module
246 //---------------------------------------------------------------------------
248 tShbError ShbIpcInit(void)
250 psMemTableElementFirst_g = NULL;
255 //---------------------------------------------------------------------------
256 // Deinitialize IPC for Shared Buffer Module
257 //---------------------------------------------------------------------------
259 tShbError ShbIpcExit(void)
266 //---------------------------------------------------------------------------
267 // Allocate Shared Buffer
268 //---------------------------------------------------------------------------
270 tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p,
271 const char *pszBufferID_p,
272 tShbInstance * ppShbInstance_p,
273 unsigned int *pfShbNewCreated_p)
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;
288 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer \n");
289 ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader);
292 ShbIpcCrc32GenTable(aulCrcTable);
293 ulCrc32 = ShbIpcCrc32GetCrc(pszBufferID_p, aulCrcTable);
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;
309 ("ShbIpcAllocBuffer attach Buffer at:%p Id:%d\n",
314 fShMemNewCreated = TRUE;
316 pSharedMem = kmalloc(ulShMemSize, GFP_KERNEL);
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;
325 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer create semas\n");
326 // append Element to Mem Table
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);
335 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer update header\n");
337 pShbMemHeader = (tShbMemHeader *) pSharedMem;
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");
345 (tShbMemInst *) ShbIpcAllocPrivateMem(sizeof(tShbMemInst));
346 if (pShbMemInst == NULL) {
347 ShbError = kShbOutOfMem;
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;
361 // initialize completion etc.
362 init_completion(&pShbMemInst->m_CompletionNewData);
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
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);
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;
387 pShbMemHeader->m_ulRefCount++;
391 pShbInstance = (tShbInstance *) pShbMemInst;
392 *pfShbNewCreated_p = fShMemNewCreated;
393 *ppShbInstance_p = pShbInstance;
398 //---------------------------------------------------------------------------
399 // Release Shared Buffer
400 //---------------------------------------------------------------------------
402 tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p)
404 tShbMemInst *pShbMemInst;
405 tShbMemHeader *pShbMemHeader;
409 DEBUG_LVL_26_TRACE1("ShbIpcReleaseBuffer(%p)\n", pShbInstance_p);
410 if (pShbInstance_p == NULL) {
413 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
414 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
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);
422 if (!--pShbMemHeader->m_ulRefCount) {
424 // delete mem table element
425 ShbIpcDeleteListElement(pShbMemHeader->m_iBufferId);
427 kfree(pShbMemInst->m_pShbMemHeader);
429 ShbError = kShbMemUsedByOtherProcs;
436 #endif // !defined(SHBIPC_INLINE_ENABLED)
438 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
440 //---------------------------------------------------------------------------
441 // Enter atomic section for Shared Buffer access
442 //---------------------------------------------------------------------------
444 INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p)
447 tShbMemInst *pShbMemInst;
448 tShbMemHeader *pShbMemHeader;
449 tShbError ShbError = kShbOk;
451 if (pShbInstance_p == NULL) {
452 ShbError = kShbInvalidArg;
455 DEBUG_LVL_29_TRACE0("enter atomic\n");
456 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
457 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
460 spin_lock_irqsave(&pShbMemHeader->m_SpinlockBuffAccess,
461 pShbMemInst->m_ulFlagsBuffAccess);
468 //---------------------------------------------------------------------------
469 // Leave atomic section for Shared Buffer access
470 //---------------------------------------------------------------------------
472 INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p)
475 tShbMemInst *pShbMemInst;
476 tShbMemHeader *pShbMemHeader;
477 tShbError ShbError = kShbOk;
479 if (pShbInstance_p == NULL) {
480 ShbError = kShbInvalidArg;
483 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
484 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
486 spin_unlock_irqrestore(&pShbMemHeader->m_SpinlockBuffAccess,
487 pShbMemInst->m_ulFlagsBuffAccess);
490 DEBUG_LVL_29_TRACE0("Leave Atomic \n");
495 //---------------------------------------------------------------------------
496 // Start signaling of new data (called from reading process)
497 //---------------------------------------------------------------------------
499 INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance
502 pfnSignalHandlerNewData_p,
506 tShbMemInst *pShbMemInst;
507 tShbMemHeader *pShbMemHeader;
510 DEBUG_LVL_29_TRACE0("------->ShbIpcStartSignalingNewData\n");
511 if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) {
512 return (kShbInvalidArg);
515 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
516 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
519 if ((pShbMemInst->m_tThreadNewDataId != INVALID_ID)
520 || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) {
521 ShbError = kShbAlreadySignaling;
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;
531 switch (ShbPriority_p) {
532 case kShbPriorityLow:
533 pShbMemInst->m_lThreadNewDataNice = -2;
536 case kShbPriorityNormal:
537 pShbMemInst->m_lThreadNewDataNice = -9;
540 case kshbPriorityHigh:
541 pShbMemInst->m_lThreadNewDataNice = -20;
546 //create thread for signalling new data
547 pShbMemInst->m_tThreadNewDataId =
548 kernel_thread(ShbIpcThreadSignalNewData, pShbInstance_p,
556 //---------------------------------------------------------------------------
557 // Stop signaling of new data (called from reading process)
558 //---------------------------------------------------------------------------
560 INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance
563 tShbMemInst *pShbMemInst;
564 tShbMemHeader *pShbMemHeader;
567 DEBUG_LVL_29_TRACE0("------->ShbIpcStopSignalingNewData\n");
568 if (pShbInstance_p == NULL) {
569 return (kShbInvalidArg);
572 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
573 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
576 ("ShbIpcStopSignalingNewData(%p) pfnSignHndlrNewData=%p\n",
577 pShbInstance_p, pShbMemInst->m_pfnSigHndlrNewData);
578 if (pShbMemInst->m_pfnSigHndlrNewData != NULL) { // signal handler was set before
580 //set termination flag in mem header
581 pShbMemInst->m_iThreadTermFlag = 1;
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);
587 // wake up thread, because it is still running
588 wake_up_interruptible(&pShbMemHeader->
591 //wait for termination of thread
592 wait_for_completion(&pShbMemInst->m_CompletionNewData);
595 pShbMemInst->m_pfnSigHndlrNewData = NULL;
596 pShbMemInst->m_tThreadNewDataId = INVALID_ID;
603 //---------------------------------------------------------------------------
604 // Signal new data (called from writing process)
605 //---------------------------------------------------------------------------
607 INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p)
609 tShbMemHeader *pShbMemHeader;
611 if (pShbInstance_p == NULL) {
612 return (kShbInvalidArg);
615 ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p));
617 pShbMemHeader->m_fNewData = TRUE;
618 DEBUG_LVL_29_TRACE0("ShbIpcSignalNewData set Sem -> New Data\n");
620 wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData);
624 //---------------------------------------------------------------------------
625 // Start signaling for job ready (called from waiting process)
626 //---------------------------------------------------------------------------
628 INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance
633 pfnSignalHandlerJobReady_p)
635 tShbMemInst *pShbMemInst;
636 tShbMemHeader *pShbMemHeader;
639 if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) {
640 return (kShbInvalidArg);
642 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
643 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
646 if ((pShbMemInst->m_tThreadJobReadyId != INVALID_ID)
647 || (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) {
648 ShbError = kShbAlreadySignaling;
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,
662 //---------------------------------------------------------------------------
663 // Signal job ready (called from executing process)
664 //---------------------------------------------------------------------------
666 INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p)
668 tShbMemHeader *pShbMemHeader;
670 DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady\n");
671 if (pShbInstance_p == NULL) {
672 return (kShbInvalidArg);
675 ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p));
677 pShbMemHeader->m_fJobReady = TRUE;
678 DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady set Sem -> Job Ready \n");
680 wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady);
684 //---------------------------------------------------------------------------
685 // Get pointer to common used share memory area
686 //---------------------------------------------------------------------------
688 INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p)
691 tShbMemHeader *pShbMemHeader;
695 ShbIpcGetShbMemHeader(ShbIpcGetShbMemInst(pShbInstance_p));
696 if (pShbMemHeader != NULL) {
697 pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader);
702 return (pShbShMemPtr);
708 //=========================================================================//
710 // P R I V A T E F U N C T I O N S //
712 //=========================================================================//
714 #if !defined(SHBIPC_INLINE_ENABLED)
716 //---------------------------------------------------------------------------
717 // Get pointer to process local information structure
718 //---------------------------------------------------------------------------
720 /*tShbMemInst* ShbIpcGetShbMemInst (
721 tShbInstance pShbInstance_p)
724 tShbMemInst* pShbMemInst;
726 pShbMemInst = (tShbMemInst*)pShbInstance_p;
728 return (pShbMemInst);
733 //---------------------------------------------------------------------------
734 // Get pointer to shared memory header
735 //---------------------------------------------------------------------------
737 /*tShbMemHeader* ShbIpcGetShbMemHeader (
738 tShbMemInst* pShbMemInst_p)
741 tShbMemHeader* pShbMemHeader;
743 pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
745 return (pShbMemHeader);
750 //---------------------------------------------------------------------------
751 // Allocate a memory block from process specific mempool
752 //---------------------------------------------------------------------------
754 static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p)
759 DEBUG_LVL_29_TRACE0("ShbIpcAllocPrivateMem \n");
761 pMem = kmalloc(ulMemSize_p, GFP_KERNEL);
763 //unable to create mem
764 ShbError = kShbOutOfMem;
772 //---------------------------------------------------------------------------
773 // Thread for new data signaling
774 //---------------------------------------------------------------------------
776 int ShbIpcThreadSignalNewData(void *pvThreadParam_p)
778 tShbInstance pShbInstance;
779 tShbMemInst *pShbMemInst;
780 tShbMemHeader *pShbMemHeader;
784 daemonize("ShbND%p", pvThreadParam_p);
785 allow_signal(SIGTERM);
786 pShbInstance = (tShbMemInst *) pvThreadParam_p;
787 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
788 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
790 DEBUG_LVL_26_TRACE1("ShbIpcThreadSignalNewData(%p)\n", pvThreadParam_p);
792 set_user_nice(current, pShbMemInst->m_lThreadNewDataNice);
794 // DEBUG_LVL_29_TRACE1("ShbIpcThreadSignalNewData wait for New Data Sem %p\n",pShbMemInst->m_pSemNewData);
797 wait_event_interruptible(pShbMemHeader->m_WaitQueueNewData,
798 (pShbMemInst->m_iThreadTermFlag !=
800 || (pShbMemHeader->m_fNewData !=
803 if (iRetVal != 0) { // signal pending
807 if (pShbMemHeader->m_fNewData != FALSE) {
808 pShbMemHeader->m_fNewData = FALSE;
812 m_pfnSigHndlrNewData(pShbInstance);
813 // call scheduler, which will execute any task with higher priority
815 } while (fCallAgain != FALSE);
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);
824 //---------------------------------------------------------------------------
825 // Thread for new data Job Ready signaling
826 //---------------------------------------------------------------------------
828 int ShbIpcThreadSignalJobReady(void *pvThreadParam_p)
830 tShbInstance pShbInstance;
831 tShbMemInst *pShbMemInst;
832 tShbMemHeader *pShbMemHeader;
836 daemonize("ShbJR%p", pvThreadParam_p);
837 allow_signal(SIGTERM);
838 pShbInstance = (tShbMemInst *) pvThreadParam_p;
839 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
840 pShbMemHeader = ShbIpcGetShbMemHeader(pShbMemInst);
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
848 wait_event_interruptible_timeout(pShbMemHeader->
851 m_fJobReady != FALSE),
854 //wait for job ready semaphore
856 wait_event_interruptible(pShbMemHeader->m_WaitQueueJobReady,
857 (pShbMemHeader->m_fJobReady !=
861 if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) {
863 pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance,
864 !pShbMemHeader->m_fJobReady);
867 pShbMemInst->m_pfnSigHndlrJobReady = NULL;
871 //Build the crc table
872 static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256])
874 unsigned long ulCrc, ulPoly;
875 int iIndexI, iIndexJ;
877 ulPoly = 0xEDB88320L;
878 for (iIndexI = 0; iIndexI < 256; iIndexI++) {
880 for (iIndexJ = 8; iIndexJ > 0; iIndexJ--) {
882 ulCrc = (ulCrc >> 1) ^ ulPoly;
887 aulCrcTable[iIndexI] = ulCrc;
891 //Calculate the crc value
892 static unsigned long ShbIpcCrc32GetCrc(const char *pcString,
893 unsigned long aulCrcTable[256])
899 for (iIndex = 0; iIndex < strlen(pcString); iIndex++) {
901 ((ulCrc >> 8) & 0x00FFFFFF) ^
902 aulCrcTable[(ulCrc ^ pcString[iIndex]) & 0xFF];
904 return (ulCrc ^ 0xFFFFFFFF);
908 static void ShbIpcAppendListElement(struct sShbMemTable *psNewMemTableElement)
910 struct sShbMemTable *psMemTableElement = psMemTableElementFirst_g;
911 psNewMemTableElement->m_psNextMemTableElement = NULL;
913 if (psMemTableElementFirst_g != NULL) { /* sind Elemente vorhanden */
914 while (psMemTableElement->m_psNextMemTableElement != NULL) { /* suche das letzte Element */
916 psMemTableElement->m_psNextMemTableElement;
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;
924 static int ShbIpcFindListElement(int iBufferId,
925 struct sShbMemTable **ppsReturnMemTableElement)
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);
935 psMemTableElement = psMemTableElement->m_psNextMemTableElement;
940 static void ShbIpcDeleteListElement(int iBufferId)
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;
949 psMemTableElement->m_psNextMemTableElement;
951 if (psMemTableElement != NULL) {
952 if (psMemTableElement != psMemTableElementFirst_g) {
953 psMemTableElementOld->m_psNextMemTableElement =
954 psMemTableElement->m_psNextMemTableElement;
955 kfree(psMemTableElement);
957 kfree(psMemTableElement);
958 psMemTableElementFirst_g = NULL;