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