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 ****************************************************************************/
60 #include "SharedBuff.h"
62 #include "ShbLinuxKernel.h"
65 #include <linux/string.h>
66 #include <linux/module.h>
67 #include <asm/processor.h>
68 //#include <linux/vmalloc.h>
69 #include <linux/sched.h>
70 #include <linux/param.h>
71 #include <linux/spinlock.h>
72 #include <linux/wait.h>
73 #include <linux/completion.h>
77 /***************************************************************************/
80 /* G L O B A L D E F I N I T I O N S */
83 /***************************************************************************/
85 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
87 //---------------------------------------------------------------------------
89 //---------------------------------------------------------------------------
93 //---------------------------------------------------------------------------
94 // Constant definitions
95 //---------------------------------------------------------------------------
97 #define MAX_LEN_BUFFER_ID 256
99 #define TIMEOUT_ENTER_ATOMIC 1000 // (ms) for debgging: INFINITE
100 #define TIMEOUT_TERM_THREAD 1000
101 #define INFINITE 3600
103 #define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+")
104 #define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*")
106 #define INVALID_ID -1
108 #define TABLE_SIZE 10
111 //---------------------------------------------------------------------------
113 //---------------------------------------------------------------------------
115 // This structure is the common header for the shared memory region used
116 // by all processes attached this shared memory. It includes common
117 // information to administrate/manage the shared buffer from a couple of
118 // separated processes (e.g. the refernce counter). This structure is
119 // located at the start of the shared memory region itself and exists
120 // consequently only one times per shared memory instance.
124 unsigned long m_ulShMemSize;
125 unsigned long m_ulRefCount;
127 // int m_iUserSpaceMem; //0 for userspace mem !=0 kernelspace mem
128 spinlock_t m_SpinlockBuffAccess;
131 wait_queue_head_t m_WaitQueueNewData;
132 wait_queue_head_t m_WaitQueueJobReady;
135 unsigned long m_ulOwnerProcID;
142 // This structure is the "external entry point" from a separate process
143 // to get access to a shared buffer. This structure includes all platform
144 // resp. target specific information to administrate/manage the shared
145 // buffer from a separate process. Every process attached to the shared
146 // buffer has its own runtime instance of this structure with its individual
147 // runtime data (e.g. the scope of an event handle is limitted to the
148 // owner process only). The structure member <m_pShbMemHeader> points
149 // to the (process specific) start address of the shared memory region
153 unsigned long m_SbiMagicID; // magic ID ("SBI+")
154 // void* m_pSharedMem;
155 int m_tThreadNewDataId;
156 long m_lThreadNewDataNice; // nice value of the new data thread
157 int m_tThreadJobReadyId;
158 unsigned long m_ulFlagsBuffAccess; // d.k. moved from tShbMemHeader, because each
159 // process needs to store the interrupt flags separately
160 tSigHndlrNewData m_pfnSigHndlrNewData;
161 unsigned long m_ulTimeOutJobReady;
162 tSigHndlrJobReady m_pfnSigHndlrJobReady;
163 tShbMemHeader* m_pShbMemHeader;
164 int m_iThreadTermFlag;
165 struct completion m_CompletionNewData;
167 struct semaphore *m_pSemBuffAccess;
168 struct semaphore *m_pSemNewData;
169 struct semaphore *m_pSemStopSignalingNewData;
170 struct semaphore *m_pSemJobReady;
173 unsigned long m_ulThreadIDNewData;
174 unsigned long m_ulThreadIDJobReady;
179 //---------------------------------------------------------------------------
180 // Prototypes of internal functions
181 //---------------------------------------------------------------------------
183 //tShbMemInst* ShbIpcGetShbMemInst (tShbInstance pShbInstance_p);
184 //tShbMemHeader* ShbIpcGetShbMemHeader (tShbMemInst* pShbMemInst_p);
186 //---------------------------------------------------------------------------
187 // Get pointer to process local information structure
188 //---------------------------------------------------------------------------
190 static inline tShbMemInst* ShbIpcGetShbMemInst (
191 tShbInstance pShbInstance_p)
194 tShbMemInst* pShbMemInst;
197 pShbMemInst = (tShbMemInst*)pShbInstance_p;
200 return (pShbMemInst);
206 //---------------------------------------------------------------------------
207 // Get pointer to shared memory header
208 //---------------------------------------------------------------------------
210 static inline tShbMemHeader* ShbIpcGetShbMemHeader (
211 tShbMemInst* pShbMemInst_p)
214 tShbMemHeader* pShbMemHeader;
217 pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
219 return (pShbMemHeader);
223 // Get pointer to process local information structure
224 //#define ShbIpcGetShbMemInst(pShbInstance_p) ((tShbMemInst*)pShbInstance_p)
226 // Get pointer to shared memory header
227 //#define ShbIpcGetShbMemHeader(pShbMemInst_p) (pShbMemInst_p->m_pShbMemHeader)
229 // not inlined internal functions
230 int ShbIpcThreadSignalNewData (void* pvThreadParam_p);
231 int ShbIpcThreadSignalJobReady (void* pvThreadParam_p);
234 //---------------------------------------------------------------------------
235 // modul globale vars
236 //---------------------------------------------------------------------------
238 #if !defined(SHBIPC_INLINE_ENABLED)
239 struct sShbMemTable *psMemTableElementFirst_g;
241 static void* ShbIpcAllocPrivateMem (unsigned long ulMemSize_p);
242 static int ShbIpcFindListElement (int iBufferId, struct sShbMemTable **ppsReturnMemTableElement);
243 static void ShbIpcAppendListElement (struct sShbMemTable *sNewMemTableElement);
244 static void ShbIpcDeleteListElement (int iBufferId);
245 static void ShbIpcCrc32GenTable (unsigned long aulCrcTable[256]);
246 static unsigned long ShbIpcCrc32GetCrc (const char *pcString, unsigned long aulCrcTable[256]);
251 //=========================================================================//
253 // P U B L I C F U N C T I O N S //
255 //=========================================================================//
257 #if !defined(SHBIPC_INLINE_ENABLED)
258 // not inlined external functions
260 //---------------------------------------------------------------------------
261 // Initialize IPC for Shared Buffer Module
262 //---------------------------------------------------------------------------
264 tShbError ShbIpcInit (void)
266 psMemTableElementFirst_g = NULL;
273 //---------------------------------------------------------------------------
274 // Deinitialize IPC for Shared Buffer Module
275 //---------------------------------------------------------------------------
277 tShbError ShbIpcExit (void)
286 //---------------------------------------------------------------------------
287 // Allocate Shared Buffer
288 //---------------------------------------------------------------------------
290 tShbError ShbIpcAllocBuffer (
291 unsigned long ulBufferSize_p,
292 const char* pszBufferID_p,
293 tShbInstance* ppShbInstance_p,
294 unsigned int* pfShbNewCreated_p)
298 unsigned long ulCrc32=0;
299 unsigned int uiFirstProcess=0;
300 unsigned long ulShMemSize;
301 tShbMemHeader* pShbMemHeader;
302 tShbMemInst* pShbMemInst=NULL;
303 tShbInstance pShbInstance;
304 unsigned int fShMemNewCreated=FALSE;
305 void *pSharedMem=NULL;
306 unsigned long aulCrcTable[256];
307 struct sShbMemTable *psMemTableElement;
310 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer \n");
311 ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader);
314 ShbIpcCrc32GenTable(aulCrcTable);
315 ulCrc32=ShbIpcCrc32GetCrc(pszBufferID_p,aulCrcTable);
317 DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferSize:%d sizeof(tShb..):%d\n",ulBufferSize_p,sizeof(tShbMemHeader));
318 DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer BufferId:%d MemSize:%d\n",iBufferId,ulShMemSize);
319 //---------------------------------------------------------------
320 // (1) open an existing or create a new shared memory
321 //---------------------------------------------------------------
322 //test if buffer already exists
323 if (ShbIpcFindListElement(iBufferId, &psMemTableElement) == 0)
325 //Buffer already exists
326 fShMemNewCreated=FALSE;
327 pSharedMem = psMemTableElement->m_pBuffer;
328 DEBUG_LVL_29_TRACE1("ShbIpcAllocBuffer attach Buffer at:%p Id:%d\n",pSharedMem);
334 fShMemNewCreated = TRUE;
336 pSharedMem = kmalloc(ulShMemSize,GFP_KERNEL);
337 DEBUG_LVL_29_TRACE2("ShbIpcAllocBuffer Create New Buffer at:%p Id:%d\n",pSharedMem,iBufferId);
338 if (pSharedMem == NULL)
340 //unable to create mem
341 ShbError = kShbOutOfMem;
344 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer create semas\n");
345 // append Element to Mem Table
346 psMemTableElement = kmalloc(sizeof(struct sShbMemTable),GFP_KERNEL);
347 psMemTableElement->m_iBufferId = iBufferId;
348 psMemTableElement->m_pBuffer = pSharedMem;
349 psMemTableElement->m_psNextMemTableElement = NULL;
350 ShbIpcAppendListElement (psMemTableElement);
353 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer update header\n");
355 pShbMemHeader = (tShbMemHeader*)pSharedMem;
356 DEBUG_LVL_29_TRACE1("ShbIpcAllocBuffer 0 pShbMemHeader->m_ulShMemSize: %d\n",pShbMemHeader->m_ulShMemSize);
357 // allocate a memory block from process specific mempool to save
358 // process local information to administrate/manage the shared buffer
359 DEBUG_LVL_29_TRACE0("ShbIpcAllocBuffer alloc private mem\n");
360 pShbMemInst = (tShbMemInst*) ShbIpcAllocPrivateMem (sizeof(tShbMemInst));
361 if (pShbMemInst == NULL)
363 ShbError = kShbOutOfMem;
367 // reset complete header to default values
368 //pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID;
369 // pShbMemInst->m_pSharedMem = pSharedMem;
370 pShbMemInst->m_tThreadNewDataId = INVALID_ID;
371 pShbMemInst->m_tThreadJobReadyId = INVALID_ID;
372 pShbMemInst->m_pfnSigHndlrNewData = NULL;
373 pShbMemInst->m_ulTimeOutJobReady = 0;
374 pShbMemInst->m_pfnSigHndlrJobReady = NULL;
375 pShbMemInst->m_pShbMemHeader = pShbMemHeader;
376 pShbMemInst->m_iThreadTermFlag = 0;
378 // initialize completion etc.
379 init_completion(&pShbMemInst->m_CompletionNewData);
382 if ( fShMemNewCreated )
384 // this process was the first who wanted to use the shared memory,
385 // so a new shared memory was created
386 // -> setup new header information inside the shared memory region
388 pShbMemHeader->m_ulShMemSize = ulShMemSize;
389 pShbMemHeader->m_ulRefCount = 1;
390 pShbMemHeader->m_iBufferId=iBufferId;
391 // initialize spinlock
392 spin_lock_init(&pShbMemHeader->m_SpinlockBuffAccess);
393 // initialize wait queues
394 init_waitqueue_head(&pShbMemHeader->m_WaitQueueNewData);
395 init_waitqueue_head(&pShbMemHeader->m_WaitQueueJobReady);
399 // any other process has created the shared memory and this
400 // process only has to attach to it
401 // -> check and update existing header information inside the
402 // shared memory region itself
403 if (pShbMemHeader->m_ulShMemSize != ulShMemSize)
405 ShbError = kShbOpenMismatch;
408 pShbMemHeader->m_ulRefCount++;
412 pShbInstance = (tShbInstance*)pShbMemInst;
413 *pfShbNewCreated_p = fShMemNewCreated;
414 *ppShbInstance_p = pShbInstance;
421 //---------------------------------------------------------------------------
422 // Release Shared Buffer
423 //---------------------------------------------------------------------------
425 tShbError ShbIpcReleaseBuffer (tShbInstance pShbInstance_p)
427 tShbMemInst* pShbMemInst;
428 tShbMemHeader* pShbMemHeader;
432 DEBUG_LVL_26_TRACE1("ShbIpcReleaseBuffer(%p)\n", pShbInstance_p);
433 if (pShbInstance_p == NULL)
437 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
438 pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
440 // stop threads in any case, because they are bound to that specific instance
441 ShbError2 = ShbIpcStopSignalingNewData (pShbInstance_p);
442 // d.k.: Whats up with JobReady thread?
443 // Just wake it up, but without setting the semaphore variable
444 wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady);
446 if ( !--pShbMemHeader->m_ulRefCount )
449 // delete mem table element
450 ShbIpcDeleteListElement(pShbMemHeader->m_iBufferId);
452 kfree(pShbMemInst->m_pShbMemHeader);
456 ShbError = kShbMemUsedByOtherProcs;
464 #endif // !defined(SHBIPC_INLINE_ENABLED)
466 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
469 //---------------------------------------------------------------------------
470 // Enter atomic section for Shared Buffer access
471 //---------------------------------------------------------------------------
473 INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection (
474 tShbInstance pShbInstance_p)
477 tShbMemInst* pShbMemInst;
478 tShbMemHeader* pShbMemHeader;
479 tShbError ShbError = kShbOk;
481 if (pShbInstance_p == NULL)
483 ShbError = kShbInvalidArg;
486 DEBUG_LVL_29_TRACE0("enter atomic\n");
487 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
488 pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
491 spin_lock_irqsave(&pShbMemHeader->m_SpinlockBuffAccess, pShbMemInst->m_ulFlagsBuffAccess);
500 //---------------------------------------------------------------------------
501 // Leave atomic section for Shared Buffer access
502 //---------------------------------------------------------------------------
504 INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection (
505 tShbInstance pShbInstance_p)
508 tShbMemInst* pShbMemInst;
509 tShbMemHeader* pShbMemHeader;
510 tShbError ShbError = kShbOk;
512 if (pShbInstance_p == NULL)
514 ShbError = kShbInvalidArg;
517 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
518 pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
520 spin_unlock_irqrestore(&pShbMemHeader->m_SpinlockBuffAccess, pShbMemInst->m_ulFlagsBuffAccess);
523 DEBUG_LVL_29_TRACE0("Leave Atomic \n");
530 //---------------------------------------------------------------------------
531 // Start signaling of new data (called from reading process)
532 //---------------------------------------------------------------------------
534 INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData (
535 tShbInstance pShbInstance_p,
536 tSigHndlrNewData pfnSignalHandlerNewData_p,
537 tShbPriority ShbPriority_p)
539 tShbMemInst* pShbMemInst;
540 tShbMemHeader* pShbMemHeader;
543 DEBUG_LVL_29_TRACE0("------->ShbIpcStartSignalingNewData\n");
544 if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL))
546 return (kShbInvalidArg);
549 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
550 pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
553 if ((pShbMemInst->m_tThreadNewDataId != INVALID_ID)
554 || (pShbMemInst->m_pfnSigHndlrNewData != NULL))
556 ShbError = kShbAlreadySignaling;
559 DEBUG_LVL_26_TRACE2("ShbIpcStartSignalingNewData(%p) m_pfnSigHndlrNewData = %p\n", pShbInstance_p, pfnSignalHandlerNewData_p);
560 pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
561 pShbMemHeader->m_fNewData = FALSE;
562 pShbMemInst->m_iThreadTermFlag = 0;
564 switch (ShbPriority_p)
566 case kShbPriorityLow:
567 pShbMemInst->m_lThreadNewDataNice = -2;
570 case kShbPriorityNormal:
571 pShbMemInst->m_lThreadNewDataNice = -9;
574 case kshbPriorityHigh:
575 pShbMemInst->m_lThreadNewDataNice = -20;
580 //create thread for signalling new data
581 pShbMemInst->m_tThreadNewDataId = kernel_thread(ShbIpcThreadSignalNewData,pShbInstance_p,CLONE_KERNEL);
590 //---------------------------------------------------------------------------
591 // Stop signaling of new data (called from reading process)
592 //---------------------------------------------------------------------------
594 INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData (
595 tShbInstance pShbInstance_p)
597 tShbMemInst* pShbMemInst;
598 tShbMemHeader* pShbMemHeader;
601 DEBUG_LVL_29_TRACE0("------->ShbIpcStopSignalingNewData\n");
602 if (pShbInstance_p == NULL)
604 return (kShbInvalidArg);
607 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
608 pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
610 DEBUG_LVL_26_TRACE2("ShbIpcStopSignalingNewData(%p) pfnSignHndlrNewData=%p\n", pShbInstance_p, pShbMemInst->m_pfnSigHndlrNewData);
611 if (pShbMemInst->m_pfnSigHndlrNewData != NULL)
612 { // signal handler was set before
614 //set termination flag in mem header
615 pShbMemInst->m_iThreadTermFlag = 1;
617 // check if thread is still running at all by sending the null-signal to this thread
618 /* iErr = kill_proc(pShbMemInst->m_tThreadNewDataId, 0, 1); */
619 iErr = send_sig(0, pShbMemInst->m_tThreadNewDataId, 1);
622 // wake up thread, because it is still running
623 wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData);
625 //wait for termination of thread
626 wait_for_completion(&pShbMemInst->m_CompletionNewData);
629 pShbMemInst->m_pfnSigHndlrNewData = NULL;
630 pShbMemInst->m_tThreadNewDataId = INVALID_ID;
639 //---------------------------------------------------------------------------
640 // Signal new data (called from writing process)
641 //---------------------------------------------------------------------------
643 INLINE_FUNCTION tShbError ShbIpcSignalNewData (
644 tShbInstance pShbInstance_p)
646 tShbMemHeader* pShbMemHeader;
648 if (pShbInstance_p == NULL)
650 return (kShbInvalidArg);
652 pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p));
654 pShbMemHeader->m_fNewData = TRUE;
655 DEBUG_LVL_29_TRACE0("ShbIpcSignalNewData set Sem -> New Data\n");
657 wake_up_interruptible(&pShbMemHeader->m_WaitQueueNewData);
663 //---------------------------------------------------------------------------
664 // Start signaling for job ready (called from waiting process)
665 //---------------------------------------------------------------------------
667 INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady (
668 tShbInstance pShbInstance_p,
669 unsigned long ulTimeOut_p,
670 tSigHndlrJobReady pfnSignalHandlerJobReady_p)
672 tShbMemInst* pShbMemInst;
673 tShbMemHeader* pShbMemHeader;
676 if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL))
678 return (kShbInvalidArg);
680 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance_p);
681 pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
684 if ((pShbMemInst->m_tThreadJobReadyId != INVALID_ID)||(pShbMemInst->m_pfnSigHndlrJobReady!= NULL))
686 ShbError = kShbAlreadySignaling;
689 pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p;
690 pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p;
691 pShbMemHeader->m_fJobReady = FALSE;
692 //create thread for signalling new data
693 pShbMemInst->m_tThreadJobReadyId=kernel_thread(ShbIpcThreadSignalJobReady,pShbInstance_p,CLONE_KERNEL);
700 //---------------------------------------------------------------------------
701 // Signal job ready (called from executing process)
702 //---------------------------------------------------------------------------
704 INLINE_FUNCTION tShbError ShbIpcSignalJobReady (
705 tShbInstance pShbInstance_p)
707 tShbMemHeader* pShbMemHeader;
710 DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady\n");
711 if (pShbInstance_p == NULL)
713 return (kShbInvalidArg);
715 pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p));
717 pShbMemHeader->m_fJobReady = TRUE;
718 DEBUG_LVL_29_TRACE0("ShbIpcSignalJobReady set Sem -> Job Ready \n");
720 wake_up_interruptible(&pShbMemHeader->m_WaitQueueJobReady);
726 //---------------------------------------------------------------------------
727 // Get pointer to common used share memory area
728 //---------------------------------------------------------------------------
730 INLINE_FUNCTION void* ShbIpcGetShMemPtr (tShbInstance pShbInstance_p)
733 tShbMemHeader* pShbMemHeader;
737 pShbMemHeader = ShbIpcGetShbMemHeader (ShbIpcGetShbMemInst (pShbInstance_p));
738 if (pShbMemHeader != NULL)
740 pShbShMemPtr = (BYTE*)pShbMemHeader + sizeof(tShbMemHeader);
747 return (pShbShMemPtr);
755 //=========================================================================//
757 // P R I V A T E F U N C T I O N S //
759 //=========================================================================//
761 #if !defined(SHBIPC_INLINE_ENABLED)
763 //---------------------------------------------------------------------------
764 // Get pointer to process local information structure
765 //---------------------------------------------------------------------------
767 /*tShbMemInst* ShbIpcGetShbMemInst (
768 tShbInstance pShbInstance_p)
771 tShbMemInst* pShbMemInst;
774 pShbMemInst = (tShbMemInst*)pShbInstance_p;
777 return (pShbMemInst);
783 //---------------------------------------------------------------------------
784 // Get pointer to shared memory header
785 //---------------------------------------------------------------------------
787 /*tShbMemHeader* ShbIpcGetShbMemHeader (
788 tShbMemInst* pShbMemInst_p)
791 tShbMemHeader* pShbMemHeader;
794 pShbMemHeader = pShbMemInst_p->m_pShbMemHeader;
796 return (pShbMemHeader);
802 //---------------------------------------------------------------------------
803 // Allocate a memory block from process specific mempool
804 //---------------------------------------------------------------------------
806 static void* ShbIpcAllocPrivateMem (unsigned long ulMemSize_p)
811 DEBUG_LVL_29_TRACE0("ShbIpcAllocPrivateMem \n");
813 pMem = kmalloc(ulMemSize_p, GFP_KERNEL);
816 //unable to create mem
817 ShbError = kShbOutOfMem;
826 //---------------------------------------------------------------------------
827 // Thread for new data signaling
828 //---------------------------------------------------------------------------
830 int ShbIpcThreadSignalNewData (void *pvThreadParam_p)
832 tShbInstance pShbInstance;
833 tShbMemInst* pShbMemInst;
834 tShbMemHeader* pShbMemHeader;
838 daemonize("ShbND%p", pvThreadParam_p);
839 allow_signal(SIGTERM);
840 pShbInstance = (tShbMemInst*)pvThreadParam_p;
841 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance);
842 pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
844 DEBUG_LVL_26_TRACE1("ShbIpcThreadSignalNewData(%p)\n",pvThreadParam_p);
846 set_user_nice(current, pShbMemInst->m_lThreadNewDataNice);
848 // DEBUG_LVL_29_TRACE1("ShbIpcThreadSignalNewData wait for New Data Sem %p\n",pShbMemInst->m_pSemNewData);
851 iRetVal = wait_event_interruptible(pShbMemHeader->m_WaitQueueNewData,
852 (pShbMemInst->m_iThreadTermFlag != 0) || (pShbMemHeader->m_fNewData != FALSE));
859 if (pShbMemHeader->m_fNewData != FALSE)
861 pShbMemHeader->m_fNewData = FALSE;
864 fCallAgain = pShbMemInst->m_pfnSigHndlrNewData(pShbInstance);
865 // call scheduler, which will execute any task with higher priority
867 } while (fCallAgain != FALSE);
869 } while (pShbMemInst->m_iThreadTermFlag==0);
870 DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalNewData terminated \n");
871 //set thread completed
872 complete_and_exit(&pShbMemInst->m_CompletionNewData, 0);
878 //---------------------------------------------------------------------------
879 // Thread for new data Job Ready signaling
880 //---------------------------------------------------------------------------
882 int ShbIpcThreadSignalJobReady (void *pvThreadParam_p)
884 tShbInstance pShbInstance;
885 tShbMemInst* pShbMemInst;
886 tShbMemHeader* pShbMemHeader;
890 daemonize("ShbJR%p", pvThreadParam_p);
891 allow_signal(SIGTERM);
892 pShbInstance = (tShbMemInst*)pvThreadParam_p;
893 pShbMemInst = ShbIpcGetShbMemInst (pShbInstance);
894 pShbMemHeader = ShbIpcGetShbMemHeader (pShbMemInst);
896 DEBUG_LVL_29_TRACE0("ShbIpcThreadSignalJobReady wait for job ready Sem\n");
897 if (pShbMemInst->m_ulTimeOutJobReady != 0)
899 lTimeOut = (long) pShbMemInst->m_ulTimeOutJobReady;
900 //wait for job ready semaphore
901 iRetVal = wait_event_interruptible_timeout(pShbMemHeader->m_WaitQueueJobReady,
902 (pShbMemHeader->m_fJobReady != FALSE), lTimeOut);
906 //wait for job ready semaphore
907 iRetVal = wait_event_interruptible(pShbMemHeader->m_WaitQueueJobReady,
908 (pShbMemHeader->m_fJobReady != FALSE));
911 if (pShbMemInst->m_pfnSigHndlrJobReady != NULL)
914 pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, !pShbMemHeader->m_fJobReady);
917 pShbMemInst->m_pfnSigHndlrJobReady=NULL;
923 //Build the crc table
924 static void ShbIpcCrc32GenTable(unsigned long aulCrcTable[256])
926 unsigned long ulCrc,ulPoly;
929 ulPoly = 0xEDB88320L;
930 for (iIndexI = 0; iIndexI < 256; iIndexI++)
933 for (iIndexJ = 8; iIndexJ > 0; iIndexJ--)
937 ulCrc = (ulCrc >> 1) ^ ulPoly;
944 aulCrcTable[iIndexI] = ulCrc;
948 //Calculate the crc value
949 static unsigned long ShbIpcCrc32GetCrc(const char *pcString,unsigned long aulCrcTable[256])
955 for (iIndex=0;iIndex<strlen(pcString);iIndex++)
957 ulCrc = ((ulCrc>>8) & 0x00FFFFFF) ^ aulCrcTable[ (ulCrc^pcString[iIndex]) & 0xFF ];
959 return( ulCrc^0xFFFFFFFF );
963 static void ShbIpcAppendListElement (struct sShbMemTable *psNewMemTableElement)
965 struct sShbMemTable *psMemTableElement=psMemTableElementFirst_g;
966 psNewMemTableElement->m_psNextMemTableElement=NULL;
968 if (psMemTableElementFirst_g!= NULL )
969 { /* sind Elemente vorhanden */
970 while (psMemTableElement->m_psNextMemTableElement != NULL )
971 { /* suche das letzte Element */
972 psMemTableElement=psMemTableElement->m_psNextMemTableElement;
974 psMemTableElement->m_psNextMemTableElement=psNewMemTableElement; /* Haenge das Element hinten an */
977 { /* wenn die liste leer ist, bin ich das erste Element */
978 psMemTableElementFirst_g=psNewMemTableElement;
985 static int ShbIpcFindListElement (int iBufferId, struct sShbMemTable **ppsReturnMemTableElement)
987 struct sShbMemTable *psMemTableElement=psMemTableElementFirst_g;
988 while (psMemTableElement!=NULL)
990 if(psMemTableElement->m_iBufferId==iBufferId)
992 //printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",psMemTableElement->m_pBuffer,psMemTableElement->m_iBufferId);
993 *ppsReturnMemTableElement=psMemTableElement;
994 //printk("ShbIpcFindListElement Buffer at:%p Id:%d\n",(*ppsReturnMemTableElement)->m_pBuffer,(*ppsReturnMemTableElement)->m_iBufferId);
997 psMemTableElement=psMemTableElement->m_psNextMemTableElement;
1002 static void ShbIpcDeleteListElement(int iBufferId)
1004 struct sShbMemTable *psMemTableElement=psMemTableElementFirst_g;
1005 struct sShbMemTable *psMemTableElementOld=psMemTableElementFirst_g;
1006 if (psMemTableElement!=NULL)
1008 while((psMemTableElement!=NULL)&&(psMemTableElement->m_iBufferId!=iBufferId))
1010 psMemTableElementOld=psMemTableElement;
1011 psMemTableElement=psMemTableElement->m_psNextMemTableElement;
1013 if (psMemTableElement!=NULL)
1015 if (psMemTableElement!=psMemTableElementFirst_g)
1017 psMemTableElementOld->m_psNextMemTableElement=psMemTableElement->m_psNextMemTableElement;
1018 kfree(psMemTableElement);
1022 kfree(psMemTableElement);
1023 psMemTableElementFirst_g=NULL;