1 /*
2   LibRCC - module responsible for thread synchronization
3 
4   Copyright (C) 2005-2008 Suren A. Chilingaryan <csa@dside.dyndns.org>
5 
6   This library is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License version 2.1 or later
8   as published by the Free Software Foundation.
9 
10   This library is distributed in the hope that it will be useful, but WITHOUT
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
13   for more details.
14 
15   You should have received a copy of the GNU Lesser General Public License
16   along with this program; if not, write to the Free Software Foundation, Inc.,
17   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include <stdlib.h>
21 #include <time.h>
22 
23 #ifdef HAVE_UNISTD_H
24 # include <unistd.h>
25 #endif /* HAVE_UNISTD_H */
26 
27 #ifdef WIN32
28 # include <windows.h>
29 #endif /* WIN32 */
30 
31 #include "rccmutex.h"
32 
33 
34 #define RCC_MUTEX_SLEEP 500
35 
rccMutexCreate()36 rcc_mutex rccMutexCreate() {
37     rcc_mutex mutex;
38 
39     mutex = (rcc_mutex)malloc(sizeof(rcc_mutex_s));
40     if (mutex) {
41 #ifdef HAVE_PTHREAD
42 	pthread_mutex_init(&mutex->mutex, NULL);
43 #else
44 	mutex->mutex = 0;
45 #endif /* HAVE_PTHREAD */
46     }
47     return mutex;
48 }
49 
rccMutexFree(rcc_mutex mutex)50 void rccMutexFree(rcc_mutex mutex) {
51     if (mutex) {
52 #ifdef HAVE_PTHREAD
53 	pthread_mutex_destroy(&mutex->mutex);
54 #endif /* HAVE_PTHREAD */
55 	free(mutex);
56     }
57 }
58 
rccMutexLock(rcc_mutex mutex)59 int rccMutexLock(rcc_mutex mutex) {
60 #ifndef HAVE_PTHREAD
61 # ifdef HAVE_NANOSLEEP
62     struct timespec ts;
63 # endif /* HAVE_NANOSLEEP */
64 #endif /* !HAVE_PTHREAD */
65 
66     if (!mutex) return -1;
67 
68 #ifdef HAVE_PTHREAD
69     return pthread_mutex_lock(&mutex->mutex);
70 #else
71     while (mutex->mutex) {
72 # if defined(HAVE_NANOSLEEP)
73 	    ts.tv_sec = RCC_MUTEX_SLEEP / 1000000;
74 	    ts.tv_nsec = (RCC_MUTEX_SLEEP % 1000000)*1000;
75 	    nanosleep(&ts, NULL);
76 # elif defined (HAVE_USLEEP)
77 	    usleep(RCC_MUTEX_SLEEP);
78 # elif defined (WIN32)
79 	    Sleep((RCC_MUTEX_SLEEP<1000)?1:RCC_MUTEX_SLEEP/1000);
80 # endif /* HAVE_NANOSLEEP */
81     }
82     mutex->mutex = 1;
83 
84     return 0;
85 #endif /* HAVE_PTHREAD */
86 }
87 
rccMutexTryLock(rcc_mutex mutex)88 int rccMutexTryLock(rcc_mutex mutex) {
89     if (!mutex) return -1;
90 
91 #ifdef HAVE_PTHREAD
92     return pthread_mutex_trylock(&mutex->mutex);
93 #else
94     if (mutex->mutex) return -1;
95     mutex->mutex = 1;
96     return 0;
97 #endif /* HAVE_PTHREAD */
98 }
99 
rccMutexUnLock(rcc_mutex mutex)100 void rccMutexUnLock(rcc_mutex mutex) {
101     if (!mutex) return;
102 #ifdef HAVE_PTHREAD
103     pthread_mutex_unlock(&mutex->mutex);
104 #else
105     mutex->mutex = 0;
106 #endif /* HAVE_PTHREAD */
107 }
108 
109 
110