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