(root)/
glib-2.79.0/
glib/
gthreadprivate.h
       1  /* GLIB - Library of useful routines for C programming
       2   *
       3   * gthreadprivate.h - GLib internal thread system related declarations.
       4   *
       5   *  Copyright (C) 2003 Sebastian Wilhelmi
       6   *
       7   * SPDX-License-Identifier: LGPL-2.1-or-later
       8   *
       9   * This library is free software; you can redistribute it and/or
      10   * modify it under the terms of the GNU Lesser General Public
      11   * License as published by the Free Software Foundation; either
      12   * version 2.1 of the License, or (at your option) any later version.
      13   *
      14   * This library is distributed in the hope that it will be useful,
      15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17   * Lesser General Public License for more details.
      18   *
      19   * You should have received a copy of the GNU Lesser General Public License
      20   * along with this library; if not, see <http://www.gnu.org/licenses/>.
      21   */
      22  
      23  #ifndef __G_THREADPRIVATE_H__
      24  #define __G_THREADPRIVATE_H__
      25  
      26  #include "config.h"
      27  
      28  #include "deprecated/gthread.h"
      29  
      30  typedef struct _GRealThread GRealThread;
      31  struct  _GRealThread
      32  {
      33    GThread thread;
      34  
      35    gint ref_count;
      36    gboolean ours;
      37    gchar *name;
      38    gpointer retval;
      39  };
      40  
      41  /* system thread implementation (gthread-posix.c, gthread-win32.c) */
      42  
      43  #if defined(HAVE_FUTEX) || defined(HAVE_FUTEX_TIME64)
      44  #include <errno.h>
      45  #include <linux/futex.h>
      46  #include <sys/syscall.h>
      47  #include <unistd.h>
      48  
      49  #ifndef FUTEX_WAIT_PRIVATE
      50  #define FUTEX_WAIT_PRIVATE FUTEX_WAIT
      51  #define FUTEX_WAKE_PRIVATE FUTEX_WAKE
      52  #endif
      53  
      54  /* Wrapper macro to call `futex_time64` and/or `futex` with simple
      55   * parameters and without returning the return value.
      56   *
      57   * We expect futex to sometimes return EAGAIN due to the race
      58   * between the caller checking the current value and deciding to
      59   * do the futex op. To avoid splattering errno on success, we
      60   * restore the original errno if EAGAIN is seen. See also:
      61   *   https://gitlab.gnome.org/GNOME/glib/-/issues/3034
      62   *
      63   * If the `futex_time64` syscall does not exist (`ENOSYS`), we retry again
      64   * with the normal `futex` syscall. This can happen if newer kernel headers
      65   * are used than the kernel that is actually running.
      66   *
      67   * This must not be called with a timeout parameter as that differs
      68   * in size between the two syscall variants!
      69   */
      70  #if defined(__NR_futex) && defined(__NR_futex_time64)
      71  #define g_futex_simple(uaddr, futex_op, ...)                                     \
      72    G_STMT_START                                                                   \
      73    {                                                                              \
      74      int saved_errno = errno;                                                     \
      75      int res = syscall (__NR_futex_time64, uaddr, (gsize) futex_op, __VA_ARGS__); \
      76      if (res < 0 && errno == ENOSYS)                                              \
      77        {                                                                          \
      78          errno = saved_errno;                                                     \
      79          res = syscall (__NR_futex, uaddr, (gsize) futex_op, __VA_ARGS__);        \
      80        }                                                                          \
      81      if (res < 0 && errno == EAGAIN)                                              \
      82        {                                                                          \
      83          errno = saved_errno;                                                     \
      84        }                                                                          \
      85    }                                                                              \
      86    G_STMT_END
      87  #elif defined(__NR_futex_time64)
      88  #define g_futex_simple(uaddr, futex_op, ...)                                     \
      89    G_STMT_START                                                                   \
      90    {                                                                              \
      91      int saved_errno = errno;                                                     \
      92      int res = syscall (__NR_futex_time64, uaddr, (gsize) futex_op, __VA_ARGS__); \
      93      if (res < 0 && errno == EAGAIN)                                              \
      94        {                                                                          \
      95          errno = saved_errno;                                                     \
      96        }                                                                          \
      97    }                                                                              \
      98    G_STMT_END
      99  #elif defined(__NR_futex)
     100  #define g_futex_simple(uaddr, futex_op, ...)                              \
     101    G_STMT_START                                                            \
     102    {                                                                       \
     103      int saved_errno = errno;                                              \
     104      int res = syscall (__NR_futex, uaddr, (gsize) futex_op, __VA_ARGS__); \
     105      if (res < 0 && errno == EAGAIN)                                       \
     106        {                                                                   \
     107          errno = saved_errno;                                              \
     108        }                                                                   \
     109    }                                                                       \
     110    G_STMT_END
     111  #else /* !defined(__NR_futex) && !defined(__NR_futex_time64) */
     112  #error "Neither __NR_futex nor __NR_futex_time64 are defined but were found by meson"
     113  #endif /* defined(__NR_futex) && defined(__NR_futex_time64) */
     114  
     115  #endif
     116  
     117  void            g_system_thread_wait            (GRealThread  *thread);
     118  
     119  GRealThread *g_system_thread_new (GThreadFunc proxy,
     120                                    gulong stack_size,
     121                                    const char *name,
     122                                    GThreadFunc func,
     123                                    gpointer data,
     124                                    GError **error);
     125  void            g_system_thread_free            (GRealThread  *thread);
     126  
     127  G_NORETURN void g_system_thread_exit            (void);
     128  void            g_system_thread_set_name        (const gchar  *name);
     129  
     130  /* gthread.c */
     131  GThread *g_thread_new_internal (const gchar *name,
     132                                  GThreadFunc proxy,
     133                                  GThreadFunc func,
     134                                  gpointer data,
     135                                  gsize stack_size,
     136                                  GError **error);
     137  
     138  gpointer        g_thread_proxy                  (gpointer      thread);
     139  
     140  guint           g_thread_n_created              (void);
     141  
     142  gpointer        g_private_set_alloc0            (GPrivate       *key,
     143                                                   gsize           size);
     144  
     145  #endif /* __G_THREADPRIVATE_H__ */