xref: /unit/src/nxt_thread.h (revision 63)
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