summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_thread.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/nxt_thread.h192
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_ */