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