Added per-CPU usage statistics and System.CPU.Count parameter
[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)
188{
5f743326
VK
189 SetEvent(hCond);
190}
191
192inline void ConditionReset(CONDITION hCond)
193{
194 ResetEvent(hCond);
195}
196
197inline void ConditionPulse(CONDITION hCond)
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
ccdbbb52 595inline BOOL ThreadCreate(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
7e679c4b
AK
596{
597 THREAD id;
598
ccdbbb52 599 if (pthread_create(&id, NULL, start_address, args) == 0)
d1fbf6ba
VK
600 {
601 pthread_detach(id);
ccdbbb52
VK
602 return TRUE;
603 }
604 else
605 {
606 return FALSE;
607 }
608}
609
610inline THREAD ThreadCreateEx(THREAD_RESULT (THREAD_CALL *start_address )(void *), int stack_size, void *args)
611{
35a3a09e 612 THREAD id;
ccdbbb52 613
35a3a09e 614 if (pthread_create(&id, NULL, start_address, args) == 0)
ccdbbb52 615 {
35a3a09e
VK
616 return id;
617 }
d1fbf6ba
VK
618 else
619 {
35a3a09e
VK
620 return INVALID_THREAD_HANDLE;
621 }
7e679c4b
AK
622}
623
624inline void ThreadExit(void)
625{
521d90e7 626 pthread_exit(NULL);
7e679c4b
AK
627}
628
ccdbbb52
VK
629inline void ThreadJoin(THREAD hThread)
630{
631 if (hThread != INVALID_THREAD_HANDLE)
35a3a09e 632 pthread_join(hThread, NULL);
ccdbbb52
VK
633}
634
54481027
VK
635inline MUTEX MutexCreate(void)
636{
637 MUTEX mutex;
638
a3c76aba 639 mutex = (MUTEX)malloc(sizeof(netxms_mutex_t));
54481027 640 if (mutex != NULL)
8118ecaf 641 pthread_mutex_init(&mutex->mutex, NULL);
a3c76aba
VK
642 return mutex;
643}
644
645inline MUTEX MutexCreateRecursive(void)
646{
647 MUTEX mutex;
648
649 mutex = (MUTEX)malloc(sizeof(netxms_mutex_t));
650 if (mutex != NULL)
651 {
652#ifdef HAVE_RECURSIVE_MUTEXES
653 pthread_mutexattr_t a;
654
655 pthread_mutexattr_init(&a);
a0537937 656 MUTEXATTR_SETTYPE(&a, MUTEX_RECURSIVE_FLAG);
a3c76aba
VK
657 pthread_mutex_init(&mutex->mutex, &a);
658 pthread_mutexattr_destroy(&a);
659#else
660#error FIXME: implement recursive mutexes
661#endif
662 }
54481027
VK
663 return mutex;
664}
665
666inline void MutexDestroy(MUTEX mutex)
667{
a3c76aba
VK
668 if (mutex != NULL)
669 {
670 pthread_mutex_destroy(&mutex->mutex);
54481027
VK
671 free(mutex);
672 }
673}
674
53c17a96 675inline BOOL MutexLock(MUTEX mutex, DWORD dwTimeOut)
54481027 676{
d16cf8a5
AK
677 int i;
678 int ret = FALSE;
679
a3c76aba
VK
680 if (mutex != NULL)
681 {
951e884e
AK
682 if (dwTimeOut == INFINITE)
683 {
a3c76aba
VK
684 if (pthread_mutex_lock(&mutex->mutex) == 0)
685 {
d16cf8a5 686 ret = TRUE;
d16cf8a5 687 }
951e884e
AK
688 }
689 else
690 {
a3c76aba
VK
691 for (i = (dwTimeOut / 50) + 1; i > 0; i--)
692 {
693 if (pthread_mutex_trylock(&mutex->mutex) == 0)
8a435919 694 {
951e884e
AK
695 ret = TRUE;
696 break;
697 }
02ed4cf1 698 ThreadSleepMs(50);
951e884e 699 }
d16cf8a5 700 }
7e679c4b 701 }
d16cf8a5 702 return ret;
54481027
VK
703}
704
705inline void MutexUnlock(MUTEX mutex)
706{
8a435919
VK
707 if (mutex != NULL)
708 {
a3c76aba 709 pthread_mutex_unlock(&mutex->mutex);
7e679c4b
AK
710 }
711}
712
d16cf8a5 713inline CONDITION ConditionCreate(BOOL bBroadcast)
7e679c4b
AK
714{
715 CONDITION cond;
716
a3c76aba 717 cond = (CONDITION)malloc(sizeof(struct netxms_condition_t));
8a435919
VK
718 if (cond != NULL)
719 {
d16cf8a5
AK
720 pthread_cond_init(&cond->cond, NULL);
721 pthread_mutex_init(&cond->mutex, NULL);
722 cond->broadcast = bBroadcast;
5f743326 723 cond->isSet = FALSE;
7e679c4b 724 }
d16cf8a5 725
7e679c4b
AK
726 return cond;
727}
728
d16cf8a5 729inline void ConditionDestroy(CONDITION cond)
7e679c4b 730{
5f743326 731 if (cond != INVALID_CONDITION_HANDLE)
d16cf8a5
AK
732 {
733 pthread_cond_destroy(&cond->cond);
734 pthread_mutex_destroy(&cond->mutex);
735 free(cond);
7e679c4b
AK
736 }
737}
738
d16cf8a5 739inline void ConditionSet(CONDITION cond)
7e679c4b 740{
5f743326 741 if (cond != INVALID_CONDITION_HANDLE)
d16cf8a5
AK
742 {
743 pthread_mutex_lock(&cond->mutex);
5f743326 744 cond->isSet = TRUE;
02ed4cf1 745 if (cond->broadcast)
d16cf8a5
AK
746 {
747 pthread_cond_broadcast(&cond->cond);
748 }
749 else
750 {
751 pthread_cond_signal(&cond->cond);
752 }
753 pthread_mutex_unlock(&cond->mutex);
754 }
7e679c4b
AK
755}
756
5f743326
VK
757inline void ConditionReset(CONDITION cond)
758{
759 if (cond != INVALID_CONDITION_HANDLE)
760 {
761 pthread_mutex_lock(&cond->mutex);
762 cond->isSet = FALSE;
763 pthread_mutex_unlock(&cond->mutex);
764 }
765}
766
767inline void ConditionPulse(CONDITION cond)
768{
769 if (cond != INVALID_CONDITION_HANDLE)
770 {
771 pthread_mutex_lock(&cond->mutex);
772 if (cond->broadcast)
773 {
774 pthread_cond_broadcast(&cond->cond);
775 }
776 else
777 {
778 pthread_cond_signal(&cond->cond);
779 }
780 cond->isSet = FALSE;
781 pthread_mutex_unlock(&cond->mutex);
782 }
783}
784
d16cf8a5 785inline BOOL ConditionWait(CONDITION cond, DWORD dwTimeOut)
7e679c4b 786{
d16cf8a5
AK
787 BOOL ret = FALSE;
788
789 if (cond != NULL)
790 {
791 int retcode;
792
793 pthread_mutex_lock(&cond->mutex);
5f743326
VK
794 if (cond->isSet)
795 {
796 ret = TRUE;
797 if (!cond->broadcast)
798 cond->isSet = FALSE;
799 }
800 else
801 {
802 if (dwTimeOut != INFINITE)
803 {
58e7e86f 804#if HAVE_PTHREAD_COND_RELTIMEDWAIT_NP || defined(_NETWARE)
5f743326 805 struct timespec timeout;
696fc54f 806
5f743326
VK
807 timeout.tv_sec = dwTimeOut / 1000;
808 timeout.tv_nsec = (dwTimeOut % 1000) * 1000000;
58e7e86f
VK
809#ifdef _NETWARE
810 retcode = pthread_cond_timedwait(&cond->cond, &cond->mutex, &timeout);
811#else
5f743326 812 retcode = pthread_cond_reltimedwait_np(&cond->cond, &cond->mutex, &timeout);
58e7e86f 813#endif
696fc54f 814#else
5f743326
VK
815 struct timeval now;
816 struct timespec timeout;
d16cf8a5 817
5f743326
VK
818 // note.
819 // mili - 10^-3
820 // micro - 10^-6
821 // nano - 10^-9
ed452de5 822
5f743326
VK
823 // FIXME there should be more accurate way
824 gettimeofday(&now, NULL);
825 timeout.tv_sec = now.tv_sec + (dwTimeOut / 1000);
1216cc73 826
5f743326
VK
827 now.tv_usec += (dwTimeOut % 1000) * 1000;
828 timeout.tv_sec += now.tv_usec / 1000000;
829 timeout.tv_nsec = (now.tv_usec % 1000000) * 1000;
ed452de5 830
5f743326 831 retcode = pthread_cond_timedwait(&cond->cond, &cond->mutex, &timeout);
696fc54f 832#endif
5f743326
VK
833 }
834 else
835 {
836 retcode = pthread_cond_wait(&cond->cond, &cond->mutex);
837 }
838
839 if (retcode == 0)
840 {
633907a4
VK
841 if (!cond->broadcast)
842 cond->isSet = FALSE;
5f743326
VK
843 ret = TRUE;
844 }
845 }
7e679c4b 846
d16cf8a5 847 pthread_mutex_unlock(&cond->mutex);
7e679c4b 848 }
d16cf8a5
AK
849
850 return ret;
54481027
VK
851}
852
bff234b8
VK
853inline DWORD GetCurrentProcessId(void)
854{
855 return getpid();
856}
857
d8250de7 858inline THREAD GetCurrentThreadId(void)
5e3c403d 859{
05f0165e 860 return pthread_self();
5e3c403d
VK
861}
862
54481027
VK
863#endif /* _WIN32 */
864
df7156b3
VK
865#include <rwlock.h>
866
b71bff93
VK
867#endif /* __cplusplus */
868
54481027 869#endif /* _nms_threads_h_ */