Cleanup the debug code.
[npth.git] / src / npth.c
1 /* npth.c - a lightweight implementation of pth over pthread.
2    Copyright (C) 2011 g10 Code GmbH
3
4    This file is part of NPTH.
5
6    NPTH is free software; you can redistribute it and/or modify it
7    under the terms of either
8
9    - the GNU Lesser General Public License as published by the Free
10    Software Foundation; either version 3 of the License, or (at
11    your option) any later version.
12
13    or
14
15    - the GNU General Public License as published by the Free
16    Software Foundation; either version 2 of the License, or (at
17    your option) any later version.
18
19    or both in parallel, as here.
20
21    NPTH is distributed in the hope that it will be useful, but WITHOUT
22    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
24    License for more details.
25
26    You should have received a copies of the GNU General Public License
27    and the GNU Lesser General Public License along with this program;
28    if not, see <http://www.gnu.org/licenses/>.  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <stdlib.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <pthread.h>
38 #include <semaphore.h>
39 #ifdef HAVE_UNISTD_H
40 # include <unistd.h>
41 #endif
42
43 #include "npth.h"
44
45
46 #include <stdio.h>
47
48 #define DEBUG_CALLS 1
49
50 #if __STDC_VERSION__ < 199901L
51 # if __GNUC__ >= 2
52 #  define __func__ __FUNCTION__
53 # else
54 #  define __func__ "<unknown>"
55 # endif
56 #endif
57
58 #ifdef TEST
59 # define _npth_debug(x, ...) printf(__VA_ARGS__)
60 #else
61 # undef  DEBUG_CALLS
62 # define DEBUG_CALLS 0
63 # undef _npth_debug
64 # define _npth_debug(x, ...)
65 #endif
66
67 /* The global lock that excludes all threads but one.  This is a
68    semaphore, because these can be safely used in a library even if
69    the application or other libraries call fork(), including from a
70    signal handler.  sem_post is async-signal-safe.  (The reason a
71    semaphore is safe and a mutex is not safe is that a mutex has an
72    owner, while a semaphore does not.)  */
73 static sem_t sceptre;
74
75 static pthread_t main_thread;
76
77 /* Systems that don't have pthread_mutex_timedlock get a busy wait
78    implementation that probes the lock every BUSY_WAIT_INTERVAL
79    milliseconds.  */
80 #define BUSY_WAIT_INTERVAL 200
81
82 typedef int (*trylock_func_t) (void *);
83
84 static int
85 busy_wait_for (trylock_func_t trylock, void *lock,
86                const struct timespec *abstime)
87 {
88   int err;
89
90   /* This is not great, but better than nothing.  Only works for locks
91      which are mostly uncontested.  Provides absolutely no fairness at
92      all.  Creates many wake-ups.  */
93   while (1)
94     {
95       struct timespec ts;
96       err = npth_clock_gettime (&ts);
97       if (err < 0)
98         {
99           /* Just for safety make sure we return some error.  */
100           err = errno ? errno : EINVAL;
101           break;
102         }
103
104       if (! npth_timercmp (abstime, &ts, <))
105         {
106           err = ETIMEDOUT;
107           break;
108         }
109
110       err = (*trylock) (lock);
111       if (err != EBUSY)
112         break;
113
114       /* Try again after waiting a bit.  We could calculate the
115          maximum wait time from ts and abstime, but we don't
116          bother, as our granularity is pretty fine.  */
117       usleep (BUSY_WAIT_INTERVAL * 1000);
118     }
119
120   return err;
121 }
122
123 \f
124 static void
125 enter_npth (const char *function)
126 {
127   int res;
128
129   if (DEBUG_CALLS)
130     _npth_debug (DEBUG_CALLS, "enter_npth (%s)\n",
131                  function ? function : "unknown");
132   res = sem_post (&sceptre);
133   assert (res == 0);
134 }
135
136
137 static void
138 leave_npth (const char *function)
139 {
140   int res;
141
142   do {
143     res = sem_wait (&sceptre);
144   } while (res < 0 && errno == EINTR);
145
146   assert (!res);
147
148   if (DEBUG_CALLS)
149     _npth_debug (DEBUG_CALLS, "leave_npth (%s)\n",
150                  function ? function : "");
151 }
152
153 #define ENTER() enter_npth(__func__)
154 #define LEAVE() leave_npth(__func__)
155
156
157 int
158 npth_init (void)
159 {
160   int res;
161
162   main_thread = pthread_self();
163
164   /* The semaphore is not shared and binary.  */
165   res = sem_init(&sceptre, 0, 1);
166   if (res < 0)
167     {
168       /* POSIX.1-2001 defines the semaphore interface but does not
169          specify the return value for success.  Thus we better bail
170          out on error only on a POSIX.1-2008 system.  */
171 #if _POSIX_C_SOURCE >= 200809L
172       return errno;
173 #endif
174     }
175
176   LEAVE();
177   return 0;
178 }
179
180
181 int
182 npth_getname_np (npth_t target_thread, char *buf, size_t buflen)
183 {
184 #ifdef HAVE_PTHREAD_GETNAME_NP
185   return pthread_getname_np (target_thread, buf, buflen);
186 #else
187   (void)target_thread;
188   (void)buf;
189   (void)buflen;
190   return ENOSYS;
191 #endif
192 }
193
194
195 int
196 npth_setname_np (npth_t target_thread, const char *name)
197 {
198 #ifdef HAVE_PTHREAD_SERNAME_NP
199   return pthread_settname_np (target_thread, name);
200 #else
201   (void)target_thread;
202   (void)name;
203   return ENOSYS;
204 #endif
205 }
206
207
208 \f
209 struct startup_s
210 {
211   void *(*start_routine) (void *);
212   void *arg;
213 };
214
215
216 static void *
217 thread_start (void *startup_arg)
218 {
219   struct startup_s *startup = startup_arg;
220   void *(*start_routine) (void *);
221   void *arg;
222   void *result;
223
224   start_routine = startup->start_routine;
225   arg = startup->arg;
226   free (startup);
227
228   LEAVE();
229   result = (*start_routine) (arg);
230   /* Note: instead of returning here, we might end up in
231      npth_exit() instead.  */
232   ENTER();
233
234   return result;
235 }
236
237
238 int
239 npth_create (npth_t *thread, const npth_attr_t *attr,
240              void *(*start_routine) (void *), void *arg)
241 {
242   int err;
243   struct startup_s *startup;
244
245   startup = malloc (sizeof (*startup));
246   if (!startup)
247     return errno;
248
249   startup->start_routine = start_routine;
250   startup->arg = arg;
251   err = pthread_create (thread, attr, thread_start, startup);
252   if (err)
253     {
254       free (startup);
255       return err;
256     }
257
258   /* Memory is released in thread_start.  */
259   return 0;
260 }
261
262
263 int
264 npth_join (npth_t thread, void **retval)
265 {
266   int err;
267
268 #ifdef HAVE_PTHREAD_TRYJOIN_NP
269   /* No need to allow competing threads to enter when we can get the
270      lock immediately.  pthread_tryjoin_np is a GNU extension.  */
271   err = pthread_tryjoin_np (thread, retval);
272   if (err != EBUSY)
273     return err;
274 #endif /*HAVE_PTHREAD_TRYJOIN_NP*/
275
276   ENTER();
277   err = pthread_join (thread, retval);
278   LEAVE();
279   return err;
280 }
281
282
283 void
284 npth_exit (void *retval)
285 {
286   ENTER();
287   pthread_exit (retval);
288   /* Never reached.  But just in case pthread_exit does return... */
289   LEAVE();
290 }
291
292 \f
293 int
294 npth_mutex_lock (npth_mutex_t *mutex)
295 {
296   int err;
297
298   /* No need to allow competing threads to enter when we can get the
299      lock immediately.  */
300   err = pthread_mutex_trylock (mutex);
301   if (err != EBUSY)
302     return err;
303
304   ENTER();
305   err = pthread_mutex_lock (mutex);
306   LEAVE();
307   return err;
308 }
309
310
311 int
312 npth_mutex_timedlock (npth_mutex_t *mutex, const struct timespec *abstime)
313 {
314   int err;
315
316   /* No need to allow competing threads to enter when we can get the
317      lock immediately.  */
318   err = pthread_mutex_trylock (mutex);
319   if (err != EBUSY)
320     return err;
321
322   ENTER();
323 #if HAVE_PTHREAD_MUTEX_TIMEDLOCK
324   err = pthread_mutex_timedlock (mutex, abstime);
325 #else
326   err = busy_wait_for ((trylock_func_t) pthread_mutex_trylock, mutex, abstime);
327 #endif
328   LEAVE();
329   return err;
330 }
331
332
333 #ifndef _NPTH_NO_RWLOCK
334 int
335 npth_rwlock_rdlock (npth_rwlock_t *rwlock)
336 {
337   int err;
338
339 #ifdef HAVE_PTHREAD_RWLOCK_TRYRDLOCK
340   /* No need to allow competing threads to enter when we can get the
341      lock immediately.  */
342   err = pthread_rwlock_tryrdlock (rwlock);
343   if (err != EBUSY)
344     return err;
345 #endif
346
347   ENTER();
348   err = pthread_rwlock_rdlock (rwlock);
349   LEAVE();
350   return err;
351 }
352
353
354 int
355 npth_rwlock_timedrdlock (npth_rwlock_t *rwlock, const struct timespec *abstime)
356 {
357   int err;
358
359 #ifdef HAVE_PTHREAD_RWLOCK_TRYRDLOCK
360   /* No need to allow competing threads to enter when we can get the
361      lock immediately.  */
362   err = pthread_rwlock_tryrdlock (rwlock);
363   if (err != EBUSY)
364     return err;
365 #endif
366
367   ENTER();
368 #if HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK
369   err = pthread_rwlock_timedrdlock (rwlock, abstime);
370 #else
371   err = busy_wait_for ((trylock_func_t) pthread_rwlock_tryrdlock, rwlock,
372                        abstime);
373 #endif
374   LEAVE();
375   return err;
376 }
377
378
379 int
380 npth_rwlock_wrlock (npth_rwlock_t *rwlock)
381 {
382   int err;
383
384 #ifdef HAVE_PTHREAD_RWLOCK_TRYWRLOCK
385   /* No need to allow competing threads to enter when we can get the
386      lock immediately.  */
387   err = pthread_rwlock_trywrlock (rwlock);
388   if (err != EBUSY)
389     return err;
390 #endif
391
392   ENTER();
393   err = pthread_rwlock_wrlock (rwlock);
394   LEAVE();
395   return err;
396 }
397
398
399 int
400 npth_rwlock_timedwrlock (npth_rwlock_t *rwlock, const struct timespec *abstime)
401 {
402   int err;
403
404 #ifdef HAVE_PTHREAD_RWLOCK_TRYWRLOCK
405   /* No need to allow competing threads to enter when we can get the
406      lock immediately.  */
407   err = pthread_rwlock_trywrlock (rwlock);
408   if (err != EBUSY)
409     return err;
410 #endif
411
412   ENTER();
413 #if HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
414   err = pthread_rwlock_timedwrlock (rwlock, abstime);
415 #elif HAVE_PTHREAD_RWLOCK_TRYRDLOCK
416   err = busy_wait_for ((trylock_func_t) pthread_rwlock_trywrlock, rwlock,
417                        abstime);
418 #endif
419   LEAVE();
420   return err;
421 }
422 #endif
423
424
425 int
426 npth_cond_wait (npth_cond_t *cond, npth_mutex_t *mutex)
427 {
428   int err;
429
430   ENTER();
431   err = pthread_cond_wait (cond, mutex);
432   LEAVE();
433   return err;
434 }
435
436
437 int
438 npth_cond_timedwait (npth_cond_t *cond, npth_mutex_t *mutex,
439                      const struct timespec *abstime)
440 {
441   int err;
442
443   ENTER();
444   err = pthread_cond_timedwait (cond, mutex, abstime);
445   LEAVE();
446   return err;
447 }
448
449 \f
450 /* Standard POSIX Replacement API */
451
452 int
453 npth_usleep(unsigned int usec)
454 {
455   int res;
456
457   ENTER();
458   res = usleep(usec);
459   LEAVE();
460   return res;
461 }
462
463
464 unsigned int
465 npth_sleep(unsigned int sec)
466 {
467   unsigned res;
468
469   ENTER();
470   res = sleep(sec);
471   LEAVE();
472   return res;
473 }
474
475
476 int
477 npth_system(const char *cmd)
478 {
479   int res;
480
481   ENTER();
482   res = system(cmd);
483   LEAVE();
484   return res;
485 }
486
487
488 pid_t
489 npth_waitpid(pid_t pid, int *status, int options)
490 {
491   pid_t res;
492
493   ENTER();
494   res = waitpid(pid,status, options);
495   LEAVE();
496   return res;
497 }
498
499
500 int
501 npth_connect(int s, const struct sockaddr *addr, socklen_t addrlen)
502 {
503   int res;
504
505   ENTER();
506   res = connect(s, addr, addrlen);
507   LEAVE();
508   return res;
509 }
510
511
512 int
513 npth_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
514 {
515   int res;
516
517   ENTER();
518   res = accept(s, addr, addrlen);
519   LEAVE();
520   return res;
521 }
522
523
524 int
525 npth_select(int nfd, fd_set *rfds, fd_set *wfds, fd_set *efds,
526             struct timeval *timeout)
527 {
528   int res;
529
530   ENTER();
531   res = select(nfd, rfds, wfds, efds, timeout);
532   LEAVE();
533   return res;
534 }
535
536
537 int
538 npth_pselect(int nfd, fd_set *rfds, fd_set *wfds, fd_set *efds,
539              const struct timespec *timeout, const sigset_t *sigmask)
540 {
541   int res;
542
543   ENTER();
544   res = pselect(nfd, rfds, wfds, efds, timeout, sigmask);
545   LEAVE();
546   return res;
547 }
548
549
550 ssize_t
551 npth_read(int fd, void *buf, size_t nbytes)
552 {
553   ssize_t res;
554
555   ENTER();
556   res = read(fd, buf, nbytes);
557   LEAVE();
558   return res;
559 }
560
561
562 ssize_t
563 npth_write(int fd, const void *buf, size_t nbytes)
564 {
565   ssize_t res;
566
567   ENTER();
568   res = write(fd, buf, nbytes);
569   LEAVE();
570   return res;
571 }
572
573
574 int
575 npth_recvmsg (int fd, struct msghdr *msg, int flags)
576 {
577   int res;
578
579   ENTER();
580   res = recvmsg (fd, msg, flags);
581   LEAVE();
582   return res;
583 }
584
585
586 int
587 npth_sendmsg (int fd, const struct msghdr *msg, int flags)
588 {
589   int res;
590
591   ENTER();
592   res = sendmsg (fd, msg, flags);
593   LEAVE();
594   return res;
595 }
596
597
598 void
599 npth_unprotect (void)
600 {
601   ENTER();
602 }
603
604
605 void
606 npth_protect (void)
607 {
608   LEAVE();
609 }
610
611
612 int
613 npth_clock_gettime (struct timespec *ts)
614 {
615 #if HAVE_CLOCK_GETTIME
616   return clock_gettime (CLOCK_REALTIME, ts);
617 #else
618   /* FIXME: fall back on time() with seconds resolution.  */
619 # error clock_gettime not available - please provide a fallback.
620 #endif
621 }