Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[deliverable/linux.git] / drivers / staging / epl / ShbIpc-LinuxKernel.c
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
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
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
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
259 tShbError ShbIpcExit(void)
260 {
261
262 return (kShbOk);
263
264 }
265
266 //---------------------------------------------------------------------------
267 // Allocate Shared Buffer
268 //---------------------------------------------------------------------------
269
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
This page took 0.068599 seconds and 5 git commands to generate.