xref: /unit/src/nxt_buf.c (revision 122)
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 #include <nxt_main.h>
80Sigor@sysoev.ru 
90Sigor@sysoev.ru 
101Sigor@sysoev.ru static void nxt_buf_completion(nxt_task_t *task, void *obj, void *data);
11*122Smax.romanov@nginx.com static void nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data);
12*122Smax.romanov@nginx.com 
13*122Smax.romanov@nginx.com 
14*122Smax.romanov@nginx.com typedef struct {
15*122Smax.romanov@nginx.com     nxt_work_t          work;
16*122Smax.romanov@nginx.com     nxt_event_engine_t  *engine;
17*122Smax.romanov@nginx.com } nxt_buf_ts_t;
180Sigor@sysoev.ru 
190Sigor@sysoev.ru 
204Sigor@sysoev.ru void
214Sigor@sysoev.ru nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size)
224Sigor@sysoev.ru {
234Sigor@sysoev.ru     b->mem.start = start;
244Sigor@sysoev.ru     b->mem.pos = start;
254Sigor@sysoev.ru     b->mem.free = start;
2698Svbart@nginx.com     b->mem.end = nxt_pointer_to(start, size);
274Sigor@sysoev.ru }
284Sigor@sysoev.ru 
294Sigor@sysoev.ru 
300Sigor@sysoev.ru nxt_buf_t *
3165Sigor@sysoev.ru nxt_buf_mem_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags)
320Sigor@sysoev.ru {
330Sigor@sysoev.ru     nxt_buf_t  *b;
340Sigor@sysoev.ru 
35*122Smax.romanov@nginx.com     b = nxt_mp_alloc(mp, NXT_BUF_MEM_SIZE + size);
360Sigor@sysoev.ru     if (nxt_slow_path(b == NULL)) {
370Sigor@sysoev.ru         return NULL;
380Sigor@sysoev.ru     }
390Sigor@sysoev.ru 
40*122Smax.romanov@nginx.com     nxt_memzero(b, NXT_BUF_MEM_SIZE);
41*122Smax.romanov@nginx.com 
420Sigor@sysoev.ru     b->data = mp;
430Sigor@sysoev.ru     b->completion_handler = nxt_buf_completion;
440Sigor@sysoev.ru 
450Sigor@sysoev.ru     if (size != 0) {
46*122Smax.romanov@nginx.com         b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE);
470Sigor@sysoev.ru         b->mem.pos = b->mem.start;
480Sigor@sysoev.ru         b->mem.free = b->mem.start;
490Sigor@sysoev.ru         b->mem.end = b->mem.start + size;
500Sigor@sysoev.ru     }
510Sigor@sysoev.ru 
520Sigor@sysoev.ru     return b;
530Sigor@sysoev.ru }
540Sigor@sysoev.ru 
550Sigor@sysoev.ru 
560Sigor@sysoev.ru nxt_buf_t *
57*122Smax.romanov@nginx.com nxt_buf_mem_ts_alloc(nxt_task_t *task, nxt_mp_t *mp, size_t size)
580Sigor@sysoev.ru {
59*122Smax.romanov@nginx.com     nxt_buf_t     *b;
60*122Smax.romanov@nginx.com     nxt_buf_ts_t  *ts;
610Sigor@sysoev.ru 
62*122Smax.romanov@nginx.com     b = nxt_mp_retain(mp, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t) + size);
630Sigor@sysoev.ru     if (nxt_slow_path(b == NULL)) {
640Sigor@sysoev.ru         return NULL;
650Sigor@sysoev.ru     }
660Sigor@sysoev.ru 
67*122Smax.romanov@nginx.com     nxt_memzero(b, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t));
68*122Smax.romanov@nginx.com 
69*122Smax.romanov@nginx.com     b->data = mp;
70*122Smax.romanov@nginx.com     b->completion_handler = nxt_buf_ts_completion;
71*122Smax.romanov@nginx.com     b->is_ts = 1;
72*122Smax.romanov@nginx.com 
73*122Smax.romanov@nginx.com     if (size != 0) {
74*122Smax.romanov@nginx.com         b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE +
75*122Smax.romanov@nginx.com                                       sizeof(nxt_buf_ts_t));
76*122Smax.romanov@nginx.com         b->mem.pos = b->mem.start;
77*122Smax.romanov@nginx.com         b->mem.free = b->mem.start;
78*122Smax.romanov@nginx.com         b->mem.end = b->mem.start + size;
79*122Smax.romanov@nginx.com     }
80*122Smax.romanov@nginx.com 
81*122Smax.romanov@nginx.com     ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE);
82*122Smax.romanov@nginx.com     ts->engine = task->thread->engine;
83*122Smax.romanov@nginx.com 
84*122Smax.romanov@nginx.com     ts->work.handler = nxt_buf_ts_completion;
85*122Smax.romanov@nginx.com     ts->work.task = task;
86*122Smax.romanov@nginx.com     ts->work.obj = b;
87*122Smax.romanov@nginx.com     ts->work.data = b->parent;
88*122Smax.romanov@nginx.com 
89*122Smax.romanov@nginx.com     return b;
90*122Smax.romanov@nginx.com }
91*122Smax.romanov@nginx.com 
92*122Smax.romanov@nginx.com 
93*122Smax.romanov@nginx.com nxt_buf_t *
94*122Smax.romanov@nginx.com nxt_buf_file_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags)
95*122Smax.romanov@nginx.com {
96*122Smax.romanov@nginx.com     nxt_buf_t  *b;
97*122Smax.romanov@nginx.com 
98*122Smax.romanov@nginx.com     b = nxt_mp_alloc(mp, NXT_BUF_FILE_SIZE + size);
99*122Smax.romanov@nginx.com     if (nxt_slow_path(b == NULL)) {
100*122Smax.romanov@nginx.com         return NULL;
101*122Smax.romanov@nginx.com     }
102*122Smax.romanov@nginx.com 
103*122Smax.romanov@nginx.com     nxt_memzero(b, NXT_BUF_FILE_SIZE);
104*122Smax.romanov@nginx.com 
1050Sigor@sysoev.ru     b->data = mp;
1060Sigor@sysoev.ru     b->completion_handler = nxt_buf_completion;
1070Sigor@sysoev.ru     nxt_buf_set_file(b);
1080Sigor@sysoev.ru 
1090Sigor@sysoev.ru     if (size != 0) {
110*122Smax.romanov@nginx.com         b->mem.start = nxt_pointer_to(b, NXT_BUF_FILE_SIZE);
1110Sigor@sysoev.ru         b->mem.pos = b->mem.start;
1120Sigor@sysoev.ru         b->mem.free = b->mem.start;
1130Sigor@sysoev.ru         b->mem.end = b->mem.start + size;
1140Sigor@sysoev.ru     }
1150Sigor@sysoev.ru 
1160Sigor@sysoev.ru     return b;
1170Sigor@sysoev.ru }
1180Sigor@sysoev.ru 
1190Sigor@sysoev.ru 
1200Sigor@sysoev.ru nxt_buf_t *
12165Sigor@sysoev.ru nxt_buf_mmap_alloc(nxt_mp_t *mp, size_t size)
1220Sigor@sysoev.ru {
1230Sigor@sysoev.ru     nxt_buf_t  *b;
1240Sigor@sysoev.ru 
12565Sigor@sysoev.ru     b = nxt_mp_zalloc(mp, NXT_BUF_MMAP_SIZE);
1260Sigor@sysoev.ru 
1270Sigor@sysoev.ru     if (nxt_fast_path(b != NULL)) {
1280Sigor@sysoev.ru         b->data = mp;
1290Sigor@sysoev.ru         b->completion_handler = nxt_buf_completion;
1300Sigor@sysoev.ru 
1310Sigor@sysoev.ru         nxt_buf_set_file(b);
1320Sigor@sysoev.ru         nxt_buf_set_mmap(b);
1330Sigor@sysoev.ru         nxt_buf_mem_set_size(&b->mem, size);
1340Sigor@sysoev.ru     }
1350Sigor@sysoev.ru 
1360Sigor@sysoev.ru     return b;
1370Sigor@sysoev.ru }
1380Sigor@sysoev.ru 
1390Sigor@sysoev.ru 
1400Sigor@sysoev.ru nxt_buf_t *
14165Sigor@sysoev.ru nxt_buf_sync_alloc(nxt_mp_t *mp, nxt_uint_t flags)
1420Sigor@sysoev.ru {
1430Sigor@sysoev.ru     nxt_buf_t  *b;
1440Sigor@sysoev.ru 
14565Sigor@sysoev.ru     b = nxt_mp_zalloc(mp, NXT_BUF_SYNC_SIZE);
1460Sigor@sysoev.ru 
1470Sigor@sysoev.ru     if (nxt_fast_path(b != NULL)) {
1480Sigor@sysoev.ru         b->data = mp;
1490Sigor@sysoev.ru         b->completion_handler = nxt_buf_completion;
1500Sigor@sysoev.ru 
1510Sigor@sysoev.ru         nxt_buf_set_sync(b);
1520Sigor@sysoev.ru         b->is_nobuf = ((flags & NXT_BUF_SYNC_NOBUF) != 0);
1530Sigor@sysoev.ru         b->is_flush = ((flags & NXT_BUF_SYNC_FLUSH) != 0);
1540Sigor@sysoev.ru         b->is_last = ((flags & NXT_BUF_SYNC_LAST) != 0);
1550Sigor@sysoev.ru     }
1560Sigor@sysoev.ru 
1570Sigor@sysoev.ru     return b;
1580Sigor@sysoev.ru }
1590Sigor@sysoev.ru 
1600Sigor@sysoev.ru 
1610Sigor@sysoev.ru void
1620Sigor@sysoev.ru nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in)
1630Sigor@sysoev.ru {
1640Sigor@sysoev.ru     nxt_buf_t  *b, **prev;
1650Sigor@sysoev.ru 
1660Sigor@sysoev.ru     prev = head;
1670Sigor@sysoev.ru 
1680Sigor@sysoev.ru     for (b = *head; b != NULL; b = b->next) {
1690Sigor@sysoev.ru         prev = &b->next;
1700Sigor@sysoev.ru     }
1710Sigor@sysoev.ru 
1720Sigor@sysoev.ru     *prev = in;
1730Sigor@sysoev.ru }
1740Sigor@sysoev.ru 
1750Sigor@sysoev.ru 
1760Sigor@sysoev.ru size_t
1770Sigor@sysoev.ru nxt_buf_chain_length(nxt_buf_t *b)
1780Sigor@sysoev.ru {
1790Sigor@sysoev.ru     size_t  length;
1800Sigor@sysoev.ru 
1810Sigor@sysoev.ru     length = 0;
1820Sigor@sysoev.ru 
1830Sigor@sysoev.ru     while (b != NULL) {
1840Sigor@sysoev.ru         length += b->mem.free - b->mem.pos;
1850Sigor@sysoev.ru         b = b->next;
1860Sigor@sysoev.ru     }
1870Sigor@sysoev.ru 
1880Sigor@sysoev.ru     return length;
1890Sigor@sysoev.ru }
1900Sigor@sysoev.ru 
1910Sigor@sysoev.ru 
1920Sigor@sysoev.ru static void
1931Sigor@sysoev.ru nxt_buf_completion(nxt_task_t *task, void *obj, void *data)
1940Sigor@sysoev.ru {
19565Sigor@sysoev.ru     nxt_mp_t   *mp;
19665Sigor@sysoev.ru     nxt_buf_t  *b, *parent;
1970Sigor@sysoev.ru 
1980Sigor@sysoev.ru     b = obj;
1990Sigor@sysoev.ru     parent = data;
2000Sigor@sysoev.ru 
2011Sigor@sysoev.ru     nxt_debug(task, "buf completion: %p %p", b, b->mem.start);
2020Sigor@sysoev.ru 
203*122Smax.romanov@nginx.com #if (NXT_DEBUG)
204*122Smax.romanov@nginx.com     if (nxt_slow_path(data != b->parent)) {
205*122Smax.romanov@nginx.com         nxt_log_alert(task->log, "completion data (%p) != b->parent (%p)",
206*122Smax.romanov@nginx.com                       data, b->parent);
207*122Smax.romanov@nginx.com         nxt_abort();
208*122Smax.romanov@nginx.com     }
209*122Smax.romanov@nginx.com #endif
210*122Smax.romanov@nginx.com 
2110Sigor@sysoev.ru     mp = b->data;
212*122Smax.romanov@nginx.com     nxt_mp_free(mp, b);
2130Sigor@sysoev.ru 
2140Sigor@sysoev.ru     if (parent != NULL) {
2151Sigor@sysoev.ru         nxt_debug(task, "parent retain:%uD", parent->retain);
2160Sigor@sysoev.ru 
2170Sigor@sysoev.ru         parent->retain--;
2180Sigor@sysoev.ru 
2190Sigor@sysoev.ru         if (parent->retain == 0) {
2200Sigor@sysoev.ru             parent->mem.pos = parent->mem.free;
2210Sigor@sysoev.ru 
2221Sigor@sysoev.ru             parent->completion_handler(task, parent, parent->parent);
2230Sigor@sysoev.ru         }
2240Sigor@sysoev.ru     }
2250Sigor@sysoev.ru }
226*122Smax.romanov@nginx.com 
227*122Smax.romanov@nginx.com 
228*122Smax.romanov@nginx.com nxt_int_t
229*122Smax.romanov@nginx.com nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data)
230*122Smax.romanov@nginx.com {
231*122Smax.romanov@nginx.com     nxt_buf_t     *b;
232*122Smax.romanov@nginx.com     nxt_buf_ts_t  *ts;
233*122Smax.romanov@nginx.com 
234*122Smax.romanov@nginx.com     b = obj;
235*122Smax.romanov@nginx.com 
236*122Smax.romanov@nginx.com #if (NXT_DEBUG)
237*122Smax.romanov@nginx.com     if (nxt_slow_path(b->is_ts == 0)) {
238*122Smax.romanov@nginx.com         nxt_log_alert(task->log, "not a thread safe buf (%p) completed", b);
239*122Smax.romanov@nginx.com         nxt_abort();
240*122Smax.romanov@nginx.com     }
241*122Smax.romanov@nginx.com #endif
242*122Smax.romanov@nginx.com 
243*122Smax.romanov@nginx.com     ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE);
244*122Smax.romanov@nginx.com 
245*122Smax.romanov@nginx.com     if (ts->engine != task->thread->engine) {
246*122Smax.romanov@nginx.com 
247*122Smax.romanov@nginx.com         nxt_debug(task, "buf ts: %p current engine is %p, expected %p",
248*122Smax.romanov@nginx.com                   b, task->thread->engine, ts->engine);
249*122Smax.romanov@nginx.com 
250*122Smax.romanov@nginx.com         ts->work.handler = b->completion_handler;
251*122Smax.romanov@nginx.com         ts->work.obj = obj;
252*122Smax.romanov@nginx.com         ts->work.data = data;
253*122Smax.romanov@nginx.com 
254*122Smax.romanov@nginx.com         nxt_event_engine_post(ts->engine, &ts->work);
255*122Smax.romanov@nginx.com 
256*122Smax.romanov@nginx.com         return 1;
257*122Smax.romanov@nginx.com     }
258*122Smax.romanov@nginx.com 
259*122Smax.romanov@nginx.com     return 0;
260*122Smax.romanov@nginx.com }
261*122Smax.romanov@nginx.com 
262*122Smax.romanov@nginx.com 
263*122Smax.romanov@nginx.com static void
264*122Smax.romanov@nginx.com nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data)
265*122Smax.romanov@nginx.com {
266*122Smax.romanov@nginx.com     nxt_mp_t   *mp;
267*122Smax.romanov@nginx.com     nxt_buf_t  *b, *parent;
268*122Smax.romanov@nginx.com 
269*122Smax.romanov@nginx.com     b = obj;
270*122Smax.romanov@nginx.com     parent = data;
271*122Smax.romanov@nginx.com 
272*122Smax.romanov@nginx.com     if (nxt_buf_ts_handle(task, obj, data)) {
273*122Smax.romanov@nginx.com         return;
274*122Smax.romanov@nginx.com     }
275*122Smax.romanov@nginx.com 
276*122Smax.romanov@nginx.com     nxt_debug(task, "buf ts completion: %p %p", b, b->mem.start);
277*122Smax.romanov@nginx.com 
278*122Smax.romanov@nginx.com #if (NXT_DEBUG)
279*122Smax.romanov@nginx.com     if (nxt_slow_path(data != b->parent)) {
280*122Smax.romanov@nginx.com         nxt_log_alert(task->log, "completion data (%p) != b->parent (%p)",
281*122Smax.romanov@nginx.com                       data, b->parent);
282*122Smax.romanov@nginx.com         nxt_abort();
283*122Smax.romanov@nginx.com     }
284*122Smax.romanov@nginx.com #endif
285*122Smax.romanov@nginx.com 
286*122Smax.romanov@nginx.com     mp = b->data;
287*122Smax.romanov@nginx.com     nxt_mp_release(mp, b);
288*122Smax.romanov@nginx.com 
289*122Smax.romanov@nginx.com     if (parent != NULL) {
290*122Smax.romanov@nginx.com         nxt_debug(task, "parent retain:%uD", parent->retain);
291*122Smax.romanov@nginx.com 
292*122Smax.romanov@nginx.com         parent->retain--;
293*122Smax.romanov@nginx.com 
294*122Smax.romanov@nginx.com         if (parent->retain == 0) {
295*122Smax.romanov@nginx.com             parent->mem.pos = parent->mem.free;
296*122Smax.romanov@nginx.com 
297*122Smax.romanov@nginx.com             parent->completion_handler(task, parent, parent->parent);
298*122Smax.romanov@nginx.com         }
299*122Smax.romanov@nginx.com     }
300*122Smax.romanov@nginx.com }
301