diff options
Diffstat (limited to 'tests/glthread')
| -rw-r--r-- | tests/glthread/thread.c | 320 | ||||
| -rw-r--r-- | tests/glthread/thread.h | 229 | ||||
| -rw-r--r-- | tests/glthread/yield.h | 57 | 
3 files changed, 236 insertions, 370 deletions
| diff --git a/tests/glthread/thread.c b/tests/glthread/thread.c index 0387406b..0b923c04 100644 --- a/tests/glthread/thread.c +++ b/tests/glthread/thread.c @@ -1,27 +1,25 @@  /* Creating and controlling threads. -   Copyright (C) 2005-2018 Free Software Foundation, Inc. +   Copyright (C) 2005-2022 Free Software Foundation, Inc. -   This program is free software; you can redistribute it and/or modify -   it under the terms of the GNU General Public License as published by -   the Free Software Foundation; either version 3, or (at your option) -   any later version. +   This file is free software: you can redistribute it and/or modify +   it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. -   This program is distributed in the hope that it will be useful, +   This file is distributed in the hope that it will be useful,     but WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -   GNU General Public License for more details. +   GNU Lesser General Public License for more details. -   You should have received a copy of the GNU General Public License -   along with this program; if not, see <https://www.gnu.org/licenses/>.  */ +   You should have received a copy of the GNU Lesser General Public License +   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */  /* Written by Bruno Haible <bruno@clisp.org>, 2005. -   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, -   gthr-win32.h.  */ +   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h.  */  #include <config.h>  /* Specification.  */ -# define _GLTHREAD_THREAD_INLINE _GL_EXTERN_INLINE  #include "glthread/thread.h"  #include <stdlib.h> @@ -29,204 +27,190 @@  /* ========================================================================= */ -#if USE_POSIX_THREADS +#if USE_ISOC_THREADS -#include <pthread.h> - -#if defined PTW32_VERSION || defined __MVS__ - -const gl_thread_t gl_null_thread /* = { .p = NULL } */; - -#endif - -#endif - -/* ========================================================================= */ - -#if USE_WINDOWS_THREADS - -#include <process.h> - -/* -------------------------- gl_thread_t datatype -------------------------- */ +struct thrd_with_exitvalue +{ +  thrd_t volatile tid; +  void * volatile exitvalue; +}; -/* The Thread-Local Storage (TLS) key that allows to access each thread's -   'struct gl_thread_struct *' pointer.  */ -static DWORD self_key = (DWORD)-1; +/* The Thread-Specific Storage (TSS) key that allows to access each thread's +   'struct thrd_with_exitvalue *' pointer.  */ +static tss_t thrd_with_exitvalue_key; -/* Initializes self_key.  This function must only be called once.  */ +/* Initializes thrd_with_exitvalue_key. +   This function must only be called once.  */  static void -do_init_self_key (void) +do_init_thrd_with_exitvalue_key (void)  { -  self_key = TlsAlloc (); -  /* If this fails, we're hosed.  */ -  if (self_key == (DWORD)-1) +  if (tss_create (&thrd_with_exitvalue_key, NULL) != thrd_success)      abort ();  } -/* Initializes self_key.  */ +/* Initializes thrd_with_exitvalue_key.  */  static void -init_self_key (void) +init_thrd_with_exitvalue_key (void)  { -  gl_once_define(static, once) -  gl_once (once, do_init_self_key); +  static once_flag once = ONCE_FLAG_INIT; +  call_once (&once, do_init_thrd_with_exitvalue_key);  } -/* This structure contains information about a thread. -   It is stored in TLS under key self_key.  */ -struct gl_thread_struct -{ -  /* Fields for managing the handle.  */ -  HANDLE volatile handle; -  CRITICAL_SECTION handle_lock; -  /* Fields for managing the exit value.  */ -  void * volatile result; -  /* Fields for managing the thread start.  */ -  void * (*func) (void *); -  void *arg; -}; +typedef union +        { +          struct thrd_with_exitvalue t; +          struct +          { +            thrd_t tid; /* reserve memory for t.tid */ +            void *(*mainfunc) (void *); +            void *arg; +          } a; +        } +        main_arg_t; -/* Return a real HANDLE object for the current thread.  */ -static HANDLE -get_current_thread_handle (void) +static int +thrd_main_func (void *pmarg)  { -  HANDLE this_handle; +  /* Unpack the object that combines mainfunc and arg.  */ +  main_arg_t *main_arg = (main_arg_t *) pmarg; +  void *(*mainfunc) (void *) = main_arg->a.mainfunc; +  void *arg = main_arg->a.arg; -  /* GetCurrentThread() returns a pseudo-handle, i.e. only a symbolic -     identifier, not a real handle.  */ -  if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), -                        GetCurrentProcess (), &this_handle, -                        0, FALSE, DUPLICATE_SAME_ACCESS)) +  if (tss_set (thrd_with_exitvalue_key, &main_arg->t) != thrd_success)      abort (); -  return this_handle; -} - -gl_thread_t -gl_thread_self_func (void) -{ -  gl_thread_t thread; - -  if (self_key == (DWORD)-1) -    init_self_key (); -  thread = TlsGetValue (self_key); -  if (thread == NULL) -    { -      /* This happens only in threads that have not been created through -         glthread_create(), such as the main thread.  */ -      for (;;) -        { -          thread = -            (struct gl_thread_struct *) -            malloc (sizeof (struct gl_thread_struct)); -          if (thread != NULL) -            break; -          /* Memory allocation failed.  There is not much we can do.  Have to -             busy-loop, waiting for the availability of memory.  */ -          Sleep (1); -        } - -      thread->handle = get_current_thread_handle (); -      InitializeCriticalSection (&thread->handle_lock); -      thread->result = NULL; /* just to be deterministic */ -      TlsSetValue (self_key, thread); -    } -  return thread; -} -/* The main function of a freshly creating thread.  It's a wrapper around -   the FUNC and ARG arguments passed to glthread_create_func.  */ -static unsigned int WINAPI -wrapper_func (void *varg) -{ -  struct gl_thread_struct *thread = (struct gl_thread_struct *)varg; - -  EnterCriticalSection (&thread->handle_lock); -  /* Create a new handle for the thread only if the parent thread did not yet -     fill in the handle.  */ -  if (thread->handle == NULL) -    thread->handle = get_current_thread_handle (); -  LeaveCriticalSection (&thread->handle_lock); - -  if (self_key == (DWORD)-1) -    init_self_key (); -  TlsSetValue (self_key, thread); - -  /* Run the thread.  Store the exit value if the thread was not terminated -     otherwise.  */ -  thread->result = thread->func (thread->arg); -  return 0; +  /* Execute mainfunc, with arg as argument.  */ +  { +    void *exitvalue = mainfunc (arg); +    /* Store the exitvalue, for use by glthread_join().  */ +    main_arg->t.exitvalue = exitvalue; +    return 0; +  }  }  int -glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg) +glthread_create (gl_thread_t *threadp, void *(*mainfunc) (void *), void *arg)  { -  struct gl_thread_struct *thread = -    (struct gl_thread_struct *) malloc (sizeof (struct gl_thread_struct)); -  if (thread == NULL) -    return ENOMEM; -  thread->handle = NULL; -  InitializeCriticalSection (&thread->handle_lock); -  thread->result = NULL; /* just to be deterministic */ -  thread->func = func; -  thread->arg = arg; - +  init_thrd_with_exitvalue_key ();    { -    unsigned int thread_id; -    HANDLE thread_handle; - -    thread_handle = (HANDLE) -      _beginthreadex (NULL, 100000, wrapper_func, thread, 0, &thread_id); -      /* calls CreateThread with the same arguments */ -    if (thread_handle == NULL) +    /* Combine mainfunc and arg in a single object. +       A stack-allocated object does not work, because it would be out of +       existence when thrd_create returns before thrd_main_func is +       entered.  So, allocate it in the heap.  */ +    main_arg_t *main_arg = (main_arg_t *) malloc (sizeof (main_arg_t)); +    if (main_arg == NULL) +      return ENOMEM; +    main_arg->a.mainfunc = mainfunc; +    main_arg->a.arg = arg; +    switch (thrd_create ((thrd_t *) &main_arg->t.tid, thrd_main_func, main_arg))        { -        DeleteCriticalSection (&thread->handle_lock); -        free (thread); +      case thrd_success: +        break; +      case thrd_nomem: +        free (main_arg); +        return ENOMEM; +      default: +        free (main_arg);          return EAGAIN;        } - -    EnterCriticalSection (&thread->handle_lock); -    if (thread->handle == NULL) -      thread->handle = thread_handle; -    else -      /* thread->handle was already set by the thread itself.  */ -      CloseHandle (thread_handle); -    LeaveCriticalSection (&thread->handle_lock); - -    *threadp = thread; +    *threadp = &main_arg->t;      return 0;    }  } +gl_thread_t +gl_thread_self (void) +{ +  init_thrd_with_exitvalue_key (); +  { +    gl_thread_t thread = +      (struct thrd_with_exitvalue *) tss_get (thrd_with_exitvalue_key); +    if (thread == NULL) +      { +        /* This happens only in threads that have not been created through +           glthread_create(), such as the main thread.  */ +        for (;;) +          { +            thread = +              (struct thrd_with_exitvalue *) +              malloc (sizeof (struct thrd_with_exitvalue)); +            if (thread != NULL) +              break; +            /* Memory allocation failed.  There is not much we can do.  Have to +               busy-loop, waiting for the availability of memory.  */ +            { +              struct timespec ts; +              ts.tv_sec = 1; +              ts.tv_nsec = 0; +              thrd_sleep (&ts, NULL); +            } +          } +        thread->tid = thrd_current (); +        thread->exitvalue = NULL; /* just to be deterministic */ +        if (tss_set (thrd_with_exitvalue_key, thread) != thrd_success) +          abort (); +      } +    return thread; +  } +} +  int -glthread_join_func (gl_thread_t thread, void **retvalp) +glthread_join (gl_thread_t thread, void **return_value_ptr)  { -  if (thread == NULL) -    return EINVAL; +  /* On Solaris 11.4, thrd_join crashes when the second argument we pass is +     NULL.  */ +  int dummy;    if (thread == gl_thread_self ()) -    return EDEADLK; - -  if (WaitForSingleObject (thread->handle, INFINITE) == WAIT_FAILED)      return EINVAL; - -  if (retvalp != NULL) -    *retvalp = thread->result; - -  DeleteCriticalSection (&thread->handle_lock); -  CloseHandle (thread->handle); +  if (thrd_join (thread->tid, &dummy) != thrd_success) +    return EINVAL; +  if (return_value_ptr != NULL) +    *return_value_ptr = thread->exitvalue;    free (thread); -    return 0;  } -int -gl_thread_exit_func (void *retval) +_Noreturn void +gl_thread_exit (void *return_value)  {    gl_thread_t thread = gl_thread_self (); -  thread->result = retval; -  _endthreadex (0); /* calls ExitThread (0) */ -  abort (); +  thread->exitvalue = return_value; +  thrd_exit (0);  }  #endif  /* ========================================================================= */ + +#if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS + +#include <pthread.h> + +#if defined PTW32_VERSION || defined __MVS__ + +const gl_thread_t gl_null_thread /* = { .p = NULL } */; + +#endif + +#endif + +/* ========================================================================= */ + +#if USE_WINDOWS_THREADS + +#endif + +/* ========================================================================= */ + +gl_thread_t +gl_thread_create (void *(*func) (void *arg), void *arg) +{ +  gl_thread_t thread; +  int ret; + +  ret = glthread_create (&thread, func, arg); +  if (ret != 0) +    abort (); +  return thread; +} diff --git a/tests/glthread/thread.h b/tests/glthread/thread.h index 1e266bd6..6d98f2d6 100644 --- a/tests/glthread/thread.h +++ b/tests/glthread/thread.h @@ -1,22 +1,21 @@  /* Creating and controlling threads. -   Copyright (C) 2005-2018 Free Software Foundation, Inc. +   Copyright (C) 2005-2022 Free Software Foundation, Inc. -   This program is free software; you can redistribute it and/or modify -   it under the terms of the GNU General Public License as published by -   the Free Software Foundation; either version 3, or (at your option) -   any later version. +   This file is free software: you can redistribute it and/or modify +   it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. -   This program is distributed in the hope that it will be useful, +   This file is distributed in the hope that it will be useful,     but WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -   GNU General Public License for more details. +   GNU Lesser General Public License for more details. -   You should have received a copy of the GNU General Public License -   along with this program; if not, see <https://www.gnu.org/licenses/>.  */ +   You should have received a copy of the GNU Lesser General Public License +   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */  /* Written by Bruno Haible <bruno@clisp.org>, 2005. -   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, -   gthr-win32.h.  */ +   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h.  */  /* This file contains primitives for creating and controlling threads. @@ -74,17 +73,53 @@  #include <errno.h>  #include <stdlib.h> -#ifndef _GL_INLINE_HEADER_BEGIN - #error "Please include config.h first." +#if !defined c11_threads_in_use +# if HAVE_THREADS_H && USE_POSIX_THREADS_FROM_LIBC +#  define c11_threads_in_use() 1 +# elif HAVE_THREADS_H && USE_POSIX_THREADS_WEAK +#  include <threads.h> +#  pragma weak thrd_exit +#  define c11_threads_in_use() (thrd_exit != NULL) +# else +#  define c11_threads_in_use() 0 +# endif  #endif -_GL_INLINE_HEADER_BEGIN -#ifndef _GLTHREAD_THREAD_INLINE -# define _GLTHREAD_THREAD_INLINE _GL_INLINE + +/* ========================================================================= */ + +#if USE_ISOC_THREADS + +/* Use the ISO C threads library.  */ + +# include <threads.h> + +# ifdef __cplusplus +extern "C" { +# endif + +/* -------------------------- gl_thread_t datatype -------------------------- */ + +typedef struct thrd_with_exitvalue *gl_thread_t; +extern int glthread_create (gl_thread_t *threadp, +                            void *(*func) (void *), void *arg); +# define glthread_sigmask(HOW, SET, OSET) \ +    pthread_sigmask (HOW, SET, OSET) +extern int glthread_join (gl_thread_t thread, void **return_value_ptr); +extern gl_thread_t gl_thread_self (void); +# define gl_thread_self_pointer() \ +    (void *) gl_thread_self () +extern _Noreturn void gl_thread_exit (void *return_value); +# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 + +# ifdef __cplusplus +} +# endif +  #endif  /* ========================================================================= */ -#if USE_POSIX_THREADS +#if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS  /* Use the POSIX threads library.  */ @@ -133,8 +168,6 @@ extern int glthread_in_use (void);     call to foo(...) in the same function.  To avoid this, we test the     address of a function in libpthread that we don't use.  */ -#  pragma weak pthread_create -  #  ifndef pthread_sigmask /* Do not declare rpl_pthread_sigmask weak.  */  #   pragma weak pthread_sigmask  #  endif @@ -150,7 +183,8 @@ extern int glthread_in_use (void);  #  if !PTHREAD_IN_USE_DETECTION_HARD  #   pragma weak pthread_mutexattr_gettype -#   define pthread_in_use() (pthread_mutexattr_gettype != NULL) +#   define pthread_in_use() \ +      (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())  #  endif  # else @@ -192,12 +226,12 @@ extern const gl_thread_t gl_null_thread;  extern const gl_thread_t gl_null_thread;  # else  #  define gl_thread_self() \ -     (pthread_in_use () ? pthread_self () : (pthread_t) NULL) +     (pthread_in_use () ? pthread_self () : (pthread_t) 0)  #  define gl_thread_self_pointer() \       (pthread_in_use () ? (void *) pthread_self () : NULL)  # endif  # define gl_thread_exit(RETVAL) \ -    (pthread_in_use () ? pthread_exit (RETVAL) : 0) +    (void) (pthread_in_use () ? (pthread_exit (RETVAL), 0) : 0)  # if HAVE_PTHREAD_ATFORK  #  define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) \ @@ -214,152 +248,33 @@ extern const gl_thread_t gl_null_thread;  /* ========================================================================= */ -#if USE_PTH_THREADS - -/* Use the GNU Pth threads library.  */ - -# include <pth.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# if USE_PTH_THREADS_WEAK - -/* Use weak references to the GNU Pth threads library.  */ - -#  pragma weak pth_init -#  pragma weak pth_spawn -#  pragma weak pth_sigmask -#  pragma weak pth_join -#  pragma weak pth_self -#  pragma weak pth_exit - -#  pragma weak pth_cancel -#  define pth_in_use() (pth_cancel != NULL) - -# else - -#  define pth_in_use() 1 - -# endif -/* -------------------------- gl_thread_t datatype -------------------------- */ - -typedef pth_t gl_thread_t; -# define glthread_create(THREADP, FUNC, ARG) \ -    (pth_in_use () ? (pth_init (), ((*(THREADP) = pth_spawn (NULL, FUNC, ARG)) ? 0 : errno)) : 0) -# define glthread_sigmask(HOW, SET, OSET) \ -    (pth_in_use () ? (pth_init (), (pth_sigmask (HOW, SET, OSET) ? 0 : errno)) : 0) -# define glthread_join(THREAD, RETVALP) \ -    (pth_in_use () ? (pth_init (), (pth_join (THREAD, RETVALP) ? 0 : errno)) : 0) -# define gl_thread_self() \ -    (pth_in_use () ? (pth_init (), (void *) pth_self ()) : NULL) -# define gl_thread_self_pointer() \ -    gl_thread_self () -# define gl_thread_exit(RETVAL) \ -    (pth_in_use () ? (pth_init (), pth_exit (RETVAL)) : 0) -# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_SOLARIS_THREADS - -/* Use the old Solaris threads library.  */ - -# include <thread.h> -# include <synch.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# if USE_SOLARIS_THREADS_WEAK - -/* Use weak references to the old Solaris threads library.  */ - -#  pragma weak thr_create -#  pragma weak thr_join -#  pragma weak thr_self -#  pragma weak thr_exit - -#  pragma weak thr_suspend -#  define thread_in_use() (thr_suspend != NULL) - -# else - -#  define thread_in_use() 1 - -# endif - -/* -------------------------- gl_thread_t datatype -------------------------- */ - -typedef thread_t gl_thread_t; -# define glthread_create(THREADP, FUNC, ARG) \ -    (thread_in_use () ? thr_create (NULL, 0, FUNC, ARG, 0, THREADP) : 0) -# define glthread_sigmask(HOW, SET, OSET) \ -    (thread_in_use () ? sigprocmask (HOW, SET, OSET) : 0) -# define glthread_join(THREAD, RETVALP) \ -    (thread_in_use () ? thr_join (THREAD, NULL, RETVALP) : 0) -# define gl_thread_self() \ -    (thread_in_use () ? (void *) thr_self () : NULL) -# define gl_thread_self_pointer() \ -    gl_thread_self () -# define gl_thread_exit(RETVAL) \ -    (thread_in_use () ? thr_exit (RETVAL) : 0) -# define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ -  #if USE_WINDOWS_THREADS  # define WIN32_LEAN_AND_MEAN  /* avoid including junk */  # include <windows.h> +# include "windows-thread.h" +  # ifdef __cplusplus  extern "C" {  # endif  /* -------------------------- gl_thread_t datatype -------------------------- */ -/* The gl_thread_t is a pointer to a structure in memory. -   Why not the thread handle?  If it were the thread handle, it would be hard -   to implement gl_thread_self() (since GetCurrentThread () returns a pseudo- -   handle, DuplicateHandle (GetCurrentThread ()) returns a handle that must be -   closed afterwards, and there is no function for quickly retrieving a thread -   handle from its id). -   Why not the thread id?  I tried it.  It did not work: Sometimes ids appeared -   that did not belong to running threads, and glthread_join failed with ESRCH. - */ -typedef struct gl_thread_struct *gl_thread_t; +typedef glwthread_thread_t gl_thread_t;  # define glthread_create(THREADP, FUNC, ARG) \ -    glthread_create_func (THREADP, FUNC, ARG) +    glwthread_thread_create (THREADP, 0, FUNC, ARG)  # define glthread_sigmask(HOW, SET, OSET) \      /* unsupported */ 0  # define glthread_join(THREAD, RETVALP) \ -    glthread_join_func (THREAD, RETVALP) +    glwthread_thread_join (THREAD, RETVALP)  # define gl_thread_self() \ -    gl_thread_self_func () +    glwthread_thread_self ()  # define gl_thread_self_pointer() \      gl_thread_self ()  # define gl_thread_exit(RETVAL) \ -    gl_thread_exit_func (RETVAL) +    glwthread_thread_exit (RETVAL)  # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0 -extern int glthread_create_func (gl_thread_t *threadp, void * (*func) (void *), void *arg); -extern int glthread_join_func (gl_thread_t thread, void **retvalp); -extern gl_thread_t gl_thread_self_func (void); -extern int gl_thread_exit_func (void *retval);  # ifdef __cplusplus  } @@ -369,7 +284,7 @@ extern int gl_thread_exit_func (void *retval);  /* ========================================================================= */ -#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS) +#if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)  /* Provide dummy implementation if threads are not supported.  */ @@ -380,7 +295,7 @@ typedef int gl_thread_t;  # define gl_thread_self() 0  # define gl_thread_self_pointer() \      ((void *) gl_thread_self ()) -# define gl_thread_exit(RETVAL) 0 +# define gl_thread_exit(RETVAL) (void)0  # define glthread_atfork(PREPARE_FUNC, PARENT_FUNC, CHILD_FUNC) 0  #endif @@ -393,17 +308,7 @@ typedef int gl_thread_t;  extern "C" {  #endif -_GLTHREAD_THREAD_INLINE gl_thread_t -gl_thread_create (void *(*func) (void *arg), void *arg) -{ -  gl_thread_t thread; -  int ret; - -  ret = glthread_create (&thread, func, arg); -  if (ret != 0) -    abort (); -  return thread; -} +extern gl_thread_t gl_thread_create (void *(*func) (void *arg), void *arg);  #define gl_thread_sigmask(HOW, SET, OSET)     \     do                                         \       {                                        \ @@ -430,6 +335,4 @@ gl_thread_create (void *(*func) (void *arg), void *arg)  }  #endif -_GL_INLINE_HEADER_END -  #endif /* _GLTHREAD_THREAD_H */ diff --git a/tests/glthread/yield.h b/tests/glthread/yield.h index 4bb3ed48..f74267ea 100644 --- a/tests/glthread/yield.h +++ b/tests/glthread/yield.h @@ -1,18 +1,18 @@  /* Yielding the processor to other threads and processes. -   Copyright (C) 2005-2018 Free Software Foundation, Inc. +   Copyright (C) 2005-2022 Free Software Foundation, Inc. -   This program is free software; you can redistribute it and/or modify -   it under the terms of the GNU General Public License as published by -   the Free Software Foundation; either version 3, or (at your option) -   any later version. +   This file is free software: you can redistribute it and/or modify +   it under the terms of the GNU Lesser General Public License as +   published by the Free Software Foundation; either version 2.1 of the +   License, or (at your option) any later version. -   This program is distributed in the hope that it will be useful, +   This file is distributed in the hope that it will be useful,     but WITHOUT ANY WARRANTY; without even the implied warranty of     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -   GNU General Public License for more details. +   GNU Lesser General Public License for more details. -   You should have received a copy of the GNU General Public License -   along with this program; if not, see <https://www.gnu.org/licenses/>.  */ +   You should have received a copy of the GNU Lesser General Public License +   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */  /* This file contains a primitive for yielding the processor to other threads.       extern void gl_thread_yield (void); @@ -25,18 +25,18 @@  /* ========================================================================= */ -#if USE_POSIX_THREADS +#if USE_ISOC_THREADS || USE_ISOC_AND_POSIX_THREADS -/* Use the POSIX threads library.  */ +/* Use the ISO C threads library.  */ -# include <sched.h> +# include <threads.h>  # ifdef __cplusplus  extern "C" {  # endif  # define gl_thread_yield() \ -    sched_yield () +    thrd_yield ()  # ifdef __cplusplus  } @@ -46,39 +46,18 @@ extern "C" {  /* ========================================================================= */ -#if USE_PTH_THREADS - -/* Use the GNU Pth threads library.  */ - -# include <pth.h> - -# ifdef __cplusplus -extern "C" { -# endif - -# define gl_thread_yield() \ -    pth_yield (NULL) - -# ifdef __cplusplus -} -# endif - -#endif - -/* ========================================================================= */ - -#if USE_SOLARIS_THREADS +#if USE_POSIX_THREADS -/* Use the old Solaris threads library.  */ +/* Use the POSIX threads library.  */ -# include <thread.h> +# include <sched.h>  # ifdef __cplusplus  extern "C" {  # endif  # define gl_thread_yield() \ -    thr_yield () +    sched_yield ()  # ifdef __cplusplus  } @@ -108,7 +87,7 @@ extern "C" {  /* ========================================================================= */ -#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WINDOWS_THREADS) +#if !(USE_ISOC_THREADS || USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS || USE_WINDOWS_THREADS)  /* Provide dummy implementation if threads are not supported.  */ | 
