Staging: comedi: fix 64bit build errors
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / epl / ShbIpc-Win32.c
blobb9181471ae0ba6208c540f806792123be5b6caf5
1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: Project independend shared buffer (linear + circular)
8 Description: Implementation of platform specific part for the
9 shared buffer
10 (Implementation for Win32)
12 License:
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions
16 are met:
18 1. Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
21 2. Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in the
23 documentation and/or other materials provided with the distribution.
25 3. Neither the name of SYSTEC electronic GmbH nor the names of its
26 contributors may be used to endorse or promote products derived
27 from this software without prior written permission. For written
28 permission, please contact info@systec-electronic.com.
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 POSSIBILITY OF SUCH DAMAGE.
43 Severability Clause:
45 If a provision of this License is or becomes illegal, invalid or
46 unenforceable in any jurisdiction, that shall not affect:
47 1. the validity or enforceability in that jurisdiction of any other
48 provision of this License; or
49 2. the validity or enforceability in other jurisdictions of that or
50 any other provision of this License.
52 -------------------------------------------------------------------------
54 2006/06/27 -rs: V 1.00 (initial version)
56 ****************************************************************************/
58 #define WINVER 0x0400 // #defines necessary for usage of
59 #define _WIN32_WINNT 0x0400 // function <SignalObjectAndWait>
61 #include <windows.h>
62 #include <stdio.h>
63 #include "global.h"
64 #include "sharedbuff.h"
65 #include "shbipc.h"
67 /***************************************************************************/
68 /* */
69 /* */
70 /* G L O B A L D E F I N I T I O N S */
71 /* */
72 /* */
73 /***************************************************************************/
75 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
77 //---------------------------------------------------------------------------
78 // Configuration
79 //---------------------------------------------------------------------------
81 //---------------------------------------------------------------------------
82 // Constant definitions
83 //---------------------------------------------------------------------------
85 #define MAX_LEN_BUFFER_ID MAX_PATH
87 #define IDX_EVENT_NEW_DATA 0
88 #define IDX_EVENT_TERM_REQU 1
89 #define IDX_EVENT_TERM_RESP 2
91 #define NAME_MUTEX_BUFF_ACCESS "BuffAccess"
92 #define NAME_EVENT_NEW_DATA "NewData"
93 #define NAME_EVENT_TERM_REQU "TermRequ"
94 #define NAME_EVENT_TERM_RESP "TermResp"
95 #define NAME_EVENT_JOB_READY "JobReady"
97 #define TIMEOUT_ENTER_ATOMIC 1000 // for debgging: INFINITE
98 #define TIMEOUT_TERM_THREAD 2000
100 #define SBI_MAGIC_ID 0x5342492B // magic ID ("SBI+")
101 #define SBH_MAGIC_ID 0x5342482A // magic ID ("SBH*")
103 //---------------------------------------------------------------------------
104 // Local types
105 //---------------------------------------------------------------------------
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.
113 typedef struct {
114 unsigned long m_SbhMagicID; // magic ID ("SBH*")
115 unsigned long m_ulShMemSize;
116 unsigned long m_ulRefCount;
117 char m_szBufferID[MAX_LEN_BUFFER_ID];
119 #ifndef NDEBUG
120 unsigned long m_ulOwnerProcID;
121 #endif
123 } tShbMemHeader;
125 // This structure is the "external entry point" from a separate process
126 // to get access to a shared buffer. This structure includes all platform
127 // resp. target specific information to administrate/manage the shared
128 // buffer from a separate process. Every process attached to the shared
129 // buffer has its own runtime instance of this structure with its individual
130 // runtime data (e.g. the scope of an event handle is limitted to the
131 // owner process only). The structure member <m_pShbMemHeader> points
132 // to the (process specific) start address of the shared memory region
133 // itself.
134 typedef struct {
135 unsigned long m_SbiMagicID; // magic ID ("SBI+")
136 HANDLE m_hSharedMem;
137 HANDLE m_hMutexBuffAccess;
138 HANDLE m_hThreadNewData; // thraed to signal that new data are available
139 HANDLE m_ahEventNewData[3]; // IDX_EVENT_NEW_DATA + IDX_EVENT_TERM_REQU + ID_EVENT_TERM_RESP
140 tSigHndlrNewData m_pfnSigHndlrNewData;
141 HANDLE m_hThreadJobReady; // thread to signal that a job/operation is ready now (e.g. reset buffer)
142 HANDLE m_hEventJobReady;
143 unsigned long m_ulTimeOutJobReady;
144 tSigHndlrJobReady m_pfnSigHndlrJobReady;
145 tShbMemHeader *m_pShbMemHeader;
147 #ifndef NDEBUG
148 unsigned long m_ulThreadIDNewData;
149 unsigned long m_ulThreadIDJobReady;
150 #endif
152 } tShbMemInst;
154 //---------------------------------------------------------------------------
155 // Global variables
156 //---------------------------------------------------------------------------
158 //---------------------------------------------------------------------------
159 // Local variables
160 //---------------------------------------------------------------------------
162 //---------------------------------------------------------------------------
163 // Prototypes of internal functions
164 //---------------------------------------------------------------------------
166 //---------------------------------------------------------------------------
167 // Get pointer to process local information structure
168 //---------------------------------------------------------------------------
170 INLINE_FUNCTION tShbMemInst *ShbIpcGetShbMemInst(tShbInstance pShbInstance_p)
173 tShbMemInst *pShbMemInst;
175 pShbMemInst = (tShbMemInst *) pShbInstance_p;
176 ASSERT(pShbMemInst->m_SbiMagicID == SBI_MAGIC_ID);
178 return (pShbMemInst);
182 //---------------------------------------------------------------------------
183 // Get pointer to shared memory header
184 //---------------------------------------------------------------------------
186 INLINE_FUNCTION tShbMemHeader *ShbIpcGetShbMemHeader(tShbInstance
187 pShbInstance_p)
190 tShbMemInst *pShbMemInst;
191 tShbMemHeader *pShbMemHeader;
193 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
194 pShbMemHeader = pShbMemInst->m_pShbMemHeader;
195 ASSERT(pShbMemHeader->m_SbhMagicID == SBH_MAGIC_ID);
197 return (pShbMemHeader);
201 // not inlined internal functions
202 DWORD WINAPI ShbIpcThreadSignalNewData(LPVOID pvThreadParam_p);
203 DWORD WINAPI ShbIpcThreadSignalJobReady(LPVOID pvThreadParam_p);
204 const char *ShbIpcGetUniformObjectName(const char *pszEventJobName_p,
205 const char *pszBufferID_p,
206 BOOL fGlobalObject_p);
208 #endif
210 #if !defined(SHBIPC_INLINE_ENABLED)
211 // true internal functions (not inlined)
212 static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p);
213 static void ShbIpcReleasePrivateMem(void *pMem_p);
214 #endif
216 //=========================================================================//
217 // //
218 // P U B L I C F U N C T I O N S //
219 // //
220 //=========================================================================//
222 #if !defined(SHBIPC_INLINE_ENABLED)
223 // not inlined external functions
225 //---------------------------------------------------------------------------
226 // Initialize IPC for Shared Buffer Module
227 //---------------------------------------------------------------------------
229 tShbError ShbIpcInit(void)
232 return (kShbOk);
236 //---------------------------------------------------------------------------
237 // Deinitialize IPC for Shared Buffer Module
238 //---------------------------------------------------------------------------
240 tShbError ShbIpcExit(void)
243 return (kShbOk);
247 //---------------------------------------------------------------------------
248 // Allocate Shared Buffer
249 //---------------------------------------------------------------------------
251 tShbError ShbIpcAllocBuffer(unsigned long ulBufferSize_p,
252 const char *pszBufferID_p,
253 tShbInstance * ppShbInstance_p,
254 unsigned int *pfShbNewCreated_p)
257 HANDLE hSharedMem;
258 LPVOID pSharedMem;
259 unsigned long ulShMemSize;
260 tShbMemInst *pShbMemInst;
261 tShbMemHeader *pShbMemHeader;
262 tShbInstance pShbInstance;
263 unsigned int fShMemNewCreated;
264 const char *pszObjectName;
265 HANDLE hMutexBuffAccess;
266 HANDLE hEventNewData;
267 HANDLE hEventJobReady;
268 tShbError ShbError;
270 ulShMemSize = ulBufferSize_p + sizeof(tShbMemHeader);
271 pSharedMem = NULL;
272 pShbInstance = NULL;
273 fShMemNewCreated = FALSE;
274 ShbError = kShbOk;
276 //---------------------------------------------------------------
277 // (1) open an existing or create a new shared memory
278 //---------------------------------------------------------------
279 // try to open an already existing shared memory
280 // (created by an another process)
281 hSharedMem = OpenFileMapping(FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess
282 FALSE, // BOOL bInheritHandle
283 pszBufferID_p); // LPCTSTR lpName
284 if (hSharedMem != NULL) {
285 // a shared memory already exists
286 fShMemNewCreated = FALSE;
287 } else {
288 // it seams that this process is the first who wants to use the
289 // shared memory, so it has to create a new shared memory
290 hSharedMem = CreateFileMapping(INVALID_HANDLE_VALUE, // HANDLE hFile
291 NULL, // LPSECURITY_ATTRIBUTES lpAttributes
292 PAGE_READWRITE, // DWORD flProtect
293 0, // DWORD dwMaximumSizeHigh
294 ulShMemSize, // DWORD dwMaximumSizeLow
295 pszBufferID_p); // LPCTSTR lpName
297 fShMemNewCreated = TRUE;
300 if (hSharedMem == NULL) {
301 ShbError = kShbOutOfMem;
302 goto Exit;
305 //---------------------------------------------------------------
306 // (2) get the pointer to the shared memory
307 //---------------------------------------------------------------
308 pSharedMem = MapViewOfFile(hSharedMem, // HANDLE hFileMappingObject
309 FILE_MAP_ALL_ACCESS, // DWORD dwDesiredAccess,
310 0, // DWORD dwFileOffsetHigh,
311 0, // DWORD dwFileOffsetLow,
312 ulShMemSize); // SIZE_T dwNumberOfBytesToMap
314 if (pSharedMem == NULL) {
315 ShbError = kShbOutOfMem;
316 goto Exit;
319 //---------------------------------------------------------------
320 // (3) setup or update header and management information
321 //---------------------------------------------------------------
322 pShbMemHeader = (tShbMemHeader *) pSharedMem;
324 // allocate a memory block from process specific mempool to save
325 // process local information to administrate/manage the shared buffer
326 pShbMemInst =
327 (tShbMemInst *) ShbIpcAllocPrivateMem(sizeof(tShbMemInst));
328 if (pShbMemInst == NULL) {
329 ShbError = kShbOutOfMem;
330 goto Exit;
332 // reset complete header to default values
333 pShbMemInst->m_SbiMagicID = SBI_MAGIC_ID;
334 pShbMemInst->m_hSharedMem = hSharedMem;
335 pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE;
336 pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE;
337 pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] =
338 INVALID_HANDLE_VALUE;
339 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] =
340 INVALID_HANDLE_VALUE;
341 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] =
342 INVALID_HANDLE_VALUE;
343 pShbMemInst->m_pfnSigHndlrNewData = NULL;
344 pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE;
345 pShbMemInst->m_hEventJobReady = INVALID_HANDLE_VALUE;
346 pShbMemInst->m_ulTimeOutJobReady = 0;
347 pShbMemInst->m_pfnSigHndlrJobReady = NULL;
348 pShbMemInst->m_pShbMemHeader = pShbMemHeader;
350 #ifndef NDEBUG
352 pShbMemInst->m_ulThreadIDNewData = 0;
353 pShbMemInst->m_ulThreadIDJobReady = 0;
355 #endif
357 // create mutex for buffer access
358 pszObjectName =
359 ShbIpcGetUniformObjectName(NAME_MUTEX_BUFF_ACCESS, pszBufferID_p,
360 TRUE);
361 hMutexBuffAccess = CreateMutex(NULL, // LPSECURITY_ATTRIBUTES lpMutexAttributes
362 FALSE, // BOOL bInitialOwner
363 pszObjectName); // LPCTSTR lpName
364 pShbMemInst->m_hMutexBuffAccess = hMutexBuffAccess;
365 ASSERT(pShbMemInst->m_hMutexBuffAccess != NULL);
367 // The EventNewData is used for signaling of new data after a write
368 // operation (SetEvent) as well as for waiting for new data on the
369 // reader side (WaitForMultipleObjects). Because it's not known if
370 // this process will be read or write data, the event will be
371 // always created here.
372 pszObjectName =
373 ShbIpcGetUniformObjectName(NAME_EVENT_NEW_DATA, pszBufferID_p,
374 TRUE);
375 hEventNewData = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
376 FALSE, // BOOL bManualReset
377 FALSE, // BOOL bInitialState
378 pszObjectName); // LPCTSTR lpName
379 pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] = hEventNewData;
380 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] != NULL);
382 // The EventJobReady is used for signaling that a job is done (SetEvent)
383 // as well as for waiting for finishing of a job (WaitForMultipleObjects).
384 // Because it's not known if this process will signal or wait, the event
385 // will be always created here.
386 pszObjectName =
387 ShbIpcGetUniformObjectName(NAME_EVENT_JOB_READY, pszBufferID_p,
388 TRUE);
389 hEventJobReady = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
390 FALSE, // BOOL bManualReset
391 FALSE, // BOOL bInitialState
392 pszObjectName); // LPCTSTR lpName
393 pShbMemInst->m_hEventJobReady = hEventJobReady;
394 ASSERT(pShbMemInst->m_hEventJobReady != NULL);
396 if (fShMemNewCreated) {
397 // this process was the first who wanted to use the shared memory,
398 // so a new shared memory was created
399 // -> setup new header information inside the shared memory region
400 // itself
401 pShbMemHeader->m_SbhMagicID = SBH_MAGIC_ID;
402 pShbMemHeader->m_ulShMemSize = ulShMemSize;
403 pShbMemHeader->m_ulRefCount = 1;
404 strncpy(pShbMemHeader->m_szBufferID, pszBufferID_p,
405 sizeof(pShbMemHeader->m_szBufferID) - 1);
407 #ifndef NDEBUG
409 pShbMemHeader->m_ulOwnerProcID = GetCurrentProcessId();
411 #endif
412 } else {
413 // any other process has created the shared memory and this
414 // process has only attached to it
415 // -> check and update existing header information inside the
416 // shared memory region itself
417 if (pShbMemHeader->m_ulShMemSize != ulShMemSize) {
418 ShbError = kShbOpenMismatch;
419 goto Exit;
421 #ifndef NDEBUG
423 if (strncmp
424 (pShbMemHeader->m_szBufferID, pszBufferID_p,
425 sizeof(pShbMemHeader->m_szBufferID) - 1)) {
426 ShbError = kShbOpenMismatch;
427 goto Exit;
430 #endif
432 pShbMemHeader->m_ulRefCount++;
435 // set abstarct "handle" for returning to application
436 pShbInstance = (tShbInstance *) pShbMemInst;
438 Exit:
440 if (ShbError != kShbOk) {
441 if (pShbMemInst != NULL) {
442 ShbIpcReleasePrivateMem(pShbMemInst);
444 if (pSharedMem != NULL) {
445 UnmapViewOfFile(pSharedMem);
447 if (hSharedMem != NULL) {
448 CloseHandle(hSharedMem);
452 *pfShbNewCreated_p = fShMemNewCreated;
453 *ppShbInstance_p = pShbInstance;
455 return (ShbError);
459 //---------------------------------------------------------------------------
460 // Release Shared Buffer
461 //---------------------------------------------------------------------------
463 tShbError ShbIpcReleaseBuffer(tShbInstance pShbInstance_p)
466 tShbMemInst *pShbMemInst;
467 tShbMemHeader *pShbMemHeader;
468 HANDLE hEventNewData;
469 HANDLE hMutexBuffAccess;
470 tShbError ShbError;
471 tShbError ShbError2;
473 if (pShbInstance_p == NULL) {
474 return (kShbOk);
477 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
478 pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
480 if (!--pShbMemHeader->m_ulRefCount) {
481 ShbError = kShbOk;
482 } else {
483 ShbError = kShbMemUsedByOtherProcs;
486 ShbError2 = ShbIpcStopSignalingNewData(pShbInstance_p);
487 hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA];
488 if (hEventNewData != INVALID_HANDLE_VALUE) {
489 CloseHandle(hEventNewData);
490 pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] =
491 INVALID_HANDLE_VALUE;
494 hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
495 if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
496 CloseHandle(hMutexBuffAccess);
497 pShbMemInst->m_hMutexBuffAccess = INVALID_HANDLE_VALUE;
500 UnmapViewOfFile(pShbMemHeader);
501 if (pShbMemInst->m_hSharedMem != INVALID_HANDLE_VALUE) {
502 CloseHandle(pShbMemInst->m_hSharedMem);
503 pShbMemInst->m_hSharedMem = INVALID_HANDLE_VALUE;
506 ShbIpcReleasePrivateMem(pShbMemInst);
508 if (ShbError == kShbOk) {
509 ShbError = ShbError2;
512 return (ShbError);
516 #endif // !defined(SHBIPC_INLINE_ENABLED)
518 #if (!defined(SHBIPC_INLINED)) || defined(SHBIPC_INLINE_ENABLED)
520 //---------------------------------------------------------------------------
521 // Enter atomic section for Shared Buffer access
522 //---------------------------------------------------------------------------
524 INLINE_FUNCTION tShbError ShbIpcEnterAtomicSection(tShbInstance pShbInstance_p)
527 tShbMemInst *pShbMemInst;
528 HANDLE hMutexBuffAccess;
529 DWORD dwWaitResult;
530 tShbError ShbError;
532 if (pShbInstance_p == NULL) {
533 return (kShbInvalidArg);
536 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
537 ShbError = kShbOk;
539 hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
540 if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
541 dwWaitResult =
542 WaitForSingleObject(hMutexBuffAccess, TIMEOUT_ENTER_ATOMIC);
543 switch (dwWaitResult) {
544 case WAIT_OBJECT_0 + 0:
546 break;
549 case WAIT_TIMEOUT:
551 TRACE0
552 ("\nShbIpcEnterAtomicSection(): WAIT_TIMEOUT");
553 ASSERT(0);
554 ShbError = kShbBufferInvalid;
555 break;
558 case WAIT_ABANDONED:
560 TRACE0
561 ("\nShbIpcEnterAtomicSection(): WAIT_ABANDONED");
562 ASSERT(0);
563 ShbError = kShbBufferInvalid;
564 break;
567 case WAIT_FAILED:
569 TRACE1
570 ("\nShbIpcEnterAtomicSection(): WAIT_FAILED -> LastError=%ld",
571 GetLastError());
572 ASSERT(0);
573 ShbError = kShbBufferInvalid;
574 break;
577 default:
579 TRACE1
580 ("\nShbIpcEnterAtomicSection(): unknown error -> LastError=%ld",
581 GetLastError());
582 ASSERT(0);
583 ShbError = kShbBufferInvalid;
584 break;
587 } else {
588 ShbError = kShbBufferInvalid;
591 return (ShbError);
595 //---------------------------------------------------------------------------
596 // Leave atomic section for Shared Buffer access
597 //---------------------------------------------------------------------------
599 INLINE_FUNCTION tShbError ShbIpcLeaveAtomicSection(tShbInstance pShbInstance_p)
602 tShbMemInst *pShbMemInst;
603 HANDLE hMutexBuffAccess;
604 BOOL fRes;
605 tShbError ShbError;
607 if (pShbInstance_p == NULL) {
608 return (kShbInvalidArg);
611 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
612 ShbError = kShbOk;
614 hMutexBuffAccess = pShbMemInst->m_hMutexBuffAccess;
615 if (hMutexBuffAccess != INVALID_HANDLE_VALUE) {
616 fRes = ReleaseMutex(hMutexBuffAccess);
617 ASSERT(fRes);
618 } else {
619 ShbError = kShbBufferInvalid;
622 return (ShbError);
626 //---------------------------------------------------------------------------
627 // Start signaling of new data (called from reading process)
628 //---------------------------------------------------------------------------
630 INLINE_FUNCTION tShbError ShbIpcStartSignalingNewData(tShbInstance
631 pShbInstance_p,
632 tSigHndlrNewData
633 pfnSignalHandlerNewData_p,
634 tShbPriority
635 ShbPriority_p)
638 tShbMemInst *pShbMemInst;
639 tShbMemHeader *pShbMemHeader;
640 const char *pszObjectName;
641 HANDLE hEventTermRequ;
642 HANDLE hEventTermResp;
643 HANDLE hThreadNewData;
644 unsigned long ulThreadIDNewData;
645 tShbError ShbError;
646 int iPriority;
648 if ((pShbInstance_p == NULL) || (pfnSignalHandlerNewData_p == NULL)) {
649 return (kShbInvalidArg);
652 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
653 pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
654 ShbError = kShbOk;
656 if ((pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) ||
657 (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] !=
658 INVALID_HANDLE_VALUE)
659 || (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
660 INVALID_HANDLE_VALUE)
661 || (pShbMemInst->m_pfnSigHndlrNewData != NULL)) {
662 ShbError = kShbAlreadySignaling;
663 goto Exit;
666 pShbMemInst->m_pfnSigHndlrNewData = pfnSignalHandlerNewData_p;
668 // Because the event <pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA]>
669 // is used for signaling of new data after a write operation too (using
670 // SetEvent), it is always created here (see <ShbIpcAllocBuffer>).
672 pszObjectName =
673 ShbIpcGetUniformObjectName(NAME_EVENT_TERM_REQU,
674 pShbMemHeader->m_szBufferID, FALSE);
675 hEventTermRequ = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
676 FALSE, // BOOL bManualReset
677 FALSE, // BOOL bInitialState
678 pszObjectName); // LPCTSTR lpName
679 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] = hEventTermRequ;
680 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] != NULL);
682 pszObjectName =
683 ShbIpcGetUniformObjectName(NAME_EVENT_TERM_RESP,
684 pShbMemHeader->m_szBufferID, FALSE);
685 hEventTermResp = CreateEvent(NULL, // LPSECURITY_ATTRIBUTES lpEventAttributes
686 FALSE, // BOOL bManualReset
687 FALSE, // BOOL bInitialState
688 pszObjectName); // LPCTSTR lpName
689 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] = hEventTermResp;
690 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] != NULL);
692 hThreadNewData = CreateThread(NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes
693 0, // SIZE_T dwStackSize
694 ShbIpcThreadSignalNewData, // LPTHREAD_START_ROUTINE lpStartAddress
695 pShbInstance_p, // LPVOID lpParameter
696 0, // DWORD dwCreationFlags
697 &ulThreadIDNewData); // LPDWORD lpThreadId
699 switch (ShbPriority_p) {
700 case kShbPriorityLow:
701 iPriority = THREAD_PRIORITY_BELOW_NORMAL;
702 break;
704 case kShbPriorityNormal:
705 iPriority = THREAD_PRIORITY_NORMAL;
706 break;
708 case kshbPriorityHigh:
709 iPriority = THREAD_PRIORITY_ABOVE_NORMAL;
710 break;
714 ASSERT(pShbMemInst->m_hThreadNewData != NULL);
716 SetThreadPriority(hThreadNewData, iPriority);
718 pShbMemInst->m_hThreadNewData = hThreadNewData;
720 #ifndef NDEBUG
722 pShbMemInst->m_ulThreadIDNewData = ulThreadIDNewData;
724 #endif
726 Exit:
728 return (ShbError);
732 //---------------------------------------------------------------------------
733 // Stop signaling of new data (called from reading process)
734 //---------------------------------------------------------------------------
736 INLINE_FUNCTION tShbError ShbIpcStopSignalingNewData(tShbInstance
737 pShbInstance_p)
740 tShbMemInst *pShbMemInst;
741 HANDLE hEventTermRequ;
742 HANDLE hEventTermResp;
743 DWORD dwWaitResult;
745 if (pShbInstance_p == NULL) {
746 return (kShbInvalidArg);
749 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
751 // terminate new data signaling thread
752 // (set event <hEventTermRequ> to wakeup the thread and dispose it
753 // to exit, then wait for confirmation using event <hEventTermResp>)
754 hEventTermRequ = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU];
755 hEventTermResp = pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP];
756 if ((hEventTermRequ != INVALID_HANDLE_VALUE) &&
757 (hEventTermResp != INVALID_HANDLE_VALUE)) {
758 TRACE0("\nShbIpcStopSignalingNewData(): enter wait state");
759 dwWaitResult = SignalObjectAndWait(hEventTermRequ, // HANDLE hObjectToSignal
760 hEventTermResp, // HANDLE hObjectToWaitOn
761 TIMEOUT_TERM_THREAD, // DWORD dwMilliseconds
762 FALSE); // BOOL bAlertable
763 TRACE0
764 ("\nShbIpcStopSignalingNewData(): wait state leaved: ---> ");
765 switch (dwWaitResult) {
766 case WAIT_OBJECT_0 + 0: // event "new data signaling thread terminated"
768 TRACE0("Event = WAIT_OBJECT_0+0");
769 break;
772 default:
774 TRACE0("Unhandled Event");
775 ASSERT(0);
776 break;
781 if (pShbMemInst->m_hThreadNewData != INVALID_HANDLE_VALUE) {
782 CloseHandle(pShbMemInst->m_hThreadNewData);
783 pShbMemInst->m_hThreadNewData = INVALID_HANDLE_VALUE;
786 if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] !=
787 INVALID_HANDLE_VALUE) {
788 CloseHandle(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU]);
789 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_REQU] =
790 INVALID_HANDLE_VALUE;
793 if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
794 INVALID_HANDLE_VALUE) {
795 CloseHandle(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]);
796 pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] =
797 INVALID_HANDLE_VALUE;
800 pShbMemInst->m_pfnSigHndlrNewData = NULL;
802 return (kShbOk);
806 //---------------------------------------------------------------------------
807 // Signal new data (called from writing process)
808 //---------------------------------------------------------------------------
810 INLINE_FUNCTION tShbError ShbIpcSignalNewData(tShbInstance pShbInstance_p)
813 tShbMemInst *pShbMemInst;
814 HANDLE hEventNewData;
815 BOOL fRes;
817 // TRACE0("\nShbIpcSignalNewData(): enter\n");
819 if (pShbInstance_p == NULL) {
820 return (kShbInvalidArg);
823 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
825 ASSERT(pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA] !=
826 INVALID_HANDLE_VALUE);
827 hEventNewData = pShbMemInst->m_ahEventNewData[IDX_EVENT_NEW_DATA];
828 if (hEventNewData != INVALID_HANDLE_VALUE) {
829 fRes = SetEvent(hEventNewData);
830 // TRACE1("\nShbIpcSignalNewData(): EventNewData set (Result=%d)\n", (int)fRes);
831 ASSERT(fRes);
833 // TRACE0("\nShbIpcSignalNewData(): leave\n");
834 return (kShbOk);
838 //---------------------------------------------------------------------------
839 // Start signaling for job ready (called from waiting process)
840 //---------------------------------------------------------------------------
842 INLINE_FUNCTION tShbError ShbIpcStartSignalingJobReady(tShbInstance
843 pShbInstance_p,
844 unsigned long
845 ulTimeOut_p,
846 tSigHndlrJobReady
847 pfnSignalHandlerJobReady_p)
850 tShbMemInst *pShbMemInst;
851 tShbMemHeader *pShbMemHeader;
852 HANDLE hThreadJobReady;
853 unsigned long ulThreadIDJobReady;
854 tShbError ShbError;
856 if ((pShbInstance_p == NULL) || (pfnSignalHandlerJobReady_p == NULL)) {
857 return (kShbInvalidArg);
860 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
861 pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
862 ShbError = kShbOk;
864 if ((pShbMemInst->m_hThreadJobReady != INVALID_HANDLE_VALUE) ||
865 (pShbMemInst->m_pfnSigHndlrJobReady != NULL)) {
866 ShbError = kShbAlreadySignaling;
867 goto Exit;
870 pShbMemInst->m_ulTimeOutJobReady = ulTimeOut_p;
871 pShbMemInst->m_pfnSigHndlrJobReady = pfnSignalHandlerJobReady_p;
873 // Because the event <pShbMemInst->m_ahEventJobReady> is used for
874 // signaling of a finished job too (using SetEvent), it is always
875 // created here (see <ShbIpcAllocBuffer>).
877 hThreadJobReady = CreateThread(NULL, // LPSECURITY_ATTRIBUTES lpThreadAttributes
878 0, // SIZE_T dwStackSize
879 ShbIpcThreadSignalJobReady, // LPTHREAD_START_ROUTINE lpStartAddress
880 pShbInstance_p, // LPVOID lpParameter
881 0, // DWORD dwCreationFlags
882 &ulThreadIDJobReady); // LPDWORD lpThreadId
884 pShbMemInst->m_hThreadJobReady = hThreadJobReady;
885 ASSERT(pShbMemInst->m_hThreadJobReady != NULL);
887 #ifndef NDEBUG
889 pShbMemInst->m_ulThreadIDJobReady = ulThreadIDJobReady;
891 #endif
893 Exit:
895 return (ShbError);
899 //---------------------------------------------------------------------------
900 // Signal job ready (called from executing process)
901 //---------------------------------------------------------------------------
903 INLINE_FUNCTION tShbError ShbIpcSignalJobReady(tShbInstance pShbInstance_p)
906 tShbMemInst *pShbMemInst;
907 HANDLE hEventJobReady;
908 BOOL fRes;
910 // TRACE0("\nShbIpcSignalJobReady(): enter\n");
912 if (pShbInstance_p == NULL) {
913 return (kShbInvalidArg);
916 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance_p);
918 ASSERT(pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE);
919 hEventJobReady = pShbMemInst->m_hEventJobReady;
920 if (hEventJobReady != INVALID_HANDLE_VALUE) {
921 fRes = SetEvent(hEventJobReady);
922 // TRACE1("\nShbIpcSignalJobReady(): EventJobReady set (Result=%d)\n", (int)fRes);
923 ASSERT(fRes);
925 // TRACE0("\nShbIpcSignalJobReady(): leave\n");
926 return (kShbOk);
930 //---------------------------------------------------------------------------
931 // Get pointer to common used share memory area
932 //---------------------------------------------------------------------------
934 INLINE_FUNCTION void *ShbIpcGetShMemPtr(tShbInstance pShbInstance_p)
937 tShbMemHeader *pShbMemHeader;
938 void *pShbShMemPtr;
940 pShbMemHeader = ShbIpcGetShbMemHeader(pShbInstance_p);
941 if (pShbMemHeader != NULL) {
942 pShbShMemPtr = (BYTE *) pShbMemHeader + sizeof(tShbMemHeader);
943 } else {
944 pShbShMemPtr = NULL;
947 return (pShbShMemPtr);
951 #endif
953 //=========================================================================//
954 // //
955 // P R I V A T E F U N C T I O N S //
956 // //
957 //=========================================================================//
959 #if !defined(SHBIPC_INLINE_ENABLED)
961 //---------------------------------------------------------------------------
962 // Allocate a memory block from process specific mempool
963 //---------------------------------------------------------------------------
965 static void *ShbIpcAllocPrivateMem(unsigned long ulMemSize_p)
968 HGLOBAL hMem;
969 void *pMem;
971 hMem = GlobalAlloc(GMEM_FIXED, ulMemSize_p + sizeof(HGLOBAL));
972 pMem = GlobalLock(hMem);
973 if (pMem != NULL) {
974 *(HGLOBAL *) pMem = hMem;
975 (BYTE *) pMem += sizeof(HGLOBAL);
978 #ifndef NDEBUG
980 memset(pMem, 0xaa, ulMemSize_p);
982 #endif
984 return (pMem);
988 //---------------------------------------------------------------------------
989 // Release a memory block from process specific mempool
990 //---------------------------------------------------------------------------
992 static void ShbIpcReleasePrivateMem(void *pMem_p)
995 HGLOBAL hMem;
997 if (pMem_p == NULL) {
998 return;
1001 (BYTE *) pMem_p -= sizeof(HGLOBAL);
1002 hMem = *(HGLOBAL *) pMem_p;
1004 GlobalUnlock(hMem);
1005 GlobalFree(hMem);
1007 return;
1011 //---------------------------------------------------------------------------
1012 // Create uniform object name (needed for inter-process communication)
1013 //---------------------------------------------------------------------------
1015 const char *ShbIpcGetUniformObjectName(const char *pszObjectJobName_p,
1016 const char *pszBufferID_p,
1017 BOOL fGlobalObject_p)
1020 static char szObjectName[MAX_PATH];
1021 char szObjectPrefix[MAX_PATH];
1023 if (fGlobalObject_p) {
1024 strncpy(szObjectPrefix, "Global\\", sizeof(szObjectPrefix));
1025 } else {
1026 _snprintf(szObjectPrefix, sizeof(szObjectPrefix), "PID%08lX_",
1027 (unsigned long)GetCurrentProcessId());
1030 _snprintf(szObjectName, sizeof(szObjectName), "%s%s#%s",
1031 szObjectPrefix, pszBufferID_p, pszObjectJobName_p);
1033 return (szObjectName);
1037 //---------------------------------------------------------------------------
1038 // Thread for new data signaling
1039 //---------------------------------------------------------------------------
1041 DWORD WINAPI ShbIpcThreadSignalNewData(LPVOID pvThreadParam_p)
1044 tShbInstance pShbInstance;
1045 tShbMemInst *pShbMemInst;
1046 DWORD dwWaitResult;
1047 BOOL fTermRequ;
1048 int fCallAgain;
1050 TRACE1
1051 ("\nShbIpcThreadSignalNewData(): SignalThread started (pShbInstance=0x%08lX)\n",
1052 (DWORD) pvThreadParam_p);
1054 pShbInstance = (tShbMemInst *) pvThreadParam_p;
1055 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
1056 fTermRequ = FALSE;
1058 do {
1059 ASSERT((pShbMemInst->m_ahEventNewData[0] !=
1060 INVALID_HANDLE_VALUE)
1061 && (pShbMemInst->m_ahEventNewData[0] != NULL));
1062 ASSERT((pShbMemInst->m_ahEventNewData[1] !=
1063 INVALID_HANDLE_VALUE)
1064 && (pShbMemInst->m_ahEventNewData[1] != NULL));
1066 TRACE0("\nShbIpcThreadSignalNewData(): enter wait state");
1067 dwWaitResult = WaitForMultipleObjects(2, // DWORD nCount
1068 pShbMemInst->m_ahEventNewData, // const HANDLE* lpHandles
1069 FALSE, // BOOL bWaitAll
1070 INFINITE); // DWORD dwMilliseconds
1071 TRACE0
1072 ("\nShbIpcThreadSignalNewData(): wait state leaved: ---> ");
1073 switch (dwWaitResult) {
1074 case WAIT_OBJECT_0 + 0: // event "new data"
1076 TRACE0("Event = WAIT_OBJECT_0+0");
1077 if (pShbMemInst->m_pfnSigHndlrNewData != NULL) {
1078 TRACE0
1079 ("\nShbIpcThreadSignalNewData(): calling SignalHandlerNewData");
1080 do {
1081 fCallAgain =
1082 pShbMemInst->
1083 m_pfnSigHndlrNewData
1084 (pShbInstance);
1085 // d.k.: try to run any shared buffer which has higher priority.
1086 // under Windows this is not really necessary because the Windows scheduler
1087 // already preempts tasks with lower priority.
1088 } while (fCallAgain != FALSE);
1090 break;
1093 case WAIT_OBJECT_0 + 1: // event "terminate"
1095 TRACE0("Event = WAIT_OBJECT_0+1");
1096 fTermRequ = TRUE;
1097 break;
1100 default:
1102 TRACE0("Unhandled Event");
1103 ASSERT(0);
1104 fTermRequ = TRUE;
1105 break;
1109 while (!fTermRequ);
1111 if (pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP] !=
1112 INVALID_HANDLE_VALUE) {
1113 SetEvent(pShbMemInst->m_ahEventNewData[IDX_EVENT_TERM_RESP]);
1116 TRACE1
1117 ("\nShbIpcThreadSignalNewData(): SignalThread terminated (pShbInstance=0x%08lX)\n",
1118 (DWORD) pShbInstance);
1120 ExitThread(0);
1124 //---------------------------------------------------------------------------
1125 // Thread for new data signaling
1126 //---------------------------------------------------------------------------
1128 DWORD WINAPI ShbIpcThreadSignalJobReady(LPVOID pvThreadParam_p)
1131 tShbInstance *pShbInstance;
1132 tShbMemInst *pShbMemInst;
1133 DWORD ulTimeOut;
1134 DWORD dwWaitResult;
1135 unsigned int fTimeOut;
1137 TRACE1
1138 ("\nShbIpcThreadSignalJobReady(): SignalThread started (pShbInstance=0x%08lX)\n",
1139 (DWORD) pvThreadParam_p);
1141 pShbInstance = (tShbInstance *) pvThreadParam_p;
1142 pShbMemInst = ShbIpcGetShbMemInst(pShbInstance);
1143 fTimeOut = FALSE;
1145 if (pShbMemInst->m_ulTimeOutJobReady != 0) {
1146 ulTimeOut = pShbMemInst->m_ulTimeOutJobReady;
1147 } else {
1148 ulTimeOut = INFINITE;
1151 ASSERT((pShbMemInst->m_hEventJobReady != INVALID_HANDLE_VALUE)
1152 && (pShbMemInst->m_hEventJobReady != NULL));
1154 TRACE0("\nShbIpcThreadSignalJobReady(): enter wait state");
1155 dwWaitResult = WaitForSingleObject(pShbMemInst->m_hEventJobReady, // HANDLE hHandle
1156 ulTimeOut); // DWORD dwMilliseconds
1157 TRACE0("\nShbIpcThreadSignalJobReady(): wait state leaved: ---> ");
1158 switch (dwWaitResult) {
1159 case WAIT_OBJECT_0 + 0: // event "new data"
1161 TRACE0("Event = WAIT_OBJECT_0+0");
1162 fTimeOut = FALSE;
1163 break;
1166 case WAIT_TIMEOUT:
1168 TRACE0("\nEvent = WAIT_TIMEOUT");
1169 fTimeOut = TRUE;
1170 // ASSERT(0);
1171 break;
1174 default:
1176 TRACE0("Unhandled Event");
1177 fTimeOut = TRUE;
1178 ASSERT(0);
1179 break;
1183 if (pShbMemInst->m_pfnSigHndlrJobReady != NULL) {
1184 TRACE0
1185 ("\nShbIpcThreadSignalJobReady(): calling SignalHandlerJobReady");
1186 pShbMemInst->m_pfnSigHndlrJobReady(pShbInstance, fTimeOut);
1189 pShbMemInst->m_hThreadJobReady = INVALID_HANDLE_VALUE;
1190 pShbMemInst->m_pfnSigHndlrJobReady = NULL;
1192 TRACE1
1193 ("\nShbIpcThreadSignalJobReady(): SignalThread terminated (pShbInstance=0x%08lX)\n",
1194 (DWORD) pShbInstance);
1196 ExitThread(0);
1200 #endif
1202 // EOF