1 2 /* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7 #ifndef _NXT_WORK_QUEUE_H_INCLUDED_ 8 #define _NXT_WORK_QUEUE_H_INCLUDED_ 9 10 11 typedef struct nxt_work_s nxt_work_t; 12 13 struct nxt_task_s { 14 nxt_thread_t *thread; 15 nxt_log_t *log; 16 uint32_t ident; 17 nxt_work_t *next_work; 18 19 /* TODO: exception_handler, prev/next task, subtasks. */ 20 }; 21 22 23 #define nxt_task_next_ident() \ 24 ((uint32_t) nxt_atomic_fetch_add(&nxt_task_ident, 1) & 0x3fffffff) 25 26 27 /* 28 * A work handler with just the obj and data arguments instead 29 * of pointer to a possibly large a work struct allows to call 30 * the handler not only via a work queue but also directly. 31 * The only obj argument is enough for the most cases except the 32 * source filters, so the data argument has been introduced and 33 * is used where appropriate. 34 */ 35 typedef void (*nxt_work_handler_t)(nxt_task_t *task, void *obj, void *data); 36 37 38 struct nxt_work_s { 39 nxt_work_t *next; 40 nxt_work_handler_t handler; 41 nxt_task_t *task; 42 void *obj; 43 void *data; 44 }; 45 46 47 typedef struct nxt_work_queue_chunk_s nxt_work_queue_chunk_t; 48 49 struct nxt_work_queue_chunk_s { 50 nxt_work_queue_chunk_t *next; 51 nxt_work_t work; 52 }; 53 54 55 typedef struct { 56 nxt_work_t *next; 57 nxt_work_t *spare; 58 nxt_work_queue_chunk_t *chunk; 59 size_t chunk_size; 60 } nxt_work_queue_cache_t; 61 62 63 typedef struct nxt_work_queue_s nxt_work_queue_t; 64 65 struct nxt_work_queue_s { 66 nxt_work_t *head; 67 nxt_work_t *tail; 68 nxt_work_queue_cache_t *cache; 69 #if (NXT_DEBUG) 70 const char *name; 71 int32_t pid; 72 nxt_tid_t tid; 73 #endif 74 }; 75 76 77 typedef struct { 78 nxt_thread_spinlock_t lock; 79 nxt_work_t *head; 80 nxt_work_t *tail; 81 nxt_work_queue_cache_t cache; 82 } nxt_locked_work_queue_t; 83 84 85 NXT_EXPORT void nxt_work_queue_cache_create(nxt_work_queue_cache_t *cache, 86 size_t chunk_size); 87 NXT_EXPORT void nxt_work_queue_cache_destroy(nxt_work_queue_cache_t *cache); 88 89 NXT_EXPORT void nxt_work_queue_add(nxt_work_queue_t *wq, 90 nxt_work_handler_t handler, nxt_task_t *task, void *obj, void *data); 91 NXT_EXPORT nxt_work_handler_t nxt_work_queue_pop(nxt_work_queue_t *wq, 92 nxt_task_t **task, void **obj, void **data); 93 94 95 #define nxt_work_set(_work, _handler, _task, _obj, _data) \ 96 do { \ 97 nxt_work_t *work = _work; \ 98 \ 99 work->handler = _handler; \ 100 work->task = _task; \ 101 work->obj = _obj; \ 102 work->data = _data; \ 103 } while (0) 104 105 #if (NXT_DEBUG) 106 107 NXT_EXPORT void nxt_work_queue_name(nxt_work_queue_t *wq, const char* name); 108 NXT_EXPORT void nxt_work_queue_thread_adopt(nxt_work_queue_t *wq); 109 110 #else 111 112 #define \ 113 nxt_work_queue_name(_wq, _name) 114 115 #define nxt_work_queue_thread_adopt(_wq) 116 117 #endif 118 119 120 NXT_EXPORT void nxt_locked_work_queue_add(nxt_locked_work_queue_t *lwq, 121 nxt_work_t *work); 122 NXT_EXPORT nxt_work_handler_t nxt_locked_work_queue_pop( 123 nxt_locked_work_queue_t *lwq, nxt_task_t **task, void **obj, void **data); 124 NXT_EXPORT void nxt_locked_work_queue_move(nxt_thread_t *thr, 125 nxt_locked_work_queue_t *lwq, nxt_work_queue_t *wq); 126 127 128 #endif /* _NXT_WORK_QUEUE_H_INCLUDED_ */ 129