Ruby  3.1.4p223 (2023-03-30 revision HEAD)
thread_pthread.h
1 #ifndef RUBY_THREAD_PTHREAD_H
2 #define RUBY_THREAD_PTHREAD_H
3 /**********************************************************************
4 
5  thread_pthread.h -
6 
7  $Author$
8 
9  Copyright (C) 2004-2007 Koichi Sasada
10 
11 **********************************************************************/
12 
13 #ifdef HAVE_PTHREAD_NP_H
14 #include <pthread_np.h>
15 #endif
16 
17 #define RB_NATIVETHREAD_LOCK_INIT PTHREAD_MUTEX_INITIALIZER
18 #define RB_NATIVETHREAD_COND_INIT PTHREAD_COND_INITIALIZER
19 
20 typedef struct native_thread_data_struct {
21  union {
22  struct list_node ubf;
23  struct list_node gvl;
24  } node;
25 #if defined(__GLIBC__) || defined(__FreeBSD__)
26  union
27 #else
28  /*
29  * assume the platform condvars are badly implemented and have a
30  * "memory" of which mutex they're associated with
31  */
32  struct
33 #endif
34  {
35  rb_nativethread_cond_t intr; /* th->interrupt_lock */
36  rb_nativethread_cond_t gvlq; /* vm->gvl.lock */
37  } cond;
39 
40 #undef except
41 #undef try
42 #undef leave
43 #undef finally
44 
45 typedef struct rb_global_vm_lock_struct {
46  /* fast path */
47  const struct rb_thread_struct *owner;
48  rb_nativethread_lock_t lock; /* AKA vm->gvl.lock */
49 
50  /*
51  * slow path, protected by vm->gvl.lock
52  * - @waitq - FIFO queue of threads waiting for GVL
53  * - @timer - it handles timeslices for @owner. It is any one thread
54  * in @waitq, there is no @timer if @waitq is empty, but always
55  * a @timer if @waitq has entries
56  * - @timer_err tracks timeslice limit, the timeslice only resets
57  * when pthread_cond_timedwait returns ETIMEDOUT, so frequent
58  * switching between contended/uncontended GVL won't reset the
59  * timer.
60  */
61  struct list_head waitq; /* <=> native_thread_data_t.node.ubf */
62  const struct rb_thread_struct *timer;
63  int timer_err;
64 
65  /* yield */
66  rb_nativethread_cond_t switch_cond;
67  rb_nativethread_cond_t switch_wait_cond;
68  int need_yield;
69  int wait_yield;
71 
72 
73 #if __STDC_VERSION__ >= 201112
74  #define RB_THREAD_LOCAL_SPECIFIER _Thread_local
75 #elif defined(__GNUC__)
76  /* note that ICC (linux) and Clang are covered by __GNUC__ */
77  #define RB_THREAD_LOCAL_SPECIFIER __thread
78 #else
79 
80 typedef pthread_key_t native_tls_key_t;
81 
82 static inline void *
83 native_tls_get(native_tls_key_t key)
84 {
85  void *ptr = pthread_getspecific(key);
86  if (UNLIKELY(ptr == NULL)) {
87  rb_bug("pthread_getspecific returns NULL");
88  }
89  return ptr;
90 }
91 
92 static inline void
93 native_tls_set(native_tls_key_t key, void *ptr)
94 {
95  if (UNLIKELY(pthread_setspecific(key, ptr) != 0)) {
96  rb_bug("pthread_setspecific error");
97  }
98 }
99 #endif
100 
101 RUBY_SYMBOL_EXPORT_BEGIN
102 #ifdef RB_THREAD_LOCAL_SPECIFIER
103  #ifdef __APPLE__
104  // on Darwin, TLS can not be accessed across .so
105  struct rb_execution_context_struct *rb_current_ec(void);
106  void rb_current_ec_set(struct rb_execution_context_struct *);
107  #else
108  RUBY_EXTERN RB_THREAD_LOCAL_SPECIFIER struct rb_execution_context_struct *ruby_current_ec;
109  #endif
110 #else
111  RUBY_EXTERN native_tls_key_t ruby_current_ec_key;
112 #endif
113 RUBY_SYMBOL_EXPORT_END
114 
115 #endif /* RUBY_THREAD_PTHREAD_H */
#define RUBY_EXTERN
Declaration of externally visible global variables.
Definition: dllexport.h:47
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition: error.c:802