LCOV - code coverage report
Current view: top level - src - npth.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 64 198 32.3 %
Date: 2017-03-02 16:41:06 Functions: 10 33 30.3 %

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

Generated by: LCOV version 1.13