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 #if (NXT_THREADS) 120Sigor@sysoev.ru 130Sigor@sysoev.ru /* 140Sigor@sysoev.ru * Thread Specific Data 150Sigor@sysoev.ru * 160Sigor@sysoev.ru * The interface unifies two TSD implementations: the __thread storage 170Sigor@sysoev.ru * class and pthread specific data. It works also in non-threaded mode. 180Sigor@sysoev.ru * The interface is optimized for the __thread storage class and non-threaded 190Sigor@sysoev.ru * mode, since the __thread storage is faster and is supported in modern 200Sigor@sysoev.ru * versions of Linux, FreeBSD, Solaris, and MacOSX. Pthread specific data 210Sigor@sysoev.ru * is considered as a fallback option. 220Sigor@sysoev.ru * 230Sigor@sysoev.ru * The underlining interfaces are different: pthread data must be allocated 240Sigor@sysoev.ru * by hand and may be accessed only by using pointers whereas __thread data 250Sigor@sysoev.ru * allocation is transparent and it is accessed directly. 260Sigor@sysoev.ru * 270Sigor@sysoev.ru * pthread_getspecific() is usually faster than pthread_setspecific() 280Sigor@sysoev.ru * (much faster on MacOSX), so there is no nxt_thread_set_data() interface 290Sigor@sysoev.ru * for this reason. It is better to store frequently alterable thread 300Sigor@sysoev.ru * log pointer in nxt_thread_t, but not in a dedicated key. 310Sigor@sysoev.ru */ 320Sigor@sysoev.ru 330Sigor@sysoev.ru #if (NXT_HAVE_THREAD_STORAGE_CLASS) 340Sigor@sysoev.ru 350Sigor@sysoev.ru #define \ 360Sigor@sysoev.ru nxt_thread_extern_data(type, tsd) \ 370Sigor@sysoev.ru NXT_EXPORT extern __thread type tsd 380Sigor@sysoev.ru 390Sigor@sysoev.ru #define \ 400Sigor@sysoev.ru nxt_thread_declare_data(type, tsd) \ 410Sigor@sysoev.ru __thread type tsd 420Sigor@sysoev.ru 430Sigor@sysoev.ru #define \ 440Sigor@sysoev.ru nxt_thread_init_data(tsd) 450Sigor@sysoev.ru 460Sigor@sysoev.ru #define \ 470Sigor@sysoev.ru nxt_thread_get_data(tsd) \ 480Sigor@sysoev.ru &tsd 490Sigor@sysoev.ru 500Sigor@sysoev.ru 510Sigor@sysoev.ru #else /* NXT_HAVE_PTHREAD_SPECIFIC_DATA */ 520Sigor@sysoev.ru 530Sigor@sysoev.ru /* 540Sigor@sysoev.ru * nxt_thread_get_data() is used as 550Sigor@sysoev.ru * p = nxt_thread_get_data(tsd), 560Sigor@sysoev.ru * but the tsd address is actually required. This could be resolved by macro 570Sigor@sysoev.ru * #define nxt_thread_get_data(tsd) nxt_thread_get_data_addr(&tsd) 580Sigor@sysoev.ru * or by definition nxt_thread_specific_data_t as an array. 590Sigor@sysoev.ru * 600Sigor@sysoev.ru * On Linux and Solaris pthread_key_t is unsigned integer. 610Sigor@sysoev.ru * On FreeBSD, NetBSD, OpenBSD, and HP-UX pthread_key_t is integer. 620Sigor@sysoev.ru * On MacOSX and AIX pthread_key_t is unsigned long integer. 630Sigor@sysoev.ru * On Cygwin pthread_key_t is pointer to void. 640Sigor@sysoev.ru */ 650Sigor@sysoev.ru 660Sigor@sysoev.ru typedef struct { 670Sigor@sysoev.ru nxt_atomic_t key; 680Sigor@sysoev.ru size_t size; 690Sigor@sysoev.ru } nxt_thread_specific_data_t[1]; 700Sigor@sysoev.ru 710Sigor@sysoev.ru 720Sigor@sysoev.ru #define \ 730Sigor@sysoev.ru nxt_thread_extern_data(type, tsd) \ 740Sigor@sysoev.ru NXT_EXPORT extern nxt_thread_specific_data_t tsd 750Sigor@sysoev.ru 760Sigor@sysoev.ru #define \ 770Sigor@sysoev.ru nxt_thread_declare_data(type, tsd) \ 780Sigor@sysoev.ru nxt_thread_specific_data_t tsd = { { (nxt_atomic_int_t) -1, sizeof(type) } } 790Sigor@sysoev.ru 800Sigor@sysoev.ru NXT_EXPORT void nxt_thread_init_data(nxt_thread_specific_data_t tsd); 810Sigor@sysoev.ru 820Sigor@sysoev.ru #define \ 830Sigor@sysoev.ru nxt_thread_get_data(tsd) \ 840Sigor@sysoev.ru pthread_getspecific((pthread_key_t) tsd->key) 850Sigor@sysoev.ru 860Sigor@sysoev.ru #endif 870Sigor@sysoev.ru 880Sigor@sysoev.ru 890Sigor@sysoev.ru typedef void (*nxt_thread_start_t)(void *data); 900Sigor@sysoev.ru 910Sigor@sysoev.ru typedef struct { 920Sigor@sysoev.ru nxt_thread_start_t start; 930Sigor@sysoev.ru nxt_event_engine_t *engine; 944Sigor@sysoev.ru nxt_work_t work; 950Sigor@sysoev.ru } nxt_thread_link_t; 960Sigor@sysoev.ru 970Sigor@sysoev.ru 980Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_create(nxt_thread_handle_t *handle, 990Sigor@sysoev.ru nxt_thread_link_t *link); 1000Sigor@sysoev.ru NXT_EXPORT nxt_thread_t *nxt_thread_init(void); 1010Sigor@sysoev.ru NXT_EXPORT void nxt_thread_exit(nxt_thread_t *thr); 1020Sigor@sysoev.ru NXT_EXPORT void nxt_thread_cancel(nxt_thread_handle_t handle); 1030Sigor@sysoev.ru NXT_EXPORT void nxt_thread_wait(nxt_thread_handle_t handle); 1040Sigor@sysoev.ru 1050Sigor@sysoev.ru 1060Sigor@sysoev.ru #define \ 1070Sigor@sysoev.ru nxt_thread_handle() \ 1080Sigor@sysoev.ru pthread_self() 1090Sigor@sysoev.ru 1100Sigor@sysoev.ru 1110Sigor@sysoev.ru typedef pthread_mutex_t nxt_thread_mutex_t; 1120Sigor@sysoev.ru 1130Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_mutex_create(nxt_thread_mutex_t *mtx); 1140Sigor@sysoev.ru NXT_EXPORT void nxt_thread_mutex_destroy(nxt_thread_mutex_t *mtx); 1150Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_mutex_lock(nxt_thread_mutex_t *mtx); 1160Sigor@sysoev.ru NXT_EXPORT nxt_bool_t nxt_thread_mutex_trylock(nxt_thread_mutex_t *mtx); 1170Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_mutex_unlock(nxt_thread_mutex_t *mtx); 1180Sigor@sysoev.ru 1190Sigor@sysoev.ru 1200Sigor@sysoev.ru typedef pthread_cond_t nxt_thread_cond_t; 1210Sigor@sysoev.ru 1220Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_cond_create(nxt_thread_cond_t *cond); 1230Sigor@sysoev.ru NXT_EXPORT void nxt_thread_cond_destroy(nxt_thread_cond_t *cond); 1240Sigor@sysoev.ru NXT_EXPORT nxt_int_t nxt_thread_cond_signal(nxt_thread_cond_t *cond); 1250Sigor@sysoev.ru NXT_EXPORT nxt_err_t nxt_thread_cond_wait(nxt_thread_cond_t *cond, 1260Sigor@sysoev.ru nxt_thread_mutex_t *mtx, nxt_nsec_t timeout); 1270Sigor@sysoev.ru 1280Sigor@sysoev.ru 1290Sigor@sysoev.ru #else /* !(NXT_THREADS) */ 1300Sigor@sysoev.ru 1310Sigor@sysoev.ru #define \ 1320Sigor@sysoev.ru nxt_thread_extern_data(type, tsd) \ 1330Sigor@sysoev.ru NXT_EXPORT extern type tsd 1340Sigor@sysoev.ru 1350Sigor@sysoev.ru #define \ 1360Sigor@sysoev.ru nxt_thread_declare_data(type, tsd) \ 1370Sigor@sysoev.ru type tsd 1380Sigor@sysoev.ru 1390Sigor@sysoev.ru #define \ 1400Sigor@sysoev.ru nxt_thread_init_data(tsd) 1410Sigor@sysoev.ru 1420Sigor@sysoev.ru #define \ 1430Sigor@sysoev.ru nxt_thread_get_data(tsd) \ 1440Sigor@sysoev.ru &tsd 1450Sigor@sysoev.ru 1460Sigor@sysoev.ru #endif /* NXT_THREADS */ 1470Sigor@sysoev.ru 1480Sigor@sysoev.ru 1490Sigor@sysoev.ru #if (NXT_HAVE_PTHREAD_YIELD) 1500Sigor@sysoev.ru #define \ 1510Sigor@sysoev.ru nxt_thread_yield() \ 1520Sigor@sysoev.ru pthread_yield() 1530Sigor@sysoev.ru 1540Sigor@sysoev.ru #elif (NXT_HAVE_PTHREAD_YIELD_NP) 1550Sigor@sysoev.ru #define \ 1560Sigor@sysoev.ru nxt_thread_yield() \ 1570Sigor@sysoev.ru pthread_yield_np() 1580Sigor@sysoev.ru 1590Sigor@sysoev.ru #else 1600Sigor@sysoev.ru #define \ 1610Sigor@sysoev.ru nxt_thread_yield() \ 1620Sigor@sysoev.ru nxt_sched_yield() 1630Sigor@sysoev.ru 1640Sigor@sysoev.ru #endif 1650Sigor@sysoev.ru 1660Sigor@sysoev.ru 1670Sigor@sysoev.ru struct nxt_thread_s { 1680Sigor@sysoev.ru nxt_log_t *log; 1690Sigor@sysoev.ru nxt_log_t main_log; 1700Sigor@sysoev.ru 171*63Sigor@sysoev.ru nxt_task_t *task; 172*63Sigor@sysoev.ru 1730Sigor@sysoev.ru nxt_tid_t tid; 1740Sigor@sysoev.ru nxt_thread_handle_t handle; 1750Sigor@sysoev.ru #if (NXT_THREADS) 1760Sigor@sysoev.ru nxt_thread_link_t *link; 1770Sigor@sysoev.ru nxt_thread_pool_t *thread_pool; 1780Sigor@sysoev.ru #endif 1790Sigor@sysoev.ru 1800Sigor@sysoev.ru nxt_thread_time_t time; 1810Sigor@sysoev.ru 18220Sigor@sysoev.ru nxt_runtime_t *runtime; 1830Sigor@sysoev.ru nxt_event_engine_t *engine; 18453Sigor@sysoev.ru void *data; 1850Sigor@sysoev.ru 1860Sigor@sysoev.ru /* 1870Sigor@sysoev.ru * Although pointer to a current fiber should be a property of 1880Sigor@sysoev.ru * engine->fibers, its placement here eliminates 2 memory accesses. 1890Sigor@sysoev.ru */ 1900Sigor@sysoev.ru nxt_fiber_t *fiber; 1910Sigor@sysoev.ru }; 1920Sigor@sysoev.ru 1930Sigor@sysoev.ru 1940Sigor@sysoev.ru #endif /* _NXT_UNIX_THREAD_H_INCLUDED_ */ 195