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_WORK_QUEUE_H_INCLUDED_ 80Sigor@sysoev.ru #define _NXT_WORK_QUEUE_H_INCLUDED_ 90Sigor@sysoev.ru 100Sigor@sysoev.ru 11*1Sigor@sysoev.ru typedef struct nxt_work_s nxt_work_t; 12*1Sigor@sysoev.ru 13*1Sigor@sysoev.ru typedef struct { 14*1Sigor@sysoev.ru nxt_thread_t *thread; 15*1Sigor@sysoev.ru nxt_log_t *log; 16*1Sigor@sysoev.ru uint32_t ident; 17*1Sigor@sysoev.ru nxt_work_t *next_work; 18*1Sigor@sysoev.ru 19*1Sigor@sysoev.ru /* TODO: exception_handler, prev/next task, subtasks. */ 20*1Sigor@sysoev.ru } nxt_task_t; 21*1Sigor@sysoev.ru 22*1Sigor@sysoev.ru 23*1Sigor@sysoev.ru #define nxt_task_next_ident() \ 24*1Sigor@sysoev.ru ((uint32_t) nxt_atomic_fetch_add(&nxt_task_ident, 1) & 0x3fffffff) 25*1Sigor@sysoev.ru 26*1Sigor@sysoev.ru 270Sigor@sysoev.ru /* 280Sigor@sysoev.ru * A work handler with just the obj and data arguments instead 290Sigor@sysoev.ru * of pointer to a possibly large a work struct allows to call 300Sigor@sysoev.ru * the handler not only via a work queue but also directly. 310Sigor@sysoev.ru * The only obj argument is enough for the most cases expect the 320Sigor@sysoev.ru * source filters, so the data argument has been introduced and 330Sigor@sysoev.ru * is used where appropriate. 340Sigor@sysoev.ru */ 35*1Sigor@sysoev.ru typedef void (*nxt_work_handler_t)(nxt_task_t *task, void *obj, void *data); 360Sigor@sysoev.ru 370Sigor@sysoev.ru 380Sigor@sysoev.ru struct nxt_work_s { 390Sigor@sysoev.ru nxt_work_t *next; 400Sigor@sysoev.ru nxt_work_handler_t handler; 41*1Sigor@sysoev.ru nxt_task_t *task; 420Sigor@sysoev.ru void *obj; 430Sigor@sysoev.ru void *data; 440Sigor@sysoev.ru }; 450Sigor@sysoev.ru 460Sigor@sysoev.ru 470Sigor@sysoev.ru typedef struct nxt_work_queue_chunk_s nxt_work_queue_chunk_t; 480Sigor@sysoev.ru 490Sigor@sysoev.ru struct nxt_work_queue_chunk_s { 500Sigor@sysoev.ru nxt_work_queue_chunk_t *next; 510Sigor@sysoev.ru nxt_work_t work; 520Sigor@sysoev.ru }; 530Sigor@sysoev.ru 540Sigor@sysoev.ru 550Sigor@sysoev.ru typedef struct { 560Sigor@sysoev.ru nxt_work_t *next; 570Sigor@sysoev.ru nxt_work_t *spare; 580Sigor@sysoev.ru nxt_work_queue_chunk_t *chunk; 590Sigor@sysoev.ru size_t chunk_size; 600Sigor@sysoev.ru } nxt_work_queue_cache_t; 610Sigor@sysoev.ru 620Sigor@sysoev.ru 630Sigor@sysoev.ru typedef struct nxt_work_queue_s nxt_work_queue_t; 640Sigor@sysoev.ru 650Sigor@sysoev.ru struct nxt_work_queue_s { 660Sigor@sysoev.ru nxt_work_t *head; 670Sigor@sysoev.ru nxt_work_t *tail; 680Sigor@sysoev.ru nxt_work_queue_t *next; 690Sigor@sysoev.ru #if (NXT_DEBUG) 700Sigor@sysoev.ru const char *name; 710Sigor@sysoev.ru #endif 720Sigor@sysoev.ru }; 730Sigor@sysoev.ru 740Sigor@sysoev.ru 750Sigor@sysoev.ru typedef struct { 760Sigor@sysoev.ru nxt_work_queue_t *head; 770Sigor@sysoev.ru nxt_work_queue_t *tail; 780Sigor@sysoev.ru nxt_work_queue_t main; 790Sigor@sysoev.ru nxt_work_queue_t last; 800Sigor@sysoev.ru nxt_work_queue_cache_t cache; 810Sigor@sysoev.ru } nxt_thread_work_queue_t; 820Sigor@sysoev.ru 830Sigor@sysoev.ru 840Sigor@sysoev.ru typedef struct { 850Sigor@sysoev.ru nxt_thread_spinlock_t lock; 860Sigor@sysoev.ru nxt_work_t *head; 870Sigor@sysoev.ru nxt_work_t *tail; 880Sigor@sysoev.ru nxt_work_queue_cache_t cache; 890Sigor@sysoev.ru } nxt_locked_work_queue_t; 900Sigor@sysoev.ru 910Sigor@sysoev.ru 920Sigor@sysoev.ru NXT_EXPORT void nxt_thread_work_queue_create(nxt_thread_t *thr, 930Sigor@sysoev.ru size_t chunk_size); 940Sigor@sysoev.ru NXT_EXPORT void nxt_thread_work_queue_destroy(nxt_thread_t *thr); 950Sigor@sysoev.ru NXT_EXPORT void nxt_thread_work_queue_add(nxt_thread_t *thr, 96*1Sigor@sysoev.ru nxt_work_queue_t *wq, nxt_work_handler_t handler, nxt_task_t *task, 97*1Sigor@sysoev.ru void *obj, void *data); 980Sigor@sysoev.ru NXT_EXPORT void nxt_thread_work_queue_push(nxt_thread_t *thr, 99*1Sigor@sysoev.ru nxt_work_queue_t *wq, nxt_work_handler_t handler, nxt_task_t *task, 100*1Sigor@sysoev.ru void *obj, void *data); 1010Sigor@sysoev.ru NXT_EXPORT void nxt_work_queue_attach(nxt_thread_t *thr, nxt_work_queue_t *wq); 1020Sigor@sysoev.ru NXT_EXPORT nxt_work_handler_t nxt_thread_work_queue_pop(nxt_thread_t *thr, 103*1Sigor@sysoev.ru nxt_task_t **task, void **obj, void **data); 1040Sigor@sysoev.ru NXT_EXPORT void nxt_thread_work_queue_drop(nxt_thread_t *thr, void *data); 1050Sigor@sysoev.ru 1060Sigor@sysoev.ru 1070Sigor@sysoev.ru #define \ 108*1Sigor@sysoev.ru nxt_thread_current_work_queue_add(thr, handler, task, obj, data) \ 1090Sigor@sysoev.ru do { \ 1100Sigor@sysoev.ru nxt_thread_t *_thr = thr; \ 1110Sigor@sysoev.ru \ 1120Sigor@sysoev.ru nxt_thread_work_queue_add(_thr, _thr->work_queue.head, \ 113*1Sigor@sysoev.ru handler, task, obj, data); \ 1140Sigor@sysoev.ru } while (0) 1150Sigor@sysoev.ru 1160Sigor@sysoev.ru 1170Sigor@sysoev.ru NXT_EXPORT void nxt_work_queue_destroy(nxt_work_queue_t *wq); 1180Sigor@sysoev.ru 1190Sigor@sysoev.ru 1200Sigor@sysoev.ru #if (NXT_DEBUG) 1210Sigor@sysoev.ru 1220Sigor@sysoev.ru #define \ 1230Sigor@sysoev.ru nxt_work_queue_name(_wq, _name) \ 1240Sigor@sysoev.ru (_wq)->name = _name 1250Sigor@sysoev.ru 1260Sigor@sysoev.ru #else 1270Sigor@sysoev.ru 1280Sigor@sysoev.ru #define \ 1290Sigor@sysoev.ru nxt_work_queue_name(_wq, _name) 1300Sigor@sysoev.ru 1310Sigor@sysoev.ru #endif 1320Sigor@sysoev.ru 1330Sigor@sysoev.ru 1340Sigor@sysoev.ru NXT_EXPORT void nxt_thread_last_work_queue_add(nxt_thread_t *thr, 135*1Sigor@sysoev.ru nxt_work_handler_t handler, void *obj, void *data); 1360Sigor@sysoev.ru NXT_EXPORT nxt_work_handler_t nxt_thread_last_work_queue_pop(nxt_thread_t *thr, 137*1Sigor@sysoev.ru nxt_task_t **task, void **obj, void **data); 1380Sigor@sysoev.ru 1390Sigor@sysoev.ru 1400Sigor@sysoev.ru NXT_EXPORT void nxt_locked_work_queue_create(nxt_locked_work_queue_t *lwq, 1410Sigor@sysoev.ru size_t chunk_size); 1420Sigor@sysoev.ru NXT_EXPORT void nxt_locked_work_queue_destroy(nxt_locked_work_queue_t *lwq); 1430Sigor@sysoev.ru NXT_EXPORT void nxt_locked_work_queue_add(nxt_locked_work_queue_t *lwq, 144*1Sigor@sysoev.ru nxt_work_handler_t handler, nxt_task_t *task, void *obj, void *data); 1450Sigor@sysoev.ru NXT_EXPORT nxt_work_handler_t nxt_locked_work_queue_pop( 146*1Sigor@sysoev.ru nxt_locked_work_queue_t *lwq, nxt_task_t **task, void **obj, void **data); 1470Sigor@sysoev.ru NXT_EXPORT void nxt_locked_work_queue_move(nxt_thread_t *thr, 1480Sigor@sysoev.ru nxt_locked_work_queue_t *lwq, nxt_work_queue_t *wq); 1490Sigor@sysoev.ru 1500Sigor@sysoev.ru 1510Sigor@sysoev.ru #endif /* _NXT_WORK_QUEUE_H_INCLUDED_ */ 152