1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#ifndef _NXT_UNIX_THREAD_H_INCLUDED_ 8#define _NXT_UNIX_THREAD_H_INCLUDED_ 9 10 11#if (NXT_THREADS) 12 13/* 14 * Thread Specific Data 15 * 16 * The interface unifies two TSD implementations: the __thread storage 17 * class and pthread specific data. It works also in non-threaded mode. 18 * The interface is optimized for the __thread storage class and non-threaded 19 * mode, since the __thread storage is faster and is supported in modern 20 * versions of Linux, FreeBSD, Solaris, and MacOSX. Pthread specific data 21 * is considered as a fallback option. 22 * 23 * The underlining interfaces are different: pthread data must be allocated 24 * by hand and may be accessed only by using pointers whereas __thread data 25 * allocation is transparent and it is accessed directly. 26 * 27 * pthread_getspecific() is usually faster than pthread_setspecific() 28 * (much faster on MacOSX), so there is no nxt_thread_set_data() interface 29 * for this reason. It is better to store frequently alterable thread 30 * log pointer in nxt_thread_t, but not in a dedicated key. 31 */ 32 33#if (NXT_HAVE_THREAD_STORAGE_CLASS) 34 35#define \ 36nxt_thread_extern_data(type, tsd) \ 37 NXT_EXPORT extern __thread type tsd 38 39#define \ 40nxt_thread_declare_data(type, tsd) \ 41 __thread type tsd 42 43#define \ 44nxt_thread_init_data(tsd) 45 46#define \ 47nxt_thread_get_data(tsd) \ 48 &tsd 49 50 51#else /* NXT_HAVE_PTHREAD_SPECIFIC_DATA */ 52 53/* 54 * nxt_thread_get_data() is used as 55 * p = nxt_thread_get_data(tsd), 56 * but the tsd address is actually required. This could be resolved by macro 57 * #define nxt_thread_get_data(tsd) nxt_thread_get_data_addr(&tsd) 58 * or by definition nxt_thread_specific_data_t as an array. 59 * 60 * On Linux and Solaris pthread_key_t is unsigned integer. 61 * On FreeBSD, NetBSD, OpenBSD, and HP-UX pthread_key_t is integer. 62 * On MacOSX and AIX pthread_key_t is unsigned long integer. 63 * On Cygwin pthread_key_t is pointer to void. 64 */ 65 66typedef struct { 67 nxt_atomic_t key; 68 size_t size; 69} nxt_thread_specific_data_t[1]; 70 71 72#define \ 73nxt_thread_extern_data(type, tsd) \ 74 NXT_EXPORT extern nxt_thread_specific_data_t tsd 75 76#define \ 77nxt_thread_declare_data(type, tsd) \ 78 nxt_thread_specific_data_t tsd = { { (nxt_atomic_int_t) -1, sizeof(type) } } 79 80NXT_EXPORT void nxt_thread_init_data(nxt_thread_specific_data_t tsd); 81 82#define \ 83nxt_thread_get_data(tsd) \ 84 pthread_getspecific((pthread_key_t) tsd->key) 85 86#endif 87 88 89typedef void (*nxt_thread_start_t)(void *data); 90 91typedef struct { 92 nxt_thread_start_t start; 93 nxt_event_engine_t *engine; 94 nxt_work_t work; 95} nxt_thread_link_t; 96 97 98NXT_EXPORT nxt_int_t nxt_thread_create(nxt_thread_handle_t *handle, 99 nxt_thread_link_t *link); 100NXT_EXPORT nxt_thread_t *nxt_thread_init(void); 101NXT_EXPORT void nxt_thread_exit(nxt_thread_t *thr); 102NXT_EXPORT void nxt_thread_cancel(nxt_thread_handle_t handle); 103NXT_EXPORT void nxt_thread_wait(nxt_thread_handle_t handle); 104 105 106#define \ 107nxt_thread_handle() \ 108 pthread_self() 109 110 111typedef pthread_mutex_t nxt_thread_mutex_t; 112 113NXT_EXPORT nxt_int_t nxt_thread_mutex_create(nxt_thread_mutex_t *mtx); 114NXT_EXPORT void nxt_thread_mutex_destroy(nxt_thread_mutex_t *mtx); 115NXT_EXPORT nxt_int_t nxt_thread_mutex_lock(nxt_thread_mutex_t *mtx); 116NXT_EXPORT nxt_bool_t nxt_thread_mutex_trylock(nxt_thread_mutex_t *mtx); 117NXT_EXPORT nxt_int_t nxt_thread_mutex_unlock(nxt_thread_mutex_t *mtx); 118 119 120typedef pthread_cond_t nxt_thread_cond_t; 121 122NXT_EXPORT nxt_int_t nxt_thread_cond_create(nxt_thread_cond_t *cond); 123NXT_EXPORT void nxt_thread_cond_destroy(nxt_thread_cond_t *cond); 124NXT_EXPORT nxt_int_t nxt_thread_cond_signal(nxt_thread_cond_t *cond); 125NXT_EXPORT nxt_err_t nxt_thread_cond_wait(nxt_thread_cond_t *cond, 126 nxt_thread_mutex_t *mtx, nxt_nsec_t timeout); 127 128 129#else /* !(NXT_THREADS) */ 130 131#define \ 132nxt_thread_extern_data(type, tsd) \ 133 NXT_EXPORT extern type tsd 134 135#define \ 136nxt_thread_declare_data(type, tsd) \ 137 type tsd 138 139#define \ 140nxt_thread_init_data(tsd) 141 142#define \ 143nxt_thread_get_data(tsd) \ 144 &tsd 145 146#endif /* NXT_THREADS */ 147 148 149#if (NXT_HAVE_PTHREAD_YIELD) 150#define \ 151nxt_thread_yield() \ 152 pthread_yield() 153 154#elif (NXT_HAVE_PTHREAD_YIELD_NP) 155#define \ 156nxt_thread_yield() \ 157 pthread_yield_np() 158 159#else 160#define \ 161nxt_thread_yield() \ 162 nxt_sched_yield() 163 164#endif 165 166 167struct nxt_thread_s { 168 nxt_log_t *log; 169 nxt_log_t main_log; 170 171 nxt_task_t *task; 172 173 nxt_tid_t tid; 174 nxt_thread_handle_t handle; 175#if (NXT_THREADS) 176 nxt_thread_link_t *link; 177 nxt_thread_pool_t *thread_pool; 178#endif 179 180 nxt_thread_time_t time; 181 182 nxt_runtime_t *runtime; 183 nxt_event_engine_t *engine; 184 void *data; 185 186 /* 187 * Although pointer to a current fiber should be a property of 188 * engine->fibers, its placement here eliminates 2 memory accesses. 189 */ 190 nxt_fiber_t *fiber;
| 1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#ifndef _NXT_UNIX_THREAD_H_INCLUDED_ 8#define _NXT_UNIX_THREAD_H_INCLUDED_ 9 10 11#if (NXT_THREADS) 12 13/* 14 * Thread Specific Data 15 * 16 * The interface unifies two TSD implementations: the __thread storage 17 * class and pthread specific data. It works also in non-threaded mode. 18 * The interface is optimized for the __thread storage class and non-threaded 19 * mode, since the __thread storage is faster and is supported in modern 20 * versions of Linux, FreeBSD, Solaris, and MacOSX. Pthread specific data 21 * is considered as a fallback option. 22 * 23 * The underlining interfaces are different: pthread data must be allocated 24 * by hand and may be accessed only by using pointers whereas __thread data 25 * allocation is transparent and it is accessed directly. 26 * 27 * pthread_getspecific() is usually faster than pthread_setspecific() 28 * (much faster on MacOSX), so there is no nxt_thread_set_data() interface 29 * for this reason. It is better to store frequently alterable thread 30 * log pointer in nxt_thread_t, but not in a dedicated key. 31 */ 32 33#if (NXT_HAVE_THREAD_STORAGE_CLASS) 34 35#define \ 36nxt_thread_extern_data(type, tsd) \ 37 NXT_EXPORT extern __thread type tsd 38 39#define \ 40nxt_thread_declare_data(type, tsd) \ 41 __thread type tsd 42 43#define \ 44nxt_thread_init_data(tsd) 45 46#define \ 47nxt_thread_get_data(tsd) \ 48 &tsd 49 50 51#else /* NXT_HAVE_PTHREAD_SPECIFIC_DATA */ 52 53/* 54 * nxt_thread_get_data() is used as 55 * p = nxt_thread_get_data(tsd), 56 * but the tsd address is actually required. This could be resolved by macro 57 * #define nxt_thread_get_data(tsd) nxt_thread_get_data_addr(&tsd) 58 * or by definition nxt_thread_specific_data_t as an array. 59 * 60 * On Linux and Solaris pthread_key_t is unsigned integer. 61 * On FreeBSD, NetBSD, OpenBSD, and HP-UX pthread_key_t is integer. 62 * On MacOSX and AIX pthread_key_t is unsigned long integer. 63 * On Cygwin pthread_key_t is pointer to void. 64 */ 65 66typedef struct { 67 nxt_atomic_t key; 68 size_t size; 69} nxt_thread_specific_data_t[1]; 70 71 72#define \ 73nxt_thread_extern_data(type, tsd) \ 74 NXT_EXPORT extern nxt_thread_specific_data_t tsd 75 76#define \ 77nxt_thread_declare_data(type, tsd) \ 78 nxt_thread_specific_data_t tsd = { { (nxt_atomic_int_t) -1, sizeof(type) } } 79 80NXT_EXPORT void nxt_thread_init_data(nxt_thread_specific_data_t tsd); 81 82#define \ 83nxt_thread_get_data(tsd) \ 84 pthread_getspecific((pthread_key_t) tsd->key) 85 86#endif 87 88 89typedef void (*nxt_thread_start_t)(void *data); 90 91typedef struct { 92 nxt_thread_start_t start; 93 nxt_event_engine_t *engine; 94 nxt_work_t work; 95} nxt_thread_link_t; 96 97 98NXT_EXPORT nxt_int_t nxt_thread_create(nxt_thread_handle_t *handle, 99 nxt_thread_link_t *link); 100NXT_EXPORT nxt_thread_t *nxt_thread_init(void); 101NXT_EXPORT void nxt_thread_exit(nxt_thread_t *thr); 102NXT_EXPORT void nxt_thread_cancel(nxt_thread_handle_t handle); 103NXT_EXPORT void nxt_thread_wait(nxt_thread_handle_t handle); 104 105 106#define \ 107nxt_thread_handle() \ 108 pthread_self() 109 110 111typedef pthread_mutex_t nxt_thread_mutex_t; 112 113NXT_EXPORT nxt_int_t nxt_thread_mutex_create(nxt_thread_mutex_t *mtx); 114NXT_EXPORT void nxt_thread_mutex_destroy(nxt_thread_mutex_t *mtx); 115NXT_EXPORT nxt_int_t nxt_thread_mutex_lock(nxt_thread_mutex_t *mtx); 116NXT_EXPORT nxt_bool_t nxt_thread_mutex_trylock(nxt_thread_mutex_t *mtx); 117NXT_EXPORT nxt_int_t nxt_thread_mutex_unlock(nxt_thread_mutex_t *mtx); 118 119 120typedef pthread_cond_t nxt_thread_cond_t; 121 122NXT_EXPORT nxt_int_t nxt_thread_cond_create(nxt_thread_cond_t *cond); 123NXT_EXPORT void nxt_thread_cond_destroy(nxt_thread_cond_t *cond); 124NXT_EXPORT nxt_int_t nxt_thread_cond_signal(nxt_thread_cond_t *cond); 125NXT_EXPORT nxt_err_t nxt_thread_cond_wait(nxt_thread_cond_t *cond, 126 nxt_thread_mutex_t *mtx, nxt_nsec_t timeout); 127 128 129#else /* !(NXT_THREADS) */ 130 131#define \ 132nxt_thread_extern_data(type, tsd) \ 133 NXT_EXPORT extern type tsd 134 135#define \ 136nxt_thread_declare_data(type, tsd) \ 137 type tsd 138 139#define \ 140nxt_thread_init_data(tsd) 141 142#define \ 143nxt_thread_get_data(tsd) \ 144 &tsd 145 146#endif /* NXT_THREADS */ 147 148 149#if (NXT_HAVE_PTHREAD_YIELD) 150#define \ 151nxt_thread_yield() \ 152 pthread_yield() 153 154#elif (NXT_HAVE_PTHREAD_YIELD_NP) 155#define \ 156nxt_thread_yield() \ 157 pthread_yield_np() 158 159#else 160#define \ 161nxt_thread_yield() \ 162 nxt_sched_yield() 163 164#endif 165 166 167struct nxt_thread_s { 168 nxt_log_t *log; 169 nxt_log_t main_log; 170 171 nxt_task_t *task; 172 173 nxt_tid_t tid; 174 nxt_thread_handle_t handle; 175#if (NXT_THREADS) 176 nxt_thread_link_t *link; 177 nxt_thread_pool_t *thread_pool; 178#endif 179 180 nxt_thread_time_t time; 181 182 nxt_runtime_t *runtime; 183 nxt_event_engine_t *engine; 184 void *data; 185 186 /* 187 * Although pointer to a current fiber should be a property of 188 * engine->fibers, its placement here eliminates 2 memory accesses. 189 */ 190 nxt_fiber_t *fiber;
|