diff options
Diffstat (limited to '')
-rw-r--r-- | src/nxt_thread.h | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/src/nxt_thread.h b/src/nxt_thread.h new file mode 100644 index 00000000..ebff808f --- /dev/null +++ b/src/nxt_thread.h @@ -0,0 +1,192 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_UNIX_THREAD_H_INCLUDED_ +#define _NXT_UNIX_THREAD_H_INCLUDED_ + + +#if (NXT_THREADS) + +/* + * Thread Specific Data + * + * The interface unifies two TSD implementations: the __thread storage + * class and pthread specific data. It works also in non-threaded mode. + * The interface is optimized for the __thread storage class and non-threaded + * mode, since the __thread storage is faster and is supported in modern + * versions of Linux, FreeBSD, Solaris, and MacOSX. Pthread specific data + * is considered as a fallback option. + * + * The underlining interfaces are different: pthread data must be allocated + * by hand and may be accessed only by using pointers whereas __thread data + * allocation is transparent and it is accessed directly. + * + * pthread_getspecific() is usually faster than pthread_setspecific() + * (much faster on MacOSX), so there is no nxt_thread_set_data() interface + * for this reason. It is better to store frequently alterable thread + * log pointer in nxt_thread_t, but not in a dedicated key. + */ + +#if (NXT_HAVE_THREAD_STORAGE_CLASS) + +#define \ +nxt_thread_extern_data(type, tsd) \ + NXT_EXPORT extern __thread type tsd + +#define \ +nxt_thread_declare_data(type, tsd) \ + __thread type tsd + +#define \ +nxt_thread_init_data(tsd) + +#define \ +nxt_thread_get_data(tsd) \ + &tsd + + +#else /* NXT_HAVE_PTHREAD_SPECIFIC_DATA */ + +/* + * nxt_thread_get_data() is used as + * p = nxt_thread_get_data(tsd), + * but the tsd address is actually required. This could be resolved by macro + * #define nxt_thread_get_data(tsd) nxt_thread_get_data_addr(&tsd) + * or by definition nxt_thread_specific_data_t as an array. + * + * On Linux and Solaris pthread_key_t is unsigned integer. + * On FreeBSD, NetBSD, OpenBSD, and HP-UX pthread_key_t is integer. + * On MacOSX and AIX pthread_key_t is unsigned long integer. + * On Cygwin pthread_key_t is pointer to void. + */ + +typedef struct { + nxt_atomic_t key; + size_t size; +} nxt_thread_specific_data_t[1]; + + +#define \ +nxt_thread_extern_data(type, tsd) \ + NXT_EXPORT extern nxt_thread_specific_data_t tsd + +#define \ +nxt_thread_declare_data(type, tsd) \ + nxt_thread_specific_data_t tsd = { { (nxt_atomic_int_t) -1, sizeof(type) } } + +NXT_EXPORT void nxt_thread_init_data(nxt_thread_specific_data_t tsd); + +#define \ +nxt_thread_get_data(tsd) \ + pthread_getspecific((pthread_key_t) tsd->key) + +#endif + + +typedef void (*nxt_thread_start_t)(void *data); + +typedef struct { + nxt_thread_start_t start; + void *data; + nxt_event_engine_t *engine; + nxt_work_handler_t exit; +} nxt_thread_link_t; + + +NXT_EXPORT nxt_int_t nxt_thread_create(nxt_thread_handle_t *handle, + nxt_thread_link_t *link); +NXT_EXPORT nxt_thread_t *nxt_thread_init(void); +NXT_EXPORT void nxt_thread_exit(nxt_thread_t *thr); +NXT_EXPORT void nxt_thread_cancel(nxt_thread_handle_t handle); +NXT_EXPORT void nxt_thread_wait(nxt_thread_handle_t handle); + + +#define \ +nxt_thread_handle() \ + pthread_self() + + +typedef pthread_mutex_t nxt_thread_mutex_t; + +NXT_EXPORT nxt_int_t nxt_thread_mutex_create(nxt_thread_mutex_t *mtx); +NXT_EXPORT void nxt_thread_mutex_destroy(nxt_thread_mutex_t *mtx); +NXT_EXPORT nxt_int_t nxt_thread_mutex_lock(nxt_thread_mutex_t *mtx); +NXT_EXPORT nxt_bool_t nxt_thread_mutex_trylock(nxt_thread_mutex_t *mtx); +NXT_EXPORT nxt_int_t nxt_thread_mutex_unlock(nxt_thread_mutex_t *mtx); + + +typedef pthread_cond_t nxt_thread_cond_t; + +NXT_EXPORT nxt_int_t nxt_thread_cond_create(nxt_thread_cond_t *cond); +NXT_EXPORT void nxt_thread_cond_destroy(nxt_thread_cond_t *cond); +NXT_EXPORT nxt_int_t nxt_thread_cond_signal(nxt_thread_cond_t *cond); +NXT_EXPORT nxt_err_t nxt_thread_cond_wait(nxt_thread_cond_t *cond, + nxt_thread_mutex_t *mtx, nxt_nsec_t timeout); + + +#else /* !(NXT_THREADS) */ + +#define \ +nxt_thread_extern_data(type, tsd) \ + NXT_EXPORT extern type tsd + +#define \ +nxt_thread_declare_data(type, tsd) \ + type tsd + +#define \ +nxt_thread_init_data(tsd) + +#define \ +nxt_thread_get_data(tsd) \ + &tsd + +#endif /* NXT_THREADS */ + + +#if (NXT_HAVE_PTHREAD_YIELD) +#define \ +nxt_thread_yield() \ + pthread_yield() + +#elif (NXT_HAVE_PTHREAD_YIELD_NP) +#define \ +nxt_thread_yield() \ + pthread_yield_np() + +#else +#define \ +nxt_thread_yield() \ + nxt_sched_yield() + +#endif + + +struct nxt_thread_s { + nxt_log_t *log; + nxt_log_t main_log; + + nxt_tid_t tid; + nxt_thread_handle_t handle; +#if (NXT_THREADS) + nxt_thread_link_t *link; + nxt_thread_pool_t *thread_pool; +#endif + + nxt_thread_time_t time; + + nxt_event_engine_t *engine; + nxt_thread_work_queue_t work_queue; + + /* + * Although pointer to a current fiber should be a property of + * engine->fibers, its placement here eliminates 2 memory accesses. + */ + nxt_fiber_t *fiber; +}; + + +#endif /* _NXT_UNIX_THREAD_H_INCLUDED_ */ |