(root)/
coreutils-9.4/
lib/
pthread-cond.c
       1  /* POSIX condition variables.
       2     Copyright (C) 2010-2023 Free Software Foundation, Inc.
       3  
       4     This file is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU Lesser General Public License as
       6     published by the Free Software Foundation; either version 2.1 of the
       7     License, or (at your option) any later version.
       8  
       9     This file is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Written by Paul Eggert, 2010, and Bruno Haible <bruno@clisp.org>, 2019.  */
      18  
      19  #include <config.h>
      20  
      21  /* Specification.  */
      22  #include <pthread.h>
      23  
      24  #if (defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS
      25  # include "windows-thread.h"
      26  #else
      27  # include <errno.h>
      28  # include <limits.h>
      29  # include <sys/time.h>
      30  # include <time.h>
      31  #endif
      32  
      33  #if ((defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS) || !HAVE_PTHREAD_H
      34  
      35  int
      36  pthread_condattr_init (pthread_condattr_t *attr)
      37  {
      38    *attr = 0;
      39    return 0;
      40  }
      41  
      42  int
      43  pthread_condattr_destroy (_GL_UNUSED pthread_condattr_t *attr)
      44  {
      45    return 0;
      46  }
      47  
      48  #endif
      49  
      50  #if (defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS
      51  /* Use Windows threads.  */
      52  
      53  int
      54  pthread_cond_init (pthread_cond_t *cond,
      55                     _GL_UNUSED const pthread_condattr_t *attr)
      56  {
      57    return glwthread_cond_init (cond);
      58  }
      59  
      60  int
      61  pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
      62  {
      63    return glwthread_cond_wait (cond, mutex,
      64                                (int (*) (void *)) pthread_mutex_lock,
      65                                (int (*) (void *)) pthread_mutex_unlock);
      66  }
      67  
      68  int
      69  pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
      70                          const struct timespec *abstime)
      71  {
      72    return glwthread_cond_timedwait (cond, mutex,
      73                                     (int (*) (void *)) pthread_mutex_lock,
      74                                     (int (*) (void *)) pthread_mutex_unlock,
      75                                     abstime);
      76  }
      77  
      78  int
      79  pthread_cond_signal (pthread_cond_t *cond)
      80  {
      81    return glwthread_cond_signal (cond);
      82  }
      83  
      84  int
      85  pthread_cond_broadcast (pthread_cond_t *cond)
      86  {
      87    return glwthread_cond_broadcast (cond);
      88  }
      89  
      90  int
      91  pthread_cond_destroy (pthread_cond_t *cond)
      92  {
      93    return glwthread_cond_destroy (cond);
      94  }
      95  
      96  #elif HAVE_PTHREAD_H
      97  /* Provide workarounds for POSIX threads.  */
      98  
      99  #else
     100  /* Provide a dummy implementation for single-threaded applications.  */
     101  
     102  int
     103  pthread_cond_init (_GL_UNUSED pthread_cond_t *cond,
     104                     _GL_UNUSED const pthread_condattr_t *attr)
     105  {
     106    /* COND is never seriously used.  */
     107    return 0;
     108  }
     109  
     110  int
     111  pthread_cond_wait (_GL_UNUSED pthread_cond_t *cond,
     112                     _GL_UNUSED pthread_mutex_t *mutex)
     113  {
     114    /* No other thread can signal this condition variable.
     115       Wait endlessly.  */
     116    for (;;)
     117      {
     118        struct timespec duration =
     119          {
     120            .tv_sec = 86400,
     121            .tv_nsec = 0
     122          };
     123        nanosleep (&duration, NULL);
     124      }
     125  }
     126  
     127  int
     128  pthread_cond_timedwait (_GL_UNUSED pthread_cond_t *cond,
     129                          _GL_UNUSED pthread_mutex_t *mutex,
     130                          const struct timespec *abstime)
     131  {
     132    /* No other thread can signal this condition variable.
     133       Wait until ABSTIME is reached.  */
     134    for (;;)
     135      {
     136        struct timeval currtime;
     137        unsigned long remaining;
     138  
     139        gettimeofday (&currtime, NULL);
     140  
     141        if (currtime.tv_sec > abstime->tv_sec)
     142          remaining = 0;
     143        else
     144          {
     145            unsigned long seconds = abstime->tv_sec - currtime.tv_sec;
     146            remaining = seconds * 1000000000;
     147            if (remaining / 1000000000 != seconds) /* overflow? */
     148              remaining = ULONG_MAX;
     149            else
     150              {
     151                long nanoseconds =
     152                  abstime->tv_nsec - currtime.tv_usec * 1000;
     153                if (nanoseconds >= 0)
     154                  {
     155                    remaining += nanoseconds;
     156                    if (remaining < nanoseconds) /* overflow? */
     157                      remaining = ULONG_MAX;
     158                  }
     159                else
     160                  {
     161                    if (remaining >= - nanoseconds)
     162                      remaining -= (- nanoseconds);
     163                    else
     164                      remaining = 0;
     165                  }
     166              }
     167          }
     168        if (remaining == 0)
     169          return ETIMEDOUT;
     170  
     171        /* Sleep up to REMAINING ns.  */
     172        struct timespec duration = { .tv_sec  = remaining / 1000000000,
     173                                     .tv_nsec = remaining % 1000000000 };
     174        nanosleep (&duration, NULL);
     175      }
     176  }
     177  
     178  int
     179  pthread_cond_signal (_GL_UNUSED pthread_cond_t *cond)
     180  {
     181    /* No threads can currently be blocked on COND.  */
     182    return 0;
     183  }
     184  
     185  int
     186  pthread_cond_broadcast (_GL_UNUSED pthread_cond_t *cond)
     187  {
     188    /* No threads can currently be blocked on COND.  */
     189    return 0;
     190  }
     191  
     192  int
     193  pthread_cond_destroy (_GL_UNUSED pthread_cond_t *cond)
     194  {
     195    /* COND is never seriously used.  */
     196    return 0;
     197  }
     198  
     199  #endif