root/maint/gnulib/lib/mtx.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mtx_init
  2. mtx_lock
  3. mtx_trylock
  4. mtx_timedlock
  5. mtx_unlock
  6. mtx_destroy
  7. call_once
  8. mtx_init
  9. mtx_lock
  10. mtx_trylock
  11. mtx_timedlock
  12. mtx_unlock
  13. mtx_destroy
  14. call_once

   1 /* ISO C 11 locking in multithreaded situations.
   2    Copyright (C) 2005-2021 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 Bruno Haible <bruno@clisp.org>, 2005, 2019.
  18    Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h.  */
  19 
  20 #include <config.h>
  21 
  22 #include <threads.h>
  23 
  24 #include <errno.h>
  25 
  26 #if defined _WIN32 && ! defined __CYGWIN__
  27 /* Use Windows threads.  */
  28 
  29 # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
  30 # include <windows.h>
  31 
  32 # include <stdlib.h>
  33 
  34 #else
  35 /* Use POSIX threads.  */
  36 
  37 # include <pthread.h>
  38 
  39 #endif
  40 
  41 #if defined _WIN32 && ! defined __CYGWIN__
  42 /* Use Windows threads.  */
  43 
  44 int
  45 mtx_init (mtx_t *mutex, int type)
     /* [previous][next][first][last][top][bottom][index][help] */
  46 {
  47   switch (type)
  48     {
  49     case mtx_plain:
  50       glwthread_mutex_init (&mutex->u.u_mutex);
  51       break;
  52     case mtx_plain | mtx_recursive:
  53       glwthread_recmutex_init (&mutex->u.u_recmutex);
  54       break;
  55     case mtx_timed:
  56       if (glwthread_timedmutex_init (&mutex->u.u_timedmutex) != 0)
  57         return thrd_error;
  58       break;
  59     case mtx_timed | mtx_recursive:
  60       if (glwthread_timedrecmutex_init (&mutex->u.u_timedrecmutex) != 0)
  61         return thrd_error;
  62       break;
  63     default:
  64       return thrd_error;
  65     }
  66   mutex->type = type;
  67   return thrd_success;
  68 }
  69 
  70 int
  71 mtx_lock (mtx_t *mutex)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73   int err;
  74 
  75   switch (mutex->type)
  76     {
  77     case mtx_plain:
  78       err = glwthread_mutex_lock (&mutex->u.u_mutex);
  79       break;
  80     case mtx_plain | mtx_recursive:
  81       err = glwthread_recmutex_lock (&mutex->u.u_recmutex);
  82       break;
  83     case mtx_timed:
  84       err = glwthread_timedmutex_lock (&mutex->u.u_timedmutex);
  85       break;
  86     case mtx_timed | mtx_recursive:
  87       err = glwthread_timedrecmutex_lock (&mutex->u.u_timedrecmutex);
  88       break;
  89     default:
  90       abort ();
  91     }
  92   return (err == 0 ? thrd_success : thrd_error);
  93 }
  94 
  95 int
  96 mtx_trylock (mtx_t *mutex)
     /* [previous][next][first][last][top][bottom][index][help] */
  97 {
  98   int err;
  99 
 100   switch (mutex->type)
 101     {
 102     case mtx_plain:
 103       err = glwthread_mutex_trylock (&mutex->u.u_mutex);
 104       break;
 105     case mtx_plain | mtx_recursive:
 106       err = glwthread_recmutex_trylock (&mutex->u.u_recmutex);
 107       break;
 108     case mtx_timed:
 109       err = glwthread_timedmutex_trylock (&mutex->u.u_timedmutex);
 110       break;
 111     case mtx_timed | mtx_recursive:
 112       err = glwthread_timedrecmutex_trylock (&mutex->u.u_timedrecmutex);
 113       break;
 114     default:
 115       abort ();
 116     }
 117   return (err == 0 ? thrd_success : err == EBUSY ? thrd_busy : thrd_error);
 118 }
 119 
 120 int
 121 mtx_timedlock (mtx_t *mutex, const struct timespec *abstime)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123   int err;
 124 
 125   switch (mutex->type)
 126     {
 127     case mtx_plain:
 128     case mtx_plain | mtx_recursive:
 129       return thrd_error;
 130     case mtx_timed:
 131       err = glwthread_timedmutex_timedlock (&mutex->u.u_timedmutex, abstime);
 132       break;
 133     case mtx_timed | mtx_recursive:
 134       err =
 135         glwthread_timedrecmutex_timedlock (&mutex->u.u_timedrecmutex, abstime);
 136       break;
 137     default:
 138       abort ();
 139     }
 140   return (err == 0 ? thrd_success : err == EBUSY ? thrd_busy : thrd_error);
 141 }
 142 
 143 int
 144 mtx_unlock (mtx_t *mutex)
     /* [previous][next][first][last][top][bottom][index][help] */
 145 {
 146   int err;
 147 
 148   switch (mutex->type)
 149     {
 150     case mtx_plain:
 151       err = glwthread_mutex_unlock (&mutex->u.u_mutex);
 152       break;
 153     case mtx_plain | mtx_recursive:
 154       err = glwthread_recmutex_unlock (&mutex->u.u_recmutex);
 155       break;
 156     case mtx_timed:
 157       err = glwthread_timedmutex_unlock (&mutex->u.u_timedmutex);
 158       break;
 159     case mtx_timed | mtx_recursive:
 160       err = glwthread_timedrecmutex_unlock (&mutex->u.u_timedrecmutex);
 161       break;
 162     default:
 163       abort ();
 164     }
 165   return (err == 0 ? thrd_success : thrd_error);
 166 }
 167 
 168 void
 169 mtx_destroy (mtx_t *mutex)
     /* [previous][next][first][last][top][bottom][index][help] */
 170 {
 171   switch (mutex->type)
 172     {
 173     case mtx_plain:
 174       glwthread_mutex_destroy (&mutex->u.u_mutex);
 175       break;
 176     case mtx_plain | mtx_recursive:
 177       glwthread_recmutex_destroy (&mutex->u.u_recmutex);
 178       break;
 179     case mtx_timed:
 180       glwthread_timedmutex_destroy (&mutex->u.u_timedmutex);
 181       break;
 182     case mtx_timed | mtx_recursive:
 183       glwthread_timedrecmutex_destroy (&mutex->u.u_timedrecmutex);
 184       break;
 185     default:
 186       abort ();
 187     }
 188 }
 189 
 190 void
 191 call_once (once_flag *flagp, void (*func) (void))
     /* [previous][next][first][last][top][bottom][index][help] */
 192 {
 193   glwthread_once (flagp, func);
 194 }
 195 
 196 #else
 197 /* Use POSIX threads.  */
 198 
 199 int
 200 mtx_init (mtx_t *mutex, int type)
     /* [previous][next][first][last][top][bottom][index][help] */
 201 {
 202   switch (type)
 203     {
 204     case mtx_plain:
 205     case mtx_timed:
 206     case mtx_plain | mtx_recursive:
 207     case mtx_timed | mtx_recursive:
 208       break;
 209     default:
 210       return thrd_error;
 211     }
 212 
 213   if ((type & mtx_recursive) != 0)
 214     {
 215       pthread_mutexattr_t attributes;
 216       int err;
 217 
 218       err = pthread_mutexattr_init (&attributes);
 219       if (err != 0)
 220         return thrd_error;
 221       err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
 222       if (err != 0)
 223         {
 224           pthread_mutexattr_destroy (&attributes);
 225           return thrd_error;
 226         }
 227       err = pthread_mutex_init (mutex, &attributes);
 228       if (err != 0)
 229         {
 230           pthread_mutexattr_destroy (&attributes);
 231           return thrd_error;
 232         }
 233       err = pthread_mutexattr_destroy (&attributes);
 234       if (err != 0)
 235         return thrd_error;
 236     }
 237   else
 238     {
 239       int err = pthread_mutex_init (mutex, NULL);
 240       if (err != 0)
 241         return thrd_error;
 242     }
 243   return thrd_success;
 244 }
 245 
 246 int
 247 mtx_lock (mtx_t *mutex)
     /* [previous][next][first][last][top][bottom][index][help] */
 248 {
 249   int err = pthread_mutex_lock (mutex);
 250   return (err == 0 ? thrd_success : thrd_error);
 251 }
 252 
 253 int
 254 mtx_trylock (mtx_t *mutex)
     /* [previous][next][first][last][top][bottom][index][help] */
 255 {
 256   int err = pthread_mutex_trylock (mutex);
 257   return (err == 0 ? thrd_success : err == EBUSY ? thrd_busy : thrd_error);
 258 }
 259 
 260 int
 261 mtx_timedlock (mtx_t *mutex, const struct timespec *abstime)
     /* [previous][next][first][last][top][bottom][index][help] */
 262 {
 263   int err = pthread_mutex_timedlock (mutex, abstime);
 264   return (err == 0 ? thrd_success :
 265           err == ETIMEDOUT ? thrd_timedout :
 266           thrd_error);
 267 }
 268 
 269 int
 270 mtx_unlock (mtx_t *mutex)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272   int err = pthread_mutex_unlock (mutex);
 273   return (err == 0 ? thrd_success : thrd_error);
 274 }
 275 
 276 void
 277 mtx_destroy (mtx_t *mutex)
     /* [previous][next][first][last][top][bottom][index][help] */
 278 {
 279   pthread_mutex_destroy (mutex);
 280 }
 281 
 282 void
 283 call_once (once_flag *flagp, void (*func) (void))
     /* [previous][next][first][last][top][bottom][index][help] */
 284 {
 285   pthread_once (flagp, func);
 286 }
 287 
 288 #endif

/* [previous][next][first][last][top][bottom][index][help] */