added NXCP command code range list
[public/netxms.git] / include / nms_threads.h
CommitLineData
54481027 1/*
4997be5c 2** NetXMS - Network Management System
54481027
VK
3** Copyright (C) 2003 Victor Kirhenshtein
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** $module: nms_threads.h
20**
21**/
22
23#ifndef _nms_threads_h_
24#define _nms_threads_h_
25
b71bff93
VK
26#ifdef __cplusplus
27
28#define NMS_THREADS_H_INCLUDED
29
9b2bfc05 30#if defined(_WIN32)
54481027 31
018fda4d 32#ifndef UNDER_CE
df7156b3 33#include <process.h>
018fda4d 34#endif
54481027
VK
35
36//
37// Related datatypes and constants
38//
39
dbe67493
VK
40typedef HANDLE MUTEX;
41typedef HANDLE THREAD;
42typedef HANDLE CONDITION;
54481027 43
449e3da9
VK
44#define INVALID_MUTEX_HANDLE INVALID_HANDLE_VALUE
45#define INVALID_CONDITION_HANDLE INVALID_HANDLE_VALUE
ccdbbb52
VK
46#define INVALID_THREAD_HANDLE (NULL)
47
288ddda4
VK
48#ifdef UNDER_CE
49typedef DWORD THREAD_RESULT;
50typedef DWORD THREAD_ID;
51#else
ccdbbb52 52typedef unsigned int THREAD_RESULT;
288ddda4
VK
53typedef unsigned int THREAD_ID;
54#endif
ccdbbb52
VK
55
56#define THREAD_OK 0
288ddda4
VK
57
58#ifdef UNDER_CE
59#define THREAD_CALL
60#else
ccdbbb52 61#define THREAD_CALL __stdcall
ba2c1467
VK
62
63typedef struct
64{
65 THREAD_RESULT (THREAD_CALL *start_address)(void *);
66 void *args;
67} THREAD_START_DATA;
68
69THREAD_RESULT LIBNETXMS_EXPORTABLE THREAD_CALL SEHThreadStarter(void *);
7a7ba846 70int LIBNETXMS_EXPORTABLE ___ExceptionHandler(EXCEPTION_POINTERS *pInfo);
ba2c1467 71
bb7a686c 72void LIBNETXMS_EXPORTABLE SetExceptionHandler(BOOL (*pfHandler)(EXCEPTION_POINTERS *),
ba2c1467 73 void (*pfWriter)(char *));
bb7a686c 74BOOL LIBNETXMS_EXPORTABLE SEHDefaultConsoleHandler(EXCEPTION_POINTERS *pInfo);
ba2c1467
VK
75TCHAR LIBNETXMS_EXPORTABLE *SEHExceptionName(DWORD code);
76void LIBNETXMS_EXPORTABLE SEHShowCallStack(CONTEXT *pCtx);
77
7a7ba846
VK
78#define LIBNETXMS_EXCEPTION_HANDLER \
79 } __except(___ExceptionHandler((EXCEPTION_POINTERS *)_exception_info())) { ExitProcess(99); }
80
288ddda4 81#endif
54481027
VK
82
83
84//
85// Inline functions
86//
87
dc5bad96
VK
88inline void InitThreadLibrary(void)
89{
90}
91
54481027
VK
92inline void ThreadSleep(int iSeconds)
93{
94 Sleep((DWORD)iSeconds * 1000); // Convert to milliseconds
95}
96
97inline void ThreadSleepMs(DWORD dwMilliseconds)
98{
99 Sleep(dwMilliseconds);
100}
101
ba2c1467 102inline BOOL ThreadCreate(THREAD_RESULT (THREAD_CALL *start_address)(void *), int stack_size, void *args)
54481027 103{
ccdbbb52 104 HANDLE hThread;
288ddda4 105 THREAD_ID dwThreadId;
ccdbbb52 106
f2fdf1b5 107#ifdef UNDER_CE
288ddda4 108 hThread = CreateThread(NULL, (DWORD)stack_size, start_address, args, 0, &dwThreadId);
f2fdf1b5 109#else
ba2c1467
VK
110 THREAD_START_DATA *data = (THREAD_START_DATA *)malloc(sizeof(THREAD_START_DATA));
111 data->start_address = start_address;
112 data->args = args;
113 hThread = (HANDLE)_beginthreadex(NULL, stack_size, SEHThreadStarter, data, 0, &dwThreadId);
f2fdf1b5 114#endif
ccdbbb52
VK
115 if (hThread != NULL)
116 CloseHandle(hThread);
117 return (hThread != NULL);
118}
119
ba2c1467 120inline THREAD ThreadCreateEx(THREAD_RESULT (THREAD_CALL *start_address)(void *), int stack_size, void *args)
ccdbbb52 121{
288ddda4 122 THREAD_ID dwThreadId;
ccdbbb52 123
288ddda4
VK
124#ifdef UNDER_CE
125 return CreateThread(NULL, (DWORD)stack_size, start_address, args, 0, &dwThreadId);
631ec742 126#else
ba2c1467
VK
127 THREAD_START_DATA *data = (THREAD_START_DATA *)malloc(sizeof(THREAD_START_DATA));
128 data->start_address = start_address;
129 data->args = args;
130 return (HANDLE)_beginthreadex(NULL, stack_size, SEHThreadStarter, data, 0, &dwThreadId);
631ec742 131#endif
54481027
VK
132}
133
134inline void ThreadExit(void)
135{
f2fdf1b5 136#ifdef UNDER_CE
018fda4d 137 ExitThread(0);
f2fdf1b5
VK
138#else
139 _endthreadex(0);
018fda4d 140#endif
54481027
VK
141}
142
ccdbbb52
VK
143inline void ThreadJoin(THREAD hThread)
144{
145 if (hThread != INVALID_THREAD_HANDLE)
146 {
147 WaitForSingleObject(hThread, INFINITE);
148 CloseHandle(hThread);
149 }
150}
151
54481027
VK
152inline MUTEX MutexCreate(void)
153{
154 return CreateMutex(NULL, FALSE, NULL);
155}
156
a3c76aba
VK
157inline MUTEX MutexCreateRecursive(void)
158{
159 return CreateMutex(NULL, FALSE, NULL);
160}
161
54481027
VK
162inline void MutexDestroy(MUTEX mutex)
163{
164 CloseHandle(mutex);
165}
166
167inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
168{
169 return WaitForSingleObject(mutex, dwTimeOut) == WAIT_OBJECT_0;
170}
171
172inline void MutexUnlock(MUTEX mutex)
173{
174 ReleaseMutex(mutex);
175}
176
d16cf8a5 177inline CONDITION ConditionCreate(BOOL bBroadcast)
54481027 178{
646d58de 179 return CreateEvent(NULL, bBroadcast, FALSE, NULL);
54481027
VK
180}
181
182inline void ConditionDestroy(CONDITION hCond)
183{
184 CloseHandle(hCond);
185}
186
187inline void ConditionSet(CONDITION hCond)
5f743326
VK
188{
189 SetEvent(hCond);
190}
191
192inline void ConditionReset(CONDITION hCond)
193{
194 ResetEvent(hCond);
195}
196
197inline void ConditionPulse(CONDITION hCond)
54481027 198{
39d7a7ed 199 PulseEvent(hCond);
54481027
VK
200}
201
c7f4f5a9 202inline BOOL ConditionWait(CONDITION hCond, DWORD dwTimeOut)
54481027 203{
c7f4f5a9 204 return WaitForSingleObject(hCond, dwTimeOut) == WAIT_OBJECT_0;
54481027
VK
205}
206
9b2bfc05
VK
207#elif defined(_USE_GNU_PTH)
208
209/****************************************************************************/
210/* GNU Pth */
211/****************************************************************************/
212
60414f77
VK
213//
214// Related datatypes and constants
215//
216
217typedef pth_t THREAD;
218typedef pth_mutex_t * MUTEX;
219struct netxms_condition_t
220{
221 pth_cond_t cond;
222 pth_mutex_t mutex;
223 BOOL broadcast;
224 BOOL isSet;
225};
226typedef struct netxms_condition_t * CONDITION;
227
228#define INVALID_MUTEX_HANDLE (NULL)
229#define INVALID_CONDITION_HANDLE (NULL)
230#define INVALID_THREAD_HANDLE (NULL)
231
232#ifndef INFINITE
233#define INFINITE 0
234#endif
235
236typedef void *THREAD_RESULT;
237
238#define THREAD_OK ((void *)0)
239#define THREAD_CALL
240
241
242//
243// Inline functions
244//
245
dc5bad96
VK
246inline void InitThreadLibrary(void)
247{
248 if (!pth_init())
249 {
250 perror("pth_init() failed");
251 exit(200);
252 }
253}
254
60414f77
VK
255inline void ThreadSleep(int nSeconds)
256{
257 pth_sleep(nSeconds);
258}
259
260inline void ThreadSleepMs(DWORD dwMilliseconds)
261{
cd4c8ca3 262 pth_usleep(dwMilliseconds * 1000);
60414f77
VK
263}
264
265inline BOOL ThreadCreate(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
266{
267 THREAD id;
268
269 if ((id = pth_spawn(PTH_ATTR_DEFAULT, start_address, args)) != NULL)
270 {
271 pth_attr_set(pth_attr_of(id), PTH_ATTR_JOINABLE, 0);
272 return TRUE;
273 }
274 else
275 {
276 return FALSE;
277 }
278}
279
280inline THREAD ThreadCreateEx(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
281{
282 THREAD id;
283
284 if ((id = pth_spawn(PTH_ATTR_DEFAULT, start_address, args)) != NULL)
285 {
cd4c8ca3 286 return id;
60414f77
VK
287 }
288 else
289 {
cd4c8ca3 290 return INVALID_THREAD_HANDLE;
60414f77
VK
291 }
292}
293
294inline void ThreadExit(void)
295{
296 pth_exit(NULL);
297}
298
299inline void ThreadJoin(THREAD hThread)
300{
301 if (hThread != INVALID_THREAD_HANDLE)
302 pth_join(hThread, NULL);
303}
304
305inline MUTEX MutexCreate(void)
306{
307 MUTEX mutex;
308
309 mutex = (MUTEX)malloc(sizeof(pth_mutex_t));
310 if (mutex != NULL)
dc5bad96 311 {
60414f77 312 pth_mutex_init(mutex);
dc5bad96 313 }
60414f77
VK
314 return mutex;
315}
316
317inline MUTEX MutexCreateRecursive(void)
318{
319 MUTEX mutex;
320
321 // In libpth, recursive locking is explicitly supported,
322 // so we just create mutex
323 mutex = (MUTEX)malloc(sizeof(pth_mutex_t));
324 if (mutex != NULL)
dc5bad96 325 {
60414f77 326 pth_mutex_init(mutex);
dc5bad96 327 }
60414f77
VK
328 return mutex;
329}
330
331inline void MutexDestroy(MUTEX mutex)
332{
333 if (mutex != NULL)
334 free(mutex);
335}
336
337inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
338{
339 int i;
340 int ret = FALSE;
341
342 if (mutex != NULL)
343 {
344 if (dwTimeOut == INFINITE)
345 {
346 if (pth_mutex_acquire(mutex, FALSE, NULL))
347 {
348 ret = TRUE;
349 }
350 }
351 else
352 {
353 pth_event_t ev;
354
355 ev = pth_event(PTH_EVENT_TIME, pth_timeout(dwTimeOut / 1000, (dwTimeOut % 1000) * 1000));
356 if (pth_mutex_acquire(mutex, FALSE, ev))
357 {
358 ret = TRUE;
359 }
360 pth_event_free(ev, PTH_FREE_ALL);
361 }
362 }
363 return ret;
364}
365
366inline void MutexUnlock(MUTEX mutex)
367{
368 if (mutex != NULL)
369 {
370 pth_mutex_release(mutex);
371 }
372}
373
374inline CONDITION ConditionCreate(BOOL bBroadcast)
375{
376 CONDITION cond;
377
cd4c8ca3
VK
378 cond = (CONDITION)malloc(sizeof(struct netxms_condition_t));
379 if (cond != NULL)
380 {
381 pth_cond_init(&cond->cond);
382 pth_mutex_init(&cond->mutex);
60414f77 383 cond->broadcast = bBroadcast;
cd4c8ca3 384 cond->isSet = FALSE;
60414f77
VK
385 }
386
cd4c8ca3 387 return cond;
60414f77
VK
388}
389
390inline void ConditionDestroy(CONDITION cond)
391{
392 if (cond != INVALID_CONDITION_HANDLE)
393 {
394 free(cond);
395 }
396}
397
398inline void ConditionSet(CONDITION cond)
399{
400 if (cond != INVALID_CONDITION_HANDLE)
401 {
402 pth_mutex_acquire(&cond->mutex, FALSE, NULL);
403 cond->isSet = TRUE;
404 pth_cond_notify(&cond->cond, cond->broadcast);
405 pth_mutex_release(&cond->mutex);
406 }
407}
408
409inline void ConditionReset(CONDITION cond)
410{
411 if (cond != INVALID_CONDITION_HANDLE)
412 {
413 pth_mutex_acquire(&cond->mutex, FALSE, NULL);
414 cond->isSet = FALSE;
415 pth_mutex_release(&cond->mutex);
416 }
417}
418
419inline void ConditionPulse(CONDITION cond)
420{
421 if (cond != INVALID_CONDITION_HANDLE)
422 {
423 pth_mutex_acquire(&cond->mutex, FALSE, NULL);
424 pth_cond_notify(&cond->cond, cond->broadcast);
425 cond->isSet = FALSE;
426 pth_mutex_release(&cond->mutex);
427 }
428}
429
430inline BOOL ConditionWait(CONDITION cond, DWORD dwTimeOut)
431{
432 BOOL ret = FALSE;
433
434 if (cond != NULL)
435 {
436 int retcode;
437
438 pth_mutex_acquire(&cond->mutex, FALSE, NULL);
439 if (cond->isSet)
440 {
441 ret = TRUE;
442 if (!cond->broadcast)
443 cond->isSet = FALSE;
444 }
445 else
446 {
447 if (dwTimeOut != INFINITE)
448 {
449 pth_event_t ev;
450
451 ev = pth_event(PTH_EVENT_TIME, pth_timeout(dwTimeOut / 1000, (dwTimeOut % 1000) * 1000));
cd4c8ca3 452 retcode = pth_cond_await(&cond->cond, &cond->mutex, ev);
60414f77
VK
453 pth_event_free(ev, PTH_FREE_ALL);
454 }
455 else
456 {
457 retcode = pth_cond_await(&cond->cond, &cond->mutex, NULL);
458 }
459
460 if (retcode)
461 {
462 if (!cond->broadcast)
463 cond->isSet = FALSE;
464 ret = TRUE;
465 }
466 }
467
468 pth_mutex_release(&cond->mutex);
469 }
470
471 return ret;
472}
473
474inline DWORD GetCurrentProcessId(void)
475{
476 return getpid();
477}
478
479inline THREAD GetCurrentThreadId(void)
480{
481 return pth_self();
482}
483
484#else /* not _WIN32 && not _USE_GNU_PTH */
54481027 485
d16cf8a5 486/****************************************************************************/
9b2bfc05 487/* pthreads */
d16cf8a5
AK
488/****************************************************************************/
489
54481027 490#include <pthread.h>
d16cf8a5
AK
491#include <errno.h>
492#include <sys/time.h>
54481027 493
9b2bfc05 494#if HAVE_PTHREAD_NP_H && !defined(_IPSO)
6cd41ceb
VK
495#include <pthread_np.h>
496#endif
497
a0537937 498#if (HAVE_PTHREAD_MUTEXATTR_SETTYPE || HAVE_PTHREAD_MUTEXATTR_SETKIND_NP) && \
6cd41ceb
VK
499 (HAVE_DECL_PTHREAD_MUTEX_RECURSIVE || \
500 HAVE_DECL_PTHREAD_MUTEX_RECURSIVE_NP || \
501 HAVE_DECL_MUTEX_TYPE_COUNTING_FAST)
a0537937
VK
502
503#define HAVE_RECURSIVE_MUTEXES 1
504
505#if HAVE_DECL_PTHREAD_MUTEX_RECURSIVE
506#define MUTEX_RECURSIVE_FLAG PTHREAD_MUTEX_RECURSIVE
6cd41ceb 507#elif HAVE_DECL_PTHREAD_MUTEX_RECURSIVE_NP
a0537937 508#define MUTEX_RECURSIVE_FLAG PTHREAD_MUTEX_RECURSIVE_NP
6cd41ceb
VK
509#elif HAVE_DECL_MUTEX_TYPE_COUNTING_FAST
510#define MUTEX_RECURSIVE_FLAG MUTEX_TYPE_COUNTING_FAST
511#else
512#error Constant used to declare recursive mutex is not known
a0537937
VK
513#endif
514
515#if HAVE_PTHREAD_MUTEXATTR_SETTYPE
516#define MUTEXATTR_SETTYPE pthread_mutexattr_settype
517#else
518#define MUTEXATTR_SETTYPE pthread_mutexattr_setkind_np
519#endif
520
521#endif
522
54481027
VK
523//
524// Related datatypes and constants
525//
526
7e679c4b 527typedef pthread_t THREAD;
a3c76aba
VK
528struct netxms_mutex_t
529{
530 pthread_mutex_t mutex;
531#ifndef HAVE_RECURSIVE_MUTEXES
532 BOOL isRecursive;
533 pthread_t owner;
534#endif
535};
536typedef netxms_mutex_t * MUTEX;
537struct netxms_condition_t
d16cf8a5
AK
538{
539 pthread_cond_t cond;
540 pthread_mutex_t mutex;
541 BOOL broadcast;
5f743326 542 BOOL isSet;
d16cf8a5 543};
a3c76aba 544typedef struct netxms_condition_t * CONDITION;
54481027 545
449e3da9
VK
546#define INVALID_MUTEX_HANDLE (NULL)
547#define INVALID_CONDITION_HANDLE (NULL)
ccdbbb52 548#define INVALID_THREAD_HANDLE 0
54481027 549
7e679c4b
AK
550#ifndef INFINITE
551# define INFINITE 0
552#endif
54481027 553
ccdbbb52
VK
554typedef void *THREAD_RESULT;
555
556#define THREAD_OK ((void *)0)
557#define THREAD_CALL
558
559
54481027
VK
560//
561// Inline functions
562//
563
dc5bad96
VK
564inline void InitThreadLibrary(void)
565{
566}
567
d16cf8a5 568inline void ThreadSleep(int nSeconds)
54481027 569{
22412a01
VK
570#ifdef _NETWARE
571 sleep(nSeconds);
572#else
d16cf8a5
AK
573 struct timeval tv;
574
575 tv.tv_sec = nSeconds;
576 tv.tv_usec = 0;
577
578 select(1, NULL, NULL, NULL, &tv);
22412a01 579#endif
54481027
VK
580}
581
582inline void ThreadSleepMs(DWORD dwMilliseconds)
583{
642bb2d8
VK
584#if HAVE_NANOSLEEP
585 struct timespec interval, remainder;
586
587 interval.tv_sec = dwMilliseconds / 1000;
588 interval.tv_nsec = (dwMilliseconds % 1000) * 1000000; // milli -> nano
589 nanosleep(&interval, &remainder);
590#else
591 usleep(dwMilliseconds * 1000); // Convert to microseconds
592#endif
54481027
VK
593}
594
f7b2df08 595inline THREAD ThreadCreateEx(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
7e679c4b 596{
f7b2df08 597 THREAD id;
7e679c4b 598
f7b2df08
AK
599 if (stack_size <= 0)
600 {
601 // TODO: Find out minimal stack size
602 stack_size = 1024 * 1024; // 1MB
603 // set stack size to 1mb (it's windows default - and application works,
604 // we need to investigate more on this)
ccdbbb52 605 }
f7b2df08
AK
606 pthread_attr_t attr;
607 pthread_attr_init(&attr);
608 pthread_attr_setstacksize(&attr, stack_size);
609
610 if (pthread_create(&id, &attr, start_address, args) != 0)
611 {
612 id = INVALID_THREAD_HANDLE;
613 }
614
615 return id;
ccdbbb52
VK
616}
617
f7b2df08 618inline BOOL ThreadCreate(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
ccdbbb52 619{
f7b2df08 620 THREAD id = ThreadCreateEx(start_address, stack_size, args);
ccdbbb52 621
f7b2df08
AK
622 if (id != INVALID_THREAD_HANDLE)
623 {
624 pthread_detach(id);
625 return TRUE;
626 }
627
628 return FALSE;
7e679c4b
AK
629}
630
631inline void ThreadExit(void)
632{
521d90e7 633 pthread_exit(NULL);
7e679c4b
AK
634}
635
ccdbbb52
VK
636inline void ThreadJoin(THREAD hThread)
637{
638 if (hThread != INVALID_THREAD_HANDLE)
35a3a09e 639 pthread_join(hThread, NULL);
ccdbbb52
VK
640}
641
54481027
VK
642inline MUTEX MutexCreate(void)
643{
644 MUTEX mutex;
645
a3c76aba 646 mutex = (MUTEX)malloc(sizeof(netxms_mutex_t));
54481027 647 if (mutex != NULL)
8118ecaf 648 pthread_mutex_init(&mutex->mutex, NULL);
a3c76aba
VK
649 return mutex;
650}
651
652inline MUTEX MutexCreateRecursive(void)
653{
654 MUTEX mutex;
655
656 mutex = (MUTEX)malloc(sizeof(netxms_mutex_t));
657 if (mutex != NULL)
658 {
659#ifdef HAVE_RECURSIVE_MUTEXES
660 pthread_mutexattr_t a;
661
662 pthread_mutexattr_init(&a);
a0537937 663 MUTEXATTR_SETTYPE(&a, MUTEX_RECURSIVE_FLAG);
a3c76aba
VK
664 pthread_mutex_init(&mutex->mutex, &a);
665 pthread_mutexattr_destroy(&a);
666#else
667#error FIXME: implement recursive mutexes
668#endif
669 }
54481027
VK
670 return mutex;
671}
672
673inline void MutexDestroy(MUTEX mutex)
674{
a3c76aba
VK
675 if (mutex != NULL)
676 {
677 pthread_mutex_destroy(&mutex->mutex);
54481027
VK
678 free(mutex);
679 }
680}
681
53c17a96 682inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
54481027 683{
d16cf8a5
AK
684 int i;
685 int ret = FALSE;
686
a3c76aba
VK
687 if (mutex != NULL)
688 {
951e884e
AK
689 if (dwTimeOut == INFINITE)
690 {
a3c76aba
VK
691 if (pthread_mutex_lock(&mutex->mutex) == 0)
692 {
d16cf8a5 693 ret = TRUE;
d16cf8a5 694 }
951e884e
AK
695 }
696 else
697 {
a3c76aba
VK
698 for (i = (dwTimeOut / 50) + 1; i > 0; i--)
699 {
700 if (pthread_mutex_trylock(&mutex->mutex) == 0)
8a435919 701 {
951e884e
AK
702 ret = TRUE;
703 break;
704 }
02ed4cf1 705 ThreadSleepMs(50);
951e884e 706 }
d16cf8a5 707 }
7e679c4b 708 }
d16cf8a5 709 return ret;
54481027
VK
710}
711
712inline void MutexUnlock(MUTEX mutex)
713{
8a435919
VK
714 if (mutex != NULL)
715 {
a3c76aba 716 pthread_mutex_unlock(&mutex->mutex);
7e679c4b
AK
717 }
718}
719
d16cf8a5 720inline CONDITION ConditionCreate(BOOL bBroadcast)
7e679c4b
AK
721{
722 CONDITION cond;
723
a3c76aba 724 cond = (CONDITION)malloc(sizeof(struct netxms_condition_t));
8a435919
VK
725 if (cond != NULL)
726 {
d16cf8a5
AK
727 pthread_cond_init(&cond->cond, NULL);
728 pthread_mutex_init(&cond->mutex, NULL);
729 cond->broadcast = bBroadcast;
5f743326 730 cond->isSet = FALSE;
7e679c4b 731 }
d16cf8a5 732
7e679c4b
AK
733 return cond;
734}
735
d16cf8a5 736inline void ConditionDestroy(CONDITION cond)
7e679c4b 737{
5f743326 738 if (cond != INVALID_CONDITION_HANDLE)
d16cf8a5
AK
739 {
740 pthread_cond_destroy(&cond->cond);
741 pthread_mutex_destroy(&cond->mutex);
742 free(cond);
7e679c4b
AK
743 }
744}
745
d16cf8a5 746inline void ConditionSet(CONDITION cond)
7e679c4b 747{
5f743326 748 if (cond != INVALID_CONDITION_HANDLE)
d16cf8a5
AK
749 {
750 pthread_mutex_lock(&cond->mutex);
5f743326 751 cond->isSet = TRUE;
02ed4cf1 752 if (cond->broadcast)
d16cf8a5
AK
753 {
754 pthread_cond_broadcast(&cond->cond);
755 }
756 else
757 {
758 pthread_cond_signal(&cond->cond);
759 }
760 pthread_mutex_unlock(&cond->mutex);
761 }
7e679c4b
AK
762}
763
5f743326
VK
764inline void ConditionReset(CONDITION cond)
765{
766 if (cond != INVALID_CONDITION_HANDLE)
767 {
768 pthread_mutex_lock(&cond->mutex);
769 cond->isSet = FALSE;
770 pthread_mutex_unlock(&cond->mutex);
771 }
772}
773
774inline void ConditionPulse(CONDITION cond)
775{
776 if (cond != INVALID_CONDITION_HANDLE)
777 {
778 pthread_mutex_lock(&cond->mutex);
779 if (cond->broadcast)
780 {
781 pthread_cond_broadcast(&cond->cond);
782 }
783 else
784 {
785 pthread_cond_signal(&cond->cond);
786 }
787 cond->isSet = FALSE;
788 pthread_mutex_unlock(&cond->mutex);
789 }
790}
791
d16cf8a5 792inline BOOL ConditionWait(CONDITION cond, DWORD dwTimeOut)
7e679c4b 793{
d16cf8a5
AK
794 BOOL ret = FALSE;
795
796 if (cond != NULL)
797 {
798 int retcode;
799
800 pthread_mutex_lock(&cond->mutex);
5f743326
VK
801 if (cond->isSet)
802 {
803 ret = TRUE;
804 if (!cond->broadcast)
805 cond->isSet = FALSE;
806 }
807 else
808 {
809 if (dwTimeOut != INFINITE)
810 {
58e7e86f 811#if HAVE_PTHREAD_COND_RELTIMEDWAIT_NP || defined(_NETWARE)
5f743326 812 struct timespec timeout;
696fc54f 813
5f743326
VK
814 timeout.tv_sec = dwTimeOut / 1000;
815 timeout.tv_nsec = (dwTimeOut % 1000) * 1000000;
58e7e86f
VK
816#ifdef _NETWARE
817 retcode = pthread_cond_timedwait(&cond->cond, &cond->mutex, &timeout);
818#else
5f743326 819 retcode = pthread_cond_reltimedwait_np(&cond->cond, &cond->mutex, &timeout);
58e7e86f 820#endif
696fc54f 821#else
5f743326
VK
822 struct timeval now;
823 struct timespec timeout;
d16cf8a5 824
5f743326
VK
825 // note.
826 // mili - 10^-3
827 // micro - 10^-6
828 // nano - 10^-9
ed452de5 829
5f743326
VK
830 // FIXME there should be more accurate way
831 gettimeofday(&now, NULL);
832 timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
1216cc73 833
5f743326
VK
834 now.tv_usec += (dwTimeOut % 1000) * 1000;
835 timeout.tv_sec += now.tv_usec / 1000000;
836 timeout.tv_nsec = (now.tv_usec % 1000000) * 1000;
ed452de5 837
5f743326 838 retcode = pthread_cond_timedwait(&cond->cond, &cond->mutex, &timeout);
696fc54f 839#endif
5f743326
VK
840 }
841 else
842 {
843 retcode = pthread_cond_wait(&cond->cond, &cond->mutex);
844 }
845
846 if (retcode == 0)
847 {
633907a4
VK
848 if (!cond->broadcast)
849 cond->isSet = FALSE;
5f743326
VK
850 ret = TRUE;
851 }
852 }
7e679c4b 853
d16cf8a5 854 pthread_mutex_unlock(&cond->mutex);
7e679c4b 855 }
d16cf8a5
AK
856
857 return ret;
54481027
VK
858}
859
bff234b8
VK
860inline DWORD GetCurrentProcessId(void)
861{
862 return getpid();
863}
864
d8250de7 865inline THREAD GetCurrentThreadId(void)
5e3c403d 866{
05f0165e 867 return pthread_self();
5e3c403d
VK
868}
869
54481027
VK
870#endif /* _WIN32 */
871
df7156b3
VK
872#include <rwlock.h>
873
b71bff93
VK
874#endif /* __cplusplus */
875
54481027 876#endif /* _nms_threads_h_ */