(root)/
bison-3.8.2/
lib/
glthread/
tls.h
       1  /* Thread-local storage in multithreaded situations.
       2     Copyright (C) 2005, 2007-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.  */
      18  
      19  /* This file contains thread-local storage primitives for use with a given
      20     thread library.  It does not contain primitives for creating threads or
      21     for other multithreading primitives.
      22  
      23       Type:                      gl_tls_key_t
      24       Initialization:            gl_tls_key_init (name, destructor);
      25       Getting per-thread value:  gl_tls_get (name)
      26       Setting per-thread value:  gl_tls_set (name, pointer);
      27       De-initialization:         gl_tls_key_destroy (name);
      28     Equivalent functions with control of error handling:
      29       Initialization:            err = glthread_tls_key_init (&name, destructor);
      30       Setting per-thread value:  err = glthread_tls_set (&name, pointer);
      31       De-initialization:         err = glthread_tls_key_destroy (&name);
      32  
      33     A per-thread value is of type 'void *'.
      34  
      35     A destructor is a function pointer of type 'void (*) (void *)', called
      36     when a thread exits, and taking the last per-thread value as argument.  It
      37     is unspecified whether the destructor function is called when the last
      38     per-thread value is NULL.  On some platforms, the destructor function is
      39     not called at all.
      40  */
      41  
      42  
      43  #ifndef _TLS_H
      44  #define _TLS_H
      45  
      46  #include <errno.h>
      47  #include <stdlib.h>
      48  
      49  #if !defined c11_threads_in_use
      50  # if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC
      51  #  define c11_threads_in_use() 1
      52  # elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK
      53  #  include <threads.h>
      54  #  pragma weak thrd_exit
      55  #  define c11_threads_in_use() (thrd_exit != NULL)
      56  # else
      57  #  define c11_threads_in_use() 0
      58  # endif
      59  #endif
      60  
      61  /* ========================================================================= */
      62  
      63  #if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS
      64  
      65  /* Use the ISO C threads library.  */
      66  
      67  # include <threads.h>
      68  
      69  /* ------------------------- gl_tls_key_t datatype ------------------------- */
      70  
      71  typedef tss_t gl_tls_key_t;
      72  # define glthread_tls_key_init(KEY, DESTRUCTOR) \
      73      (tss_create (KEY, DESTRUCTOR) != thrd_success ? EAGAIN : 0)
      74  # define gl_tls_get(NAME) \
      75      tss_get (NAME)
      76  # define glthread_tls_set(KEY, POINTER) \
      77      (tss_set (*(KEY), (POINTER)) != thrd_success ? ENOMEM : 0)
      78  # define glthread_tls_key_destroy(KEY) \
      79      (tss_delete (*(KEY)), 0)
      80  
      81  #endif
      82  
      83  /* ========================================================================= */
      84  
      85  #if USE_POSIX_THREADS
      86  
      87  /* Use the POSIX threads library.  */
      88  
      89  # include <pthread.h>
      90  
      91  # if PTHREAD_IN_USE_DETECTION_HARD
      92  
      93  /* The pthread_in_use() detection needs to be done at runtime.  */
      94  #  define pthread_in_use() \
      95       glthread_in_use ()
      96  extern int glthread_in_use (void);
      97  
      98  # endif
      99  
     100  # if USE_POSIX_THREADS_WEAK
     101  
     102  /* Use weak references to the POSIX threads library.  */
     103  
     104  #  pragma weak pthread_key_create
     105  #  pragma weak pthread_getspecific
     106  #  pragma weak pthread_setspecific
     107  #  pragma weak pthread_key_delete
     108  #  ifndef pthread_self
     109  #   pragma weak pthread_self
     110  #  endif
     111  
     112  #  if !PTHREAD_IN_USE_DETECTION_HARD
     113  #   pragma weak pthread_mutexattr_gettype
     114  #   define pthread_in_use() \
     115        (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
     116  #  endif
     117  
     118  # else
     119  
     120  #  if !PTHREAD_IN_USE_DETECTION_HARD
     121  #   define pthread_in_use() 1
     122  #  endif
     123  
     124  # endif
     125  
     126  /* ------------------------- gl_tls_key_t datatype ------------------------- */
     127  
     128  typedef union
     129          {
     130            void *singlethread_value;
     131            pthread_key_t key;
     132          }
     133          gl_tls_key_t;
     134  # define glthread_tls_key_init(KEY, DESTRUCTOR) \
     135      (pthread_in_use ()                              \
     136       ? pthread_key_create (&(KEY)->key, DESTRUCTOR) \
     137       : ((KEY)->singlethread_value = NULL, 0))
     138  # define gl_tls_get(NAME) \
     139      (pthread_in_use ()                  \
     140       ? pthread_getspecific ((NAME).key) \
     141       : (NAME).singlethread_value)
     142  # define glthread_tls_set(KEY, POINTER) \
     143      (pthread_in_use ()                             \
     144       ? pthread_setspecific ((KEY)->key, (POINTER)) \
     145       : ((KEY)->singlethread_value = (POINTER), 0))
     146  # define glthread_tls_key_destroy(KEY) \
     147      (pthread_in_use () ? pthread_key_delete ((KEY)->key) : 0)
     148  
     149  #endif
     150  
     151  /* ========================================================================= */
     152  
     153  #if USE_WINDOWS_THREADS
     154  
     155  # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
     156  # include <windows.h>
     157  
     158  # include "windows-tls.h"
     159  
     160  /* ------------------------- gl_tls_key_t datatype ------------------------- */
     161  
     162  typedef glwthread_tls_key_t gl_tls_key_t;
     163  # define glthread_tls_key_init(KEY, DESTRUCTOR) \
     164      glwthread_tls_key_create (KEY, DESTRUCTOR)
     165  # define gl_tls_get(NAME) \
     166      TlsGetValue (NAME)
     167  # define glthread_tls_set(KEY, POINTER) \
     168      (!TlsSetValue (*(KEY), POINTER) ? EINVAL : 0)
     169  # define glthread_tls_key_destroy(KEY) \
     170      glwthread_tls_key_delete (*(KEY))
     171  
     172  #endif
     173  
     174  /* ========================================================================= */
     175  
     176  #if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)
     177  
     178  /* Provide dummy implementation if threads are not supported.  */
     179  
     180  /* ------------------------- gl_tls_key_t datatype ------------------------- */
     181  
     182  typedef struct
     183          {
     184            void *singlethread_value;
     185          }
     186          gl_tls_key_t;
     187  # define glthread_tls_key_init(KEY, DESTRUCTOR) \
     188      ((KEY)->singlethread_value = NULL, \
     189       (void) (DESTRUCTOR),              \
     190       0)
     191  # define gl_tls_get(NAME) \
     192      (NAME).singlethread_value
     193  # define glthread_tls_set(KEY, POINTER) \
     194      ((KEY)->singlethread_value = (POINTER), 0)
     195  # define glthread_tls_key_destroy(KEY) \
     196      0
     197  
     198  #endif
     199  
     200  /* ========================================================================= */
     201  
     202  /* Macros with built-in error handling.  */
     203  
     204  /* ------------------------- gl_tls_key_t datatype ------------------------- */
     205  
     206  #define gl_tls_key_init(NAME, DESTRUCTOR) \
     207     do                                                 \
     208       {                                                \
     209         if (glthread_tls_key_init (&NAME, DESTRUCTOR)) \
     210           abort ();                                    \
     211       }                                                \
     212     while (0)
     213  #define gl_tls_set(NAME, POINTER) \
     214     do                                         \
     215       {                                        \
     216         if (glthread_tls_set (&NAME, POINTER)) \
     217           abort ();                            \
     218       }                                        \
     219     while (0)
     220  #define gl_tls_key_destroy(NAME) \
     221     do                                        \
     222       {                                       \
     223         if (glthread_tls_key_destroy (&NAME)) \
     224           abort ();                           \
     225       }                                       \
     226     while (0)
     227  
     228  /* ========================================================================= */
     229  
     230  #endif /* _TLS_H */