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