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