• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
115 typedef 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.
142 typedef 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 
ShbIpcGetShbMemInst(tShbInstance pShbInstance_p)179 static 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 
ShbIpcGetShbMemHeader(tShbMemInst * pShbMemInst_p)194 static 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
212 int ShbIpcThreadSignalNewData(void *pvThreadParam_p);
213 int ShbIpcThreadSignalJobReady(void *pvThreadParam_p);
214 #endif
215 
216 //---------------------------------------------------------------------------
217 // modul globale vars
218 //---------------------------------------------------------------------------
219 
220 #if !defined(SHBIPC_INLINE_ENABLED)
221 struct sShbMemTable *psMemTableElementFirst_g;
222 
223 static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p);
224 static int ShbIpcFindListElement(int iBufferId,
225 				 struct sShbMemTable
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]);
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 
ShbIpcInit(void)248 tShbError ShbIpcInit(void)
249 {
250 	psMemTableElementFirst_g = NULL;
251 	return (kShbOk);
252 
253 }
254 
255 //---------------------------------------------------------------------------
256 //  Deinitialize IPC for Shared Buffer Module
257 //---------------------------------------------------------------------------
258 
ShbIpcExit(void)259 tShbError ShbIpcExit(void)
260 {
261 
262 	return (kShbOk);
263 
264 }
265 
266 //---------------------------------------------------------------------------
267 //  Allocate Shared Buffer
268 //---------------------------------------------------------------------------
269 
ShbIpcAllocBuffer(unsigned long ulBufferSize_p,const char * pszBufferID_p,tShbInstance * ppShbInstance_p,unsigned int * pfShbNewCreated_p)270 tShbError 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 
ShbIpcReleaseBuffer(tShbInstance pShbInstance_p)402 tShbError 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 
ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p)444 INLINE_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 
ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p)472 INLINE_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 
ShbIpcStartSignalingNewData(tShbInstance pShbInstance_p,tSigHndlrNewData pfnSignalHandlerNewData_p,tShbPriority ShbPriority_p)499 INLINE_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 
ShbIpcStopSignalingNewData(tShbInstance pShbInstance_p)560 INLINE_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 
ShbIpcSignalNewData(tShbInstance pShbInstance_p)607 INLINE_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 
ShbIpcStartSignalingJobReady(tShbInstance pShbInstance_p,unsigned long ulTimeOut_p,tSigHndlrJobReady pfnSignalHandlerJobReady_p)628 INLINE_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 
ShbIpcSignalJobReady(tShbInstance pShbInstance_p)666 INLINE_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 
ShbIpcGetShMemPtr(tShbInstance pShbInstance_p)688 INLINE_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 
724 tShbMemInst*  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 
741 tShbMemHeader*  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 
ShbIpcAllocPrivateMem(unsigned long ulMemSize_p)754 static 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 
ShbIpcThreadSignalNewData(void * pvThreadParam_p)776 int 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 
ShbIpcThreadSignalJobReady(void * pvThreadParam_p)828 int 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
ShbIpcCrc32GenTable(unsigned long aulCrcTable[256])872 static 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
ShbIpcCrc32GetCrc(const char * pcString,unsigned long aulCrcTable[256])892 static 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 
ShbIpcAppendListElement(struct sShbMemTable * psNewMemTableElement)908 static 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 
ShbIpcFindListElement(int iBufferId,struct sShbMemTable ** ppsReturnMemTableElement)924 static 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 
ShbIpcDeleteListElement(int iBufferId)940 static 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
967