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