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