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