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