(root)/
coreutils-9.4/
lib/
pthread-mutex.c
       1  /* POSIX mutexes (locks).
       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-timedmutex.h"
      26  # include "windows-timedrecmutex.h"
      27  #else
      28  # include <stdlib.h>
      29  #endif
      30  
      31  #if ((defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS) || !HAVE_PTHREAD_H
      32  
      33  int
      34  pthread_mutexattr_init (pthread_mutexattr_t *attr)
      35  {
      36    *attr = (PTHREAD_MUTEX_STALLED << 2) | PTHREAD_MUTEX_DEFAULT;
      37    return 0;
      38  }
      39  
      40  int
      41  pthread_mutexattr_gettype (const pthread_mutexattr_t *attr, int *typep)
      42  {
      43    *typep = *attr & (PTHREAD_MUTEX_DEFAULT | PTHREAD_MUTEX_NORMAL
      44                      | PTHREAD_MUTEX_ERRORCHECK | PTHREAD_MUTEX_RECURSIVE);
      45    return 0;
      46  }
      47  
      48  int
      49  pthread_mutexattr_settype (pthread_mutexattr_t *attr, int type)
      50  {
      51    if (!(type == PTHREAD_MUTEX_DEFAULT
      52          || type == PTHREAD_MUTEX_NORMAL
      53          || type == PTHREAD_MUTEX_ERRORCHECK
      54          || type == PTHREAD_MUTEX_RECURSIVE))
      55      return EINVAL;
      56    *attr ^= (*attr ^ type)
      57             & (PTHREAD_MUTEX_DEFAULT | PTHREAD_MUTEX_NORMAL
      58                | PTHREAD_MUTEX_ERRORCHECK | PTHREAD_MUTEX_RECURSIVE);
      59    return 0;
      60  }
      61  
      62  int
      63  pthread_mutexattr_getrobust (const pthread_mutexattr_t *attr, int *robustp)
      64  {
      65    *robustp = (*attr >> 2) & (PTHREAD_MUTEX_STALLED | PTHREAD_MUTEX_ROBUST);
      66    return 0;
      67  }
      68  
      69  int
      70  pthread_mutexattr_setrobust (pthread_mutexattr_t *attr, int robust)
      71  {
      72    if (!(robust == PTHREAD_MUTEX_STALLED || robust == PTHREAD_MUTEX_ROBUST))
      73      return EINVAL;
      74    *attr ^= (*attr ^ (robust << 2))
      75             & ((PTHREAD_MUTEX_STALLED | PTHREAD_MUTEX_ROBUST) << 2);
      76    return 0;
      77  }
      78  
      79  int
      80  pthread_mutexattr_destroy (_GL_UNUSED pthread_mutexattr_t *attr)
      81  {
      82    return 0;
      83  }
      84  
      85  #elif PTHREAD_MUTEXATTR_ROBUST_UNIMPLEMENTED
      86  
      87  int
      88  pthread_mutexattr_getrobust (const pthread_mutexattr_t *attr, int *robustp)
      89  {
      90    *robustp = PTHREAD_MUTEX_STALLED;
      91    return 0;
      92  }
      93  
      94  int
      95  pthread_mutexattr_setrobust (pthread_mutexattr_t *attr, int robust)
      96  {
      97    if (!(robust == PTHREAD_MUTEX_STALLED || robust == PTHREAD_MUTEX_ROBUST))
      98      return EINVAL;
      99    if (!(robust == PTHREAD_MUTEX_STALLED))
     100      return ENOTSUP;
     101    return 0;
     102  }
     103  
     104  #endif
     105  
     106  #if (defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS
     107  /* Use Windows threads.  */
     108  
     109  int
     110  pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
     111  {
     112    /* This implementation does not support PTHREAD_MUTEX_ERRORCHECK
     113       and ignores the 'robust' attribute.  */
     114    if (attr != NULL
     115        && (*attr & (PTHREAD_MUTEX_DEFAULT | PTHREAD_MUTEX_NORMAL
     116                     | PTHREAD_MUTEX_ERRORCHECK | PTHREAD_MUTEX_RECURSIVE))
     117           == PTHREAD_MUTEX_RECURSIVE)
     118      {
     119        mutex->type = 2;
     120        return glwthread_timedrecmutex_init (&mutex->u.u_timedrecmutex);
     121      }
     122    else
     123      {
     124        mutex->type = 1;
     125        return glwthread_timedmutex_init (&mutex->u.u_timedmutex);
     126      }
     127  }
     128  
     129  int
     130  pthread_mutex_lock (pthread_mutex_t *mutex)
     131  {
     132    switch (mutex->type)
     133      {
     134      case 1:
     135        return glwthread_timedmutex_lock (&mutex->u.u_timedmutex);
     136      case 2:
     137        return glwthread_timedrecmutex_lock (&mutex->u.u_timedrecmutex);
     138      default:
     139        abort ();
     140      }
     141  }
     142  
     143  int
     144  pthread_mutex_trylock (pthread_mutex_t *mutex)
     145  {
     146    switch (mutex->type)
     147      {
     148      case 1:
     149        return glwthread_timedmutex_trylock (&mutex->u.u_timedmutex);
     150      case 2:
     151        return glwthread_timedrecmutex_trylock (&mutex->u.u_timedrecmutex);
     152      default:
     153        abort ();
     154      }
     155  }
     156  
     157  int
     158  pthread_mutex_timedlock (pthread_mutex_t *mutex, const struct timespec *abstime)
     159  {
     160    switch (mutex->type)
     161      {
     162      case 1:
     163        return glwthread_timedmutex_timedlock (&mutex->u.u_timedmutex, abstime);
     164      case 2:
     165        return glwthread_timedrecmutex_timedlock (&mutex->u.u_timedrecmutex,
     166                                                  abstime);
     167      default:
     168        abort ();
     169      }
     170  }
     171  
     172  int
     173  pthread_mutex_unlock (pthread_mutex_t *mutex)
     174  {
     175    switch (mutex->type)
     176      {
     177      case 1:
     178        return glwthread_timedmutex_unlock (&mutex->u.u_timedmutex);
     179      case 2:
     180        return glwthread_timedrecmutex_unlock (&mutex->u.u_timedrecmutex);
     181      default:
     182        abort ();
     183      }
     184  }
     185  
     186  int
     187  pthread_mutex_destroy (pthread_mutex_t *mutex)
     188  {
     189    switch (mutex->type)
     190      {
     191      case 1:
     192        return glwthread_timedmutex_destroy (&mutex->u.u_timedmutex);
     193      case 2:
     194        return glwthread_timedrecmutex_destroy (&mutex->u.u_timedrecmutex);
     195      default:
     196        abort ();
     197      }
     198  }
     199  
     200  #elif HAVE_PTHREAD_H
     201  /* Provide workarounds for POSIX threads.  */
     202  
     203  /* pthread_mutex_timedlock is defined by the 'pthread_mutex_timedlock'
     204     module.  */
     205  
     206  #else
     207  /* Provide a dummy implementation for single-threaded applications.  */
     208  
     209  int
     210  pthread_mutex_init (_GL_UNUSED pthread_mutex_t *mutex,
     211                      _GL_UNUSED const pthread_mutexattr_t *attr)
     212  {
     213    /* MUTEX is never seriously used.  */
     214    return 0;
     215  }
     216  
     217  int
     218  pthread_mutex_lock (_GL_UNUSED pthread_mutex_t *mutex)
     219  {
     220    /* There is only one thread, so it always gets the lock.  This
     221       implementation does not support PTHREAD_MUTEX_ERRORCHECK.  */
     222    return 0;
     223  }
     224  
     225  int
     226  pthread_mutex_trylock (_GL_UNUSED pthread_mutex_t *mutex)
     227  {
     228    /* There is only one thread, so it always gets the lock.  This
     229       implementation does not support PTHREAD_MUTEX_ERRORCHECK.  */
     230    return 0;
     231  }
     232  
     233  int
     234  pthread_mutex_timedlock (_GL_UNUSED pthread_mutex_t *mutex,
     235                           _GL_UNUSED const struct timespec *abstime)
     236  {
     237    /* There is only one thread, so it always gets the lock.  This
     238       implementation does not support PTHREAD_MUTEX_ERRORCHECK.  */
     239    return 0;
     240  }
     241  
     242  int
     243  pthread_mutex_unlock (_GL_UNUSED pthread_mutex_t *mutex)
     244  {
     245    /* There is only one thread, so it always unlocks successfully.
     246       This implementation does not support robust mutexes or
     247       PTHREAD_MUTEX_ERRORCHECK.  */
     248    return 0;
     249  }
     250  
     251  int
     252  pthread_mutex_destroy (_GL_UNUSED pthread_mutex_t *mutex)
     253  {
     254    /* MUTEX is never seriously used.  */
     255    return 0;
     256  }
     257  
     258  #endif