7ff23ed112ffb3992a8a2c43fa12a5d98fa096e0
[yaz-moved-to-github.git] / src / mutex.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2010 Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file mutex.c
8  * \brief Implements MUTEX functions
9  *
10  */
11 #if HAVE_CONFIG_H
12 #include <config.h>
13 #endif
14
15 #include <assert.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <stddef.h>
20 #include <yaz/xmalloc.h>
21 #include <yaz/nmem.h>
22 #include <yaz/log.h>
23 #include <yaz/mutex.h>
24
25 #ifdef WIN32
26 #include <windows.h>
27 #endif
28
29 #if HAVE_SYS_TIME_H
30 #include <sys/time.h>
31 #endif
32
33 #if YAZ_POSIX_THREADS
34 #include <pthread.h>
35 #endif
36
37 struct yaz_mutex {
38 #ifdef WIN32
39     CRITICAL_SECTION handle;
40 #elif YAZ_POSIX_THREADS
41     pthread_mutex_t handle;
42 #endif
43     char *name;
44     int log_level;
45 };
46
47 struct yaz_cond {
48 #ifdef WIN32
49
50 #elif YAZ_POSIX_THREADS
51     pthread_cond_t cond;
52 #endif
53 };
54
55 void yaz_mutex_create(YAZ_MUTEX *p)
56 {
57     if (!*p)
58     {
59         *p = (YAZ_MUTEX) malloc(sizeof(**p));
60 #ifdef WIN32
61         InitializeCriticalSection(&(*p)->handle);
62 #elif YAZ_POSIX_THREADS
63         pthread_mutex_init(&(*p)->handle, 0);
64 #endif
65         (*p)->name = 0;
66         (*p)->log_level = 0;
67     }
68 }
69
70 void yaz_mutex_set_name(YAZ_MUTEX p, int log_level, const char *name)
71 {
72     if (p->name)
73         free(p->name);
74     p->name = 0;
75     p->log_level = 0;
76     if (name)
77     {
78         p->name = strdup(name);
79         p->log_level = log_level;
80     }
81 }
82
83 void yaz_mutex_enter(YAZ_MUTEX p)
84 {
85     if (p)
86     {
87 #ifdef WIN32
88         EnterCriticalSection(&p->handle);
89 #elif YAZ_POSIX_THREADS
90         int r = 1; /* signal : not locked (yet) */
91         
92         if (p->log_level)
93         {   /* debugging */
94             r = pthread_mutex_trylock(&p->handle);
95             if (r)
96             {
97 #if HAVE_SYS_TIME_H
98                 long long d;
99                 struct timeval tv1, tv2;
100                 gettimeofday(&tv1, 0);
101 #endif
102                 yaz_log(p->log_level,
103                         "yaz_mutex_enter: %p tid=%p name=%s waiting",
104                         p, (void *) pthread_self(), p->name);
105 #if HAVE_SYS_TIME_H
106                 r = pthread_mutex_lock(&p->handle);
107                 gettimeofday(&tv2, 0);
108                 d = 1000000LL * ((long long) tv2.tv_sec - tv1.tv_sec) +
109                     tv2.tv_usec - tv1.tv_usec;
110                 yaz_log(p->log_level, "yaz_mutex_enter: %p tid=%p name=%s "
111                         "lock delay %lld",
112                         p, (void *) pthread_self(), p->name, d);
113 #endif
114             }
115             else
116             {
117                 yaz_log(p->log_level, "yaz_mutex_enter: %p tid=%p name=%s lock",
118                         p, (void *) pthread_self(), p->name);
119             }
120         }
121         if (r)
122         {
123             r = pthread_mutex_lock(&p->handle);
124             if (p->log_level)
125             {
126                 yaz_log(p->log_level, "yaz_mutex_enter: %p tid=%p name=%s lock",
127                         p, (void *) pthread_self(), p->name);
128             }
129         }
130 #endif
131     }
132 }
133
134 void yaz_mutex_leave(YAZ_MUTEX p)
135 {
136     if (p)
137     {
138 #ifdef WIN32
139         LeaveCriticalSection(&p->handle);
140 #elif YAZ_POSIX_THREADS
141         pthread_mutex_unlock(&p->handle);
142         if (p->log_level)
143         {
144             yaz_log(p->log_level,
145                     "yaz_mutex_leave: %p tid=%p name=%s unlock",
146                     p, (void *) pthread_self(), p->name);
147         }
148 #endif
149     }
150 }
151
152 void yaz_mutex_destroy(YAZ_MUTEX *p)
153 {
154     if (*p)
155     {
156 #ifdef WIN32
157         DeleteCriticalSection(&(*p)->handle);
158 #elif YAZ_POSIX_THREADS
159         pthread_mutex_destroy(&(*p)->handle);
160 #endif
161         if ((*p)->name)
162             free((*p)->name);
163         free(*p);
164         *p = 0;
165     }
166 }
167
168
169 void yaz_cond_create(YAZ_COND *p)
170 {
171     *p = (YAZ_COND) malloc(sizeof(**p));
172 #ifdef WIN32
173 #elif YAZ_POSIX_THREADS
174     pthread_cond_init(&(*p)->cond, 0);
175 #endif
176 }
177
178 void yaz_cond_destroy(YAZ_COND *p)
179 {
180     if (*p)
181     {
182 #ifdef WIN32
183 #elif YAZ_POSIX_THREADS
184         pthread_cond_destroy(&(*p)->cond);
185 #endif
186         free(*p);
187         *p = 0;
188     }
189 }
190
191 int yaz_cond_wait(YAZ_COND p, YAZ_MUTEX m, const struct timespec *abstime)
192 {
193 #ifdef WIN32
194     return -1;
195 #elif YAZ_POSIX_THREADS
196     if (abstime)
197         return pthread_cond_timedwait(&p->cond, &m->handle, abstime);
198     else
199         return pthread_cond_wait(&p->cond, &m->handle);
200 #else
201     return -1;
202 #endif
203 }
204
205 int yaz_cond_signal(YAZ_COND p)
206 {
207 #ifdef WIN32
208     return -1;
209 #elif YAZ_POSIX_THREADS
210     return pthread_cond_signal(&p->cond);
211 #else
212     return -1;
213 #endif
214 }
215
216 int yaz_cond_broadcast(YAZ_COND p)
217 {
218 #ifdef WIN32
219     return -1;
220 #elif YAZ_POSIX_THREADS
221     return pthread_cond_broadcast(&p->cond);
222 #else
223     return -1;
224 #endif
225 }
226
227 /*
228  * Local variables:
229  * c-basic-offset: 4
230  * c-file-style: "Stroustrup"
231  * indent-tabs-mode: nil
232  * End:
233  * vim: shiftwidth=4 tabstop=8 expandtab
234  */
235