f25f1d26d21beec974b5eee56cbcfc52f1e812c7
[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
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * nPth is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
14  * the GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this program; if not, see <https://www.gnu.org/licenses/>.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <errno.h>
29 #include <pthread.h>
30 #include <fcntl.h>
31 #include <sys/stat.h>
32 #ifdef HAVE_LIB_DISPATCH
33 # include <dispatch/dispatch.h>
34 typedef dispatch_semaphore_t sem_t;
35
36 /* This glue code is for macOS which does not have full implementation
37    of POSIX semaphore.  On macOS, using semaphore in Grand Central
38    Dispatch library is better than using the partial implementation of
39    POSIX semaphore where sem_init doesn't work well.
40  */
41
42 static int
43 sem_init (sem_t *sem, int is_shared, unsigned int value)
44 {
45   (void)is_shared;
46   if ((*sem = dispatch_semaphore_create (value)) == NULL)
47     return -1;
48   else
49     return 0;
50 }
51
52 static int
53 sem_post (sem_t *sem)
54 {
55   dispatch_semaphore_signal (*sem);
56   return 0;
57 }
58
59 static int
60 sem_wait (sem_t *sem)
61 {
62   dispatch_semaphore_wait (*sem, DISPATCH_TIME_FOREVER);
63   return 0;
64 }
65 #else
66 # include <semaphore.h>
67 #endif
68 #ifdef HAVE_UNISTD_H
69 # include <unistd.h>
70 #endif
71 #ifndef HAVE_PSELECT
72 # include <signal.h>
73 #endif
74
75 #include "npth.h"
76
77
78 /* The global lock that excludes all threads but one.  This is a
79    semaphore, because these can be safely used in a library even if
80    the application or other libraries call fork(), including from a
81    signal handler.  sem_post is async-signal-safe.  (The reason a
82    semaphore is safe and a mutex is not safe is that a mutex has an
83    owner, while a semaphore does not.)  We init sceptre to a static
84    buffer for use by sem_init; in case sem_open is used instead
85    SCEPTRE will changed to the value returned by sem_open.
86    GOT_SCEPTRE is a flag used for debugging to tell wether we hold
87    SCEPTRE.  */
88 static sem_t sceptre_buffer;
89 static sem_t *sceptre = &sceptre_buffer;
90 static int got_sceptre;
91
92 /* Configure defines HAVE_FORK_UNSAFE_SEMAPHORE if child process can't
93    access non-shared unnamed semaphore which is created by its parent.
94
95    We use unnamed semaphore (if available) for the global lock.  The
96    specific semaphore is only valid for those threads in a process,
97    and it is no use by other processes.  Thus, PSHARED argument for
98    sem_init is naturally 0.
99
100    However, there are daemon-like applications which use fork after
101    npth's initialization by npth_init.  In this case, a child process
102    uses the semaphore which was created by its parent process, while
103    parent does nothing with the semaphore.  In some system (e.g. AIX),
104    access by child process to non-shared unnamed semaphore is
105    prohibited.  For such a system, HAVE_FORK_UNSAFE_SEMAPHORE should
106    be defined, so that unnamed semaphore will be created with the
107    option PSHARED=1.  The purpose of the setting of PSHARED=1 is only
108    for allowing the access of the lock by child process.  For NPTH, it
109    does not mean any other interactions between processes.
110
111  */
112 #ifdef HAVE_FORK_UNSAFE_SEMAPHORE
113 #define NPTH_SEMAPHORE_PSHARED 1
114 #else
115 #define NPTH_SEMAPHORE_PSHARED 0
116 #endif
117
118 /* The main thread is the active thread at the time pth_init was
119    called.  As of now it is only useful for debugging.  The volatile
120    make sure the compiler does not eliminate this set but not used
121    variable.  */
122 static volatile pthread_t main_thread;
123
124 /* This flag is set as soon as npth_init has been called or if any
125  * thread has been created.  It will never be cleared again.  The only
126  * purpose is to make npth_protect and npth_unprotect more robust in
127  * that they can be shortcut when npth_init has not yet been called.
128  * This is important for libraries which want to support nPth by using
129  * those two functions but may have be initialized before pPth. */
130 static int initialized_or_any_threads;
131
132 /* Systems that don't have pthread_mutex_timedlock get a busy wait
133    implementation that probes the lock every BUSY_WAIT_INTERVAL
134    milliseconds.  */
135 #define BUSY_WAIT_INTERVAL 200
136
137 typedef int (*trylock_func_t) (void *);
138
139 static int
140 busy_wait_for (trylock_func_t trylock, void *lock,
141                const struct timespec *abstime)
142 {
143   int err;
144
145   /* This is not great, but better than nothing.  Only works for locks
146      which are mostly uncontested.  Provides absolutely no fairness at
147      all.  Creates many wake-ups.  */
148   while (1)
149     {
150       struct timespec ts;
151       err = npth_clock_gettime (&ts);
152       if (err < 0)
153         {
154           /* Just for safety make sure we return some error.  */
155           err = errno ? errno : EINVAL;
156           break;
157         }
158
159       if (! npth_timercmp (abstime, &ts, <))
160         {
161           err = ETIMEDOUT;
162           break;
163         }
164
165       err = (*trylock) (lock);
166       if (err != EBUSY)
167         break;
168
169       /* Try again after waiting a bit.  We could calculate the
170          maximum wait time from ts and abstime, but we don't
171          bother, as our granularity is pretty fine.  */
172       usleep (BUSY_WAIT_INTERVAL * 1000);
173     }
174
175   return err;
176 }
177
178 \f
179 static void
180 enter_npth (void)
181 {
182   int res;
183
184   got_sceptre = 0;
185   res = sem_post (sceptre);
186   assert (res == 0);
187 }
188
189
190 static void
191 leave_npth (void)
192 {
193   int res;
194   int save_errno = errno;
195
196   do {
197     res = sem_wait (sceptre);
198   } while (res < 0 && errno == EINTR);
199
200   assert (!res);
201   got_sceptre = 1;
202   errno = save_errno;
203 }
204
205 #define ENTER() enter_npth ()
206 #define LEAVE() leave_npth ()
207
208
209 int
210 npth_init (void)
211 {
212   int res;
213
214   main_thread = pthread_self();
215
216   /* Track that we have been initialized.  */
217   initialized_or_any_threads |= 1;
218
219   /* Better reset ERRNO so that we know that it has been set by
220      sem_init.  */
221   errno = 0;
222
223   /* The semaphore is binary.  */
224   res = sem_init (sceptre, NPTH_SEMAPHORE_PSHARED, 1);
225   /* There are some versions of operating systems which have sem_init
226      symbol defined but the call actually returns ENOSYS at runtime.
227      We know this problem for older versions of AIX (<= 4.3.3) and
228      macOS.  For macOS, we use semaphore in Grand Central Dispatch
229      library, so ENOSYS doesn't happen.  We only support AIX >= 5.2,
230      where sem_init is supported.
231    */
232   if (res < 0)
233     {
234       /* POSIX.1-2001 defines the semaphore interface but does not
235          specify the return value for success.  Thus we better
236          bail out on error only on a POSIX.1-2008 system.  */
237 #if _POSIX_C_SOURCE >= 200809L
238       return errno;
239 #endif
240     }
241
242   LEAVE();
243   return 0;
244 }
245
246
247 int
248 npth_getname_np (npth_t target_thread, char *buf, size_t buflen)
249 {
250 #ifdef HAVE_PTHREAD_GETNAME_NP
251   return pthread_getname_np (target_thread, buf, buflen);
252 #else
253   (void)target_thread;
254   (void)buf;
255   (void)buflen;
256   return ENOSYS;
257 #endif
258 }
259
260
261 int
262 npth_setname_np (npth_t target_thread, const char *name)
263 {
264 #ifdef HAVE_PTHREAD_SETNAME_NP
265 #ifdef __NetBSD__
266   return pthread_setname_np (target_thread, "%s", (void*) name);
267 #else
268 #ifdef __APPLE__
269   if (target_thread == npth_self ())
270     return pthread_setname_np (name);
271   else
272     return ENOTSUP;
273 #else
274   return pthread_setname_np (target_thread, name);
275 #endif
276 #endif
277 #else
278   (void)target_thread;
279   (void)name;
280   return ENOSYS;
281 #endif
282 }
283
284
285 \f
286 struct startup_s
287 {
288   void *(*start_routine) (void *);
289   void *arg;
290 };
291
292
293 static void *
294 thread_start (void *startup_arg)
295 {
296   struct startup_s *startup = startup_arg;
297   void *(*start_routine) (void *);
298   void *arg;
299   void *result;
300
301   start_routine = startup->start_routine;
302   arg = startup->arg;
303   free (startup);
304
305   LEAVE();
306   result = (*start_routine) (arg);
307   /* Note: instead of returning here, we might end up in
308      npth_exit() instead.  */
309   ENTER();
310
311   return result;
312 }
313
314
315 int
316 npth_create (npth_t *thread, const npth_attr_t *attr,
317              void *(*start_routine) (void *), void *arg)
318 {
319   int err;
320   struct startup_s *startup;
321
322   startup = malloc (sizeof (*startup));
323   if (!startup)
324     return errno;
325
326   initialized_or_any_threads |= 2;
327
328   startup->start_routine = start_routine;
329   startup->arg = arg;
330   err = pthread_create (thread, attr, thread_start, startup);
331   if (err)
332     {
333       free (startup);
334       return err;
335     }
336
337   /* Memory is released in thread_start.  */
338   return 0;
339 }
340
341
342 int
343 npth_join (npth_t thread, void **retval)
344 {
345   int err;
346
347 #ifdef HAVE_PTHREAD_TRYJOIN_NP
348   /* No need to allow competing threads to enter when we can get the
349      lock immediately.  pthread_tryjoin_np is a GNU extension.  */
350   err = pthread_tryjoin_np (thread, retval);
351   if (err != EBUSY)
352     return err;
353 #endif /*HAVE_PTHREAD_TRYJOIN_NP*/
354
355   ENTER();
356   err = pthread_join (thread, retval);
357   LEAVE();
358   return err;
359 }
360
361
362 void
363 npth_exit (void *retval)
364 {
365   ENTER();
366   pthread_exit (retval);
367   /* Never reached.  But just in case pthread_exit does return... */
368   LEAVE();
369 }
370
371 \f
372 int
373 npth_mutex_lock (npth_mutex_t *mutex)
374 {
375   int err;
376
377   /* No need to allow competing threads to enter when we can get the
378      lock immediately.  */
379   err = pthread_mutex_trylock (mutex);
380   if (err != EBUSY)
381     return err;
382
383   ENTER();
384   err = pthread_mutex_lock (mutex);
385   LEAVE();
386   return err;
387 }
388
389
390 int
391 npth_mutex_timedlock (npth_mutex_t *mutex, const struct timespec *abstime)
392 {
393   int err;
394
395   /* No need to allow competing threads to enter when we can get the
396      lock immediately.  */
397   err = pthread_mutex_trylock (mutex);
398   if (err != EBUSY)
399     return err;
400
401   ENTER();
402 #if HAVE_PTHREAD_MUTEX_TIMEDLOCK
403   err = pthread_mutex_timedlock (mutex, abstime);
404 #else
405   err = busy_wait_for ((trylock_func_t) pthread_mutex_trylock, mutex, abstime);
406 #endif
407   LEAVE();
408   return err;
409 }
410
411
412 #ifndef _NPTH_NO_RWLOCK
413 int
414 npth_rwlock_rdlock (npth_rwlock_t *rwlock)
415 {
416   int err;
417
418 #ifdef HAVE_PTHREAD_RWLOCK_TRYRDLOCK
419   /* No need to allow competing threads to enter when we can get the
420      lock immediately.  */
421   err = pthread_rwlock_tryrdlock (rwlock);
422   if (err != EBUSY)
423     return err;
424 #endif
425
426   ENTER();
427   err = pthread_rwlock_rdlock (rwlock);
428   LEAVE();
429   return err;
430 }
431
432
433 int
434 npth_rwlock_timedrdlock (npth_rwlock_t *rwlock, const struct timespec *abstime)
435 {
436   int err;
437
438 #ifdef HAVE_PTHREAD_RWLOCK_TRYRDLOCK
439   /* No need to allow competing threads to enter when we can get the
440      lock immediately.  */
441   err = pthread_rwlock_tryrdlock (rwlock);
442   if (err != EBUSY)
443     return err;
444 #endif
445
446   ENTER();
447 #if HAVE_PTHREAD_RWLOCK_TIMEDRDLOCK
448   err = pthread_rwlock_timedrdlock (rwlock, abstime);
449 #else
450   err = busy_wait_for ((trylock_func_t) pthread_rwlock_tryrdlock, rwlock,
451                        abstime);
452 #endif
453   LEAVE();
454   return err;
455 }
456
457
458 int
459 npth_rwlock_wrlock (npth_rwlock_t *rwlock)
460 {
461   int err;
462
463 #ifdef HAVE_PTHREAD_RWLOCK_TRYWRLOCK
464   /* No need to allow competing threads to enter when we can get the
465      lock immediately.  */
466   err = pthread_rwlock_trywrlock (rwlock);
467   if (err != EBUSY)
468     return err;
469 #endif
470
471   ENTER();
472   err = pthread_rwlock_wrlock (rwlock);
473   LEAVE();
474   return err;
475 }
476
477
478 int
479 npth_rwlock_timedwrlock (npth_rwlock_t *rwlock, const struct timespec *abstime)
480 {
481   int err;
482
483 #ifdef HAVE_PTHREAD_RWLOCK_TRYWRLOCK
484   /* No need to allow competing threads to enter when we can get the
485      lock immediately.  */
486   err = pthread_rwlock_trywrlock (rwlock);
487   if (err != EBUSY)
488     return err;
489 #endif
490
491   ENTER();
492 #if HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
493   err = pthread_rwlock_timedwrlock (rwlock, abstime);
494 #elif HAVE_PTHREAD_RWLOCK_TRYRDLOCK
495   err = busy_wait_for ((trylock_func_t) pthread_rwlock_trywrlock, rwlock,
496                        abstime);
497 #else
498   err = ENOSYS;
499 #endif
500   LEAVE();
501   return err;
502 }
503 #endif
504
505
506 int
507 npth_cond_wait (npth_cond_t *cond, npth_mutex_t *mutex)
508 {
509   int err;
510
511   ENTER();
512   err = pthread_cond_wait (cond, mutex);
513   LEAVE();
514   return err;
515 }
516
517
518 int
519 npth_cond_timedwait (npth_cond_t *cond, npth_mutex_t *mutex,
520                      const struct timespec *abstime)
521 {
522   int err;
523
524   ENTER();
525   err = pthread_cond_timedwait (cond, mutex, abstime);
526   LEAVE();
527   return err;
528 }
529
530 \f
531 /* Standard POSIX Replacement API */
532
533 int
534 npth_usleep(unsigned int usec)
535 {
536   int res;
537
538   ENTER();
539   res = usleep(usec);
540   LEAVE();
541   return res;
542 }
543
544
545 unsigned int
546 npth_sleep(unsigned int sec)
547 {
548   unsigned res;
549
550   ENTER();
551   res = sleep(sec);
552   LEAVE();
553   return res;
554 }
555
556
557 int
558 npth_system(const char *cmd)
559 {
560   int res;
561
562   ENTER();
563   res = system(cmd);
564   LEAVE();
565   return res;
566 }
567
568
569 pid_t
570 npth_waitpid(pid_t pid, int *status, int options)
571 {
572   pid_t res;
573
574   ENTER();
575   res = waitpid(pid,status, options);
576   LEAVE();
577   return res;
578 }
579
580
581 int
582 npth_connect(int s, const struct sockaddr *addr, socklen_t addrlen)
583 {
584   int res;
585
586   ENTER();
587   res = connect(s, addr, addrlen);
588   LEAVE();
589   return res;
590 }
591
592
593 int
594 npth_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
595 {
596   int res;
597
598   ENTER();
599   res = accept(s, addr, addrlen);
600   LEAVE();
601   return res;
602 }
603
604
605 int
606 npth_select(int nfd, fd_set *rfds, fd_set *wfds, fd_set *efds,
607             struct timeval *timeout)
608 {
609   int res;
610
611   ENTER();
612   res = select(nfd, rfds, wfds, efds, timeout);
613   LEAVE();
614   return res;
615 }
616
617
618 int
619 npth_pselect(int nfd, fd_set *rfds, fd_set *wfds, fd_set *efds,
620              const struct timespec *timeout, const sigset_t *sigmask)
621 {
622   int res;
623
624   ENTER();
625 #ifdef HAVE_PSELECT
626   res = pselect (nfd, rfds, wfds, efds, timeout, sigmask);
627 #else /*!HAVE_PSELECT*/
628   {
629     /* A better emulation of pselect would be to create a pipe, wait
630        in the select for one end and have a signal handler write to
631        the other end.  However, this is non-trivial to implement and
632        thus we only print a compile time warning.  */
633 #   ifdef __GNUC__
634 #     warning Using a non race free pselect emulation.
635 #   endif
636
637     struct timeval t, *tp;
638
639     tp = NULL;
640     if (!timeout)
641       ;
642     else if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000)
643       {
644         t.tv_sec = timeout->tv_sec;
645         t.tv_usec = (timeout->tv_nsec + 999) / 1000;
646         tp = &t;
647       }
648     else
649       {
650         errno = EINVAL;
651         res = -1;
652         goto leave;
653       }
654
655     if (sigmask)
656       {
657         int save_errno;
658         sigset_t savemask;
659
660         pthread_sigmask (SIG_SETMASK, sigmask, &savemask);
661         res = select (nfd, rfds, wfds, efds, tp);
662         save_errno = errno;
663         pthread_sigmask (SIG_SETMASK, &savemask, NULL);
664         errno = save_errno;
665       }
666     else
667       res = select (nfd, rfds, wfds, efds, tp);
668
669   leave:
670     ;
671   }
672 #endif /*!HAVE_PSELECT*/
673   LEAVE();
674   return res;
675 }
676
677
678 ssize_t
679 npth_read(int fd, void *buf, size_t nbytes)
680 {
681   ssize_t res;
682
683   ENTER();
684   res = read(fd, buf, nbytes);
685   LEAVE();
686   return res;
687 }
688
689
690 ssize_t
691 npth_write(int fd, const void *buf, size_t nbytes)
692 {
693   ssize_t res;
694
695   ENTER();
696   res = write(fd, buf, nbytes);
697   LEAVE();
698   return res;
699 }
700
701
702 int
703 npth_recvmsg (int fd, struct msghdr *msg, int flags)
704 {
705   int res;
706
707   ENTER();
708   res = recvmsg (fd, msg, flags);
709   LEAVE();
710   return res;
711 }
712
713
714 int
715 npth_sendmsg (int fd, const struct msghdr *msg, int flags)
716 {
717   int res;
718
719   ENTER();
720   res = sendmsg (fd, msg, flags);
721   LEAVE();
722   return res;
723 }
724
725
726 void
727 npth_unprotect (void)
728 {
729   /* If we are not initialized we may not access the semaphore and
730    * thus we shortcut it. Note that in this case the unprotect/protect
731    * is not needed.  For failsafe reasons if an nPth thread has ever
732    * been created but nPth has accidentally not initialized we do not
733    * shortcut so that a stack backtrace (due to the access of the
734    * uninitialized semaphore) is more expressive.  */
735   if (initialized_or_any_threads)
736     ENTER();
737 }
738
739
740 void
741 npth_protect (void)
742 {
743   /* See npth_unprotect for commentary.  */
744   if (initialized_or_any_threads)
745     LEAVE();
746 }
747
748
749 int
750 npth_is_protected (void)
751 {
752   return got_sceptre;
753 }
754
755
756 int
757 npth_clock_gettime (struct timespec *ts)
758 {
759 #if defined(CLOCK_REALTIME) && HAVE_CLOCK_GETTIME
760   return clock_gettime (CLOCK_REALTIME, ts);
761 #elif HAVE_GETTIMEOFDAY
762   {
763     struct timeval tv;
764
765     if (gettimeofday (&tv, NULL))
766       return -1;
767     ts->tv_sec = tv.tv_sec;
768     ts->tv_nsec = tv.tv_usec * 1000;
769     return 0;
770   }
771 #else
772   /* FIXME: fall back on time() with seconds resolution.  */
773 # error clock_gettime not available - please provide a fallback.
774 #endif
775 }