10Sigor@sysoev.ru 20Sigor@sysoev.ru /* 30Sigor@sysoev.ru * Copyright (C) Igor Sysoev 40Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 50Sigor@sysoev.ru */ 60Sigor@sysoev.ru 70Sigor@sysoev.ru #ifndef _NXT_UNIX_THREAD_H_INCLUDED_ 80Sigor@sysoev.ru #define _NXT_UNIX_THREAD_H_INCLUDED_ 90Sigor@sysoev.ru 100Sigor@sysoev.ru 110Sigor@sysoev.ru /* 120Sigor@sysoev.ru * Thread Specific Data 130Sigor@sysoev.ru * 140Sigor@sysoev.ru * The interface unifies two TSD implementations: the __thread storage 150Sigor@sysoev.ru * class and pthread specific data. It works also in non-threaded mode. 160Sigor@sysoev.ru * The interface is optimized for the __thread storage class and non-threaded 170Sigor@sysoev.ru * mode, since the __thread storage is faster and is supported in modern 180Sigor@sysoev.ru * versions of Linux, FreeBSD, Solaris, and MacOSX. Pthread specific data 190Sigor@sysoev.ru * is considered as a fallback option. 200Sigor@sysoev.ru * 210Sigor@sysoev.ru * The underlining interfaces are different: pthread data must be allocated 220Sigor@sysoev.ru * by hand and may be accessed only by using pointers whereas __thread data 230Sigor@sysoev.ru * allocation is transparent and it is accessed directly. 240Sigor@sysoev.ru * 250Sigor@sysoev.ru * pthread_getspecific() is usually faster than pthread_setspecific() 260Sigor@sysoev.ru * (much faster on MacOSX), so there is no nxt_thread_set_data() interface 270Sigor@sysoev.ru * for this reason. It is better to store frequently alterable thread 280Sigor@sysoev.ru * log pointer in nxt_thread_t, but not in a dedicated key. 290Sigor@sysoev.ru */ 300Sigor@sysoev.ru 310Sigor@sysoev.ru #if (NXT_HAVE_THREAD_STORAGE_CLASS) 320Sigor@sysoev.ru 33*2084Salx.manpages@gmail.com #define nxt_thread_extern_data(type, tsd) \ 340Sigor@sysoev.ru NXT_EXPORT extern __thread type tsd 350Sigor@sysoev.ru 36*2084Salx.manpages@gmail.com #define nxt_thread_declare_data(type, tsd) \ 370Sigor@sysoev.ru __thread type tsd 380Sigor@sysoev.ru 39*2084Salx.manpages@gmail.com #define nxt_thread_init_data(tsd) 400Sigor@sysoev.ru 41*2084Salx.manpages@gmail.com #define nxt_thread_get_data(tsd) \ 420Sigor@sysoev.ru &tsd 430Sigor@sysoev.ru 440Sigor@sysoev.ru 450Sigor@sysoev.ru #else /* NXT_HAVE_PTHREAD_SPECIFIC_DATA */ 460Sigor@sysoev.ru 470Sigor@sysoev.ru /* 480Sigor@sysoev.ru * nxt_thread_get_data() is used as 490Sigor@sysoev.ru * p = nxt_thread_get_data(tsd), 500Sigor@sysoev.ru * but the tsd address is actually required. This could be resolved by macro 510Sigor@sysoev.ru * #define nxt_thread_get_data(tsd) nxt_thread_get_data_addr(&tsd) 520Sigor@sysoev.ru * or by definition nxt_thread_specific_data_t as an array. 530Sigor@sysoev.ru * 540Sigor@sysoev.ru * On Linux and Solaris pthread_key_t is unsigned integer. 550Sigor@sysoev.ru * On FreeBSD, NetBSD, OpenBSD, and HP-UX pthread_key_t is integer. 560Sigor@sysoev.ru * On MacOSX and AIX pthread_key_t is unsigned long integer. 570Sigor@sysoev.ru * On Cygwin pthread_key_t is pointer to void. 580Sigor@sysoev.ru */ 590Sigor@sysoev.ru 600Sigor@sysoev.ru typedef struct { 610Sigor@sysoev.ru nxt_atomic_t key; 620Sigor@sysoev.ru size_t size; 630Sigor@sysoev.ru } nxt_thread_specific_data_t[1]; 640Sigor@sysoev.ru 650Sigor@sysoev.ru 66*2084Salx.manpages@gmail.com #define nxt_thread_extern_data(type, tsd) \ 670Sigor@sysoev.ru NXT_EXPORT extern nxt_thread_specific_data_t tsd 680Sigor@sysoev.ru 69*2084Salx.manpages@gmail.com #define nxt_thread_declare_data(type, tsd) \ 700Sigor@sysoev.ru nxt_thread_specific_data_t tsd = { { (nxt_atomic_int_t) -1, sizeof(type) } } 710Sigor@sysoev.ru 720Sigor@sysoev.ru NXT_EXPORT void nxt_thread_init_data(nxt_thread_specific_data_t tsd); 730Sigor@sysoev.ru 74*2084Salx.manpages@gmail.com #define nxt_thread_get_data(tsd) \ 750Sigor@sysoev.ru pthread_getspecific((pthread_key_t) tsd->key) 760Sigor@sysoev.ru 770Sigor@sysoev.ru #endif 780Sigor@sysoev.ru 790Sigor@sysoev.ru 800Sigor@sysoev.ru typedef void (*nxt_thread_start_t)(void *data); 810Sigor@sysoev.ru 820Sigor@sysoev.ru typedef struct { 830Sigor@sysoev.ru nxt_thread_start_t start; 840Sigor@sysoev.ru nxt_event_engine_t *engine; 854Sigor@sysoev.ru nxt_work_t work; 860Sigor@sysoev.ru } nxt_thread_link_t; 870Sigor@sysoev.ru 880Sigor@sysoev.ru 890Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_create(nxt_thread_handle_t *handle, 900Sigor@sysoev.ru nxt_thread_link_t *link); 910Sigor@sysoev.ru NXT_EXPORT nxt_thread_t *nxt_thread_init(void); 920Sigor@sysoev.ru NXT_EXPORT void nxt_thread_exit(nxt_thread_t *thr); 930Sigor@sysoev.ru NXT_EXPORT void nxt_thread_cancel(nxt_thread_handle_t handle); 940Sigor@sysoev.ru NXT_EXPORT void nxt_thread_wait(nxt_thread_handle_t handle); 950Sigor@sysoev.ru 960Sigor@sysoev.ru 97*2084Salx.manpages@gmail.com #define nxt_thread_handle() \ 980Sigor@sysoev.ru pthread_self() 990Sigor@sysoev.ru 1000Sigor@sysoev.ru 1010Sigor@sysoev.ru typedef pthread_mutex_t nxt_thread_mutex_t; 1020Sigor@sysoev.ru 1030Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_mutex_create(nxt_thread_mutex_t *mtx); 1040Sigor@sysoev.ru NXT_EXPORT void nxt_thread_mutex_destroy(nxt_thread_mutex_t *mtx); 1050Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_mutex_lock(nxt_thread_mutex_t *mtx); 1060Sigor@sysoev.ru NXT_EXPORT nxt_bool_t nxt_thread_mutex_trylock(nxt_thread_mutex_t *mtx); 1070Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_mutex_unlock(nxt_thread_mutex_t *mtx); 1080Sigor@sysoev.ru 1090Sigor@sysoev.ru 1100Sigor@sysoev.ru typedef pthread_cond_t nxt_thread_cond_t; 1110Sigor@sysoev.ru 1120Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_cond_create(nxt_thread_cond_t *cond); 1130Sigor@sysoev.ru NXT_EXPORT void nxt_thread_cond_destroy(nxt_thread_cond_t *cond); 1140Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_cond_signal(nxt_thread_cond_t *cond); 1150Sigor@sysoev.ru NXT_EXPORT nxt_err_t nxt_thread_cond_wait(nxt_thread_cond_t *cond, 1160Sigor@sysoev.ru nxt_thread_mutex_t *mtx, nxt_nsec_t timeout); 1170Sigor@sysoev.ru 1180Sigor@sysoev.ru 1190Sigor@sysoev.ru #if (NXT_HAVE_PTHREAD_YIELD) 120*2084Salx.manpages@gmail.com #define nxt_thread_yield() \ 1210Sigor@sysoev.ru pthread_yield() 1220Sigor@sysoev.ru 1230Sigor@sysoev.ru #elif (NXT_HAVE_PTHREAD_YIELD_NP) 124*2084Salx.manpages@gmail.com #define nxt_thread_yield() \ 1250Sigor@sysoev.ru pthread_yield_np() 1260Sigor@sysoev.ru 1270Sigor@sysoev.ru #else 128*2084Salx.manpages@gmail.com #define nxt_thread_yield() \ 1290Sigor@sysoev.ru nxt_sched_yield() 1300Sigor@sysoev.ru 1310Sigor@sysoev.ru #endif 1320Sigor@sysoev.ru 1330Sigor@sysoev.ru 1340Sigor@sysoev.ru struct nxt_thread_s { 1350Sigor@sysoev.ru nxt_log_t *log; 1360Sigor@sysoev.ru nxt_log_t main_log; 1370Sigor@sysoev.ru 13863Sigor@sysoev.ru nxt_task_t *task; 13963Sigor@sysoev.ru 1400Sigor@sysoev.ru nxt_tid_t tid; 1410Sigor@sysoev.ru nxt_thread_handle_t handle; 1420Sigor@sysoev.ru nxt_thread_link_t *link; 1430Sigor@sysoev.ru nxt_thread_pool_t *thread_pool; 1440Sigor@sysoev.ru 1450Sigor@sysoev.ru nxt_thread_time_t time; 1460Sigor@sysoev.ru 14720Sigor@sysoev.ru nxt_runtime_t *runtime; 1480Sigor@sysoev.ru nxt_event_engine_t *engine; 14953Sigor@sysoev.ru void *data; 1500Sigor@sysoev.ru 151326Svbart@nginx.com #if 0 1520Sigor@sysoev.ru /* 1530Sigor@sysoev.ru * Although pointer to a current fiber should be a property of 1540Sigor@sysoev.ru * engine->fibers, its placement here eliminates 2 memory accesses. 1550Sigor@sysoev.ru */ 1560Sigor@sysoev.ru nxt_fiber_t *fiber; 157326Svbart@nginx.com #endif 158138Sigor@sysoev.ru 159138Sigor@sysoev.ru nxt_random_t random; 1600Sigor@sysoev.ru }; 1610Sigor@sysoev.ru 1620Sigor@sysoev.ru 1630Sigor@sysoev.ru #endif /* _NXT_UNIX_THREAD_H_INCLUDED_ */ 164