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);
11122Smax.romanov@nginx.com static void nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data);
12122Smax.romanov@nginx.com
13122Smax.romanov@nginx.com
14122Smax.romanov@nginx.com typedef struct {
15122Smax.romanov@nginx.com nxt_work_t work;
16122Smax.romanov@nginx.com nxt_event_engine_t *engine;
17122Smax.romanov@nginx.com } nxt_buf_ts_t;
180Sigor@sysoev.ru
190Sigor@sysoev.ru
204Sigor@sysoev.ru void
nxt_buf_mem_init(nxt_buf_t * b,void * start,size_t size)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 *
nxt_buf_mem_alloc(nxt_mp_t * mp,size_t size,nxt_uint_t flags)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
35122Smax.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
40122Smax.romanov@nginx.com nxt_memzero(b, NXT_BUF_MEM_SIZE);
41122Smax.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) {
46122Smax.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 *
nxt_buf_mem_ts_alloc(nxt_task_t * task,nxt_mp_t * mp,size_t size)57122Smax.romanov@nginx.com nxt_buf_mem_ts_alloc(nxt_task_t *task, nxt_mp_t *mp, size_t size)
580Sigor@sysoev.ru {
59122Smax.romanov@nginx.com nxt_buf_t *b;
60122Smax.romanov@nginx.com nxt_buf_ts_t *ts;
610Sigor@sysoev.ru
62430Sigor@sysoev.ru b = nxt_mp_alloc(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
67430Sigor@sysoev.ru nxt_mp_retain(mp);
68430Sigor@sysoev.ru
69122Smax.romanov@nginx.com nxt_memzero(b, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t));
70122Smax.romanov@nginx.com
71122Smax.romanov@nginx.com b->data = mp;
72122Smax.romanov@nginx.com b->completion_handler = nxt_buf_ts_completion;
73122Smax.romanov@nginx.com b->is_ts = 1;
74122Smax.romanov@nginx.com
75122Smax.romanov@nginx.com if (size != 0) {
76613Svbart@nginx.com b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE
77613Svbart@nginx.com + sizeof(nxt_buf_ts_t));
78122Smax.romanov@nginx.com b->mem.pos = b->mem.start;
79122Smax.romanov@nginx.com b->mem.free = b->mem.start;
80122Smax.romanov@nginx.com b->mem.end = b->mem.start + size;
81122Smax.romanov@nginx.com }
82122Smax.romanov@nginx.com
83122Smax.romanov@nginx.com ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE);
84122Smax.romanov@nginx.com ts->engine = task->thread->engine;
85122Smax.romanov@nginx.com
86122Smax.romanov@nginx.com ts->work.handler = nxt_buf_ts_completion;
87122Smax.romanov@nginx.com ts->work.task = task;
88122Smax.romanov@nginx.com ts->work.obj = b;
89122Smax.romanov@nginx.com ts->work.data = b->parent;
90122Smax.romanov@nginx.com
91122Smax.romanov@nginx.com return b;
92122Smax.romanov@nginx.com }
93122Smax.romanov@nginx.com
94122Smax.romanov@nginx.com
95122Smax.romanov@nginx.com nxt_buf_t *
nxt_buf_file_alloc(nxt_mp_t * mp,size_t size,nxt_uint_t flags)96122Smax.romanov@nginx.com nxt_buf_file_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags)
97122Smax.romanov@nginx.com {
98122Smax.romanov@nginx.com nxt_buf_t *b;
99122Smax.romanov@nginx.com
100122Smax.romanov@nginx.com b = nxt_mp_alloc(mp, NXT_BUF_FILE_SIZE + size);
101122Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) {
102122Smax.romanov@nginx.com return NULL;
103122Smax.romanov@nginx.com }
104122Smax.romanov@nginx.com
105122Smax.romanov@nginx.com nxt_memzero(b, NXT_BUF_FILE_SIZE);
106122Smax.romanov@nginx.com
1070Sigor@sysoev.ru b->data = mp;
1080Sigor@sysoev.ru b->completion_handler = nxt_buf_completion;
1090Sigor@sysoev.ru nxt_buf_set_file(b);
1100Sigor@sysoev.ru
1110Sigor@sysoev.ru if (size != 0) {
112122Smax.romanov@nginx.com b->mem.start = nxt_pointer_to(b, NXT_BUF_FILE_SIZE);
1130Sigor@sysoev.ru b->mem.pos = b->mem.start;
1140Sigor@sysoev.ru b->mem.free = b->mem.start;
1150Sigor@sysoev.ru b->mem.end = b->mem.start + size;
1160Sigor@sysoev.ru }
1170Sigor@sysoev.ru
1180Sigor@sysoev.ru return b;
1190Sigor@sysoev.ru }
1200Sigor@sysoev.ru
1210Sigor@sysoev.ru
1220Sigor@sysoev.ru nxt_buf_t *
nxt_buf_mmap_alloc(nxt_mp_t * mp,size_t size)12365Sigor@sysoev.ru nxt_buf_mmap_alloc(nxt_mp_t *mp, size_t size)
1240Sigor@sysoev.ru {
1250Sigor@sysoev.ru nxt_buf_t *b;
1260Sigor@sysoev.ru
12765Sigor@sysoev.ru b = nxt_mp_zalloc(mp, NXT_BUF_MMAP_SIZE);
1280Sigor@sysoev.ru
1290Sigor@sysoev.ru if (nxt_fast_path(b != NULL)) {
1300Sigor@sysoev.ru b->data = mp;
1310Sigor@sysoev.ru b->completion_handler = nxt_buf_completion;
1320Sigor@sysoev.ru
1330Sigor@sysoev.ru nxt_buf_set_file(b);
1340Sigor@sysoev.ru nxt_buf_set_mmap(b);
1350Sigor@sysoev.ru nxt_buf_mem_set_size(&b->mem, size);
1360Sigor@sysoev.ru }
1370Sigor@sysoev.ru
1380Sigor@sysoev.ru return b;
1390Sigor@sysoev.ru }
1400Sigor@sysoev.ru
1410Sigor@sysoev.ru
1420Sigor@sysoev.ru nxt_buf_t *
nxt_buf_sync_alloc(nxt_mp_t * mp,nxt_uint_t flags)14365Sigor@sysoev.ru nxt_buf_sync_alloc(nxt_mp_t *mp, nxt_uint_t flags)
1440Sigor@sysoev.ru {
1450Sigor@sysoev.ru nxt_buf_t *b;
1460Sigor@sysoev.ru
147608Sigor@sysoev.ru b = nxt_mp_zalloc(mp, NXT_BUF_MEM_SIZE);
1480Sigor@sysoev.ru
1490Sigor@sysoev.ru if (nxt_fast_path(b != NULL)) {
1500Sigor@sysoev.ru b->data = mp;
1510Sigor@sysoev.ru b->completion_handler = nxt_buf_completion;
1520Sigor@sysoev.ru
1530Sigor@sysoev.ru nxt_buf_set_sync(b);
1540Sigor@sysoev.ru b->is_nobuf = ((flags & NXT_BUF_SYNC_NOBUF) != 0);
1550Sigor@sysoev.ru b->is_flush = ((flags & NXT_BUF_SYNC_FLUSH) != 0);
1560Sigor@sysoev.ru b->is_last = ((flags & NXT_BUF_SYNC_LAST) != 0);
1570Sigor@sysoev.ru }
1580Sigor@sysoev.ru
1590Sigor@sysoev.ru return b;
1600Sigor@sysoev.ru }
1610Sigor@sysoev.ru
1620Sigor@sysoev.ru
1630Sigor@sysoev.ru void
nxt_buf_chain_add(nxt_buf_t ** head,nxt_buf_t * in)1640Sigor@sysoev.ru nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in)
1650Sigor@sysoev.ru {
1660Sigor@sysoev.ru nxt_buf_t *b, **prev;
1670Sigor@sysoev.ru
1680Sigor@sysoev.ru prev = head;
1690Sigor@sysoev.ru
1700Sigor@sysoev.ru for (b = *head; b != NULL; b = b->next) {
1710Sigor@sysoev.ru prev = &b->next;
1720Sigor@sysoev.ru }
1730Sigor@sysoev.ru
1740Sigor@sysoev.ru *prev = in;
1750Sigor@sysoev.ru }
1760Sigor@sysoev.ru
1770Sigor@sysoev.ru
1780Sigor@sysoev.ru size_t
nxt_buf_chain_length(nxt_buf_t * b)1790Sigor@sysoev.ru nxt_buf_chain_length(nxt_buf_t *b)
1800Sigor@sysoev.ru {
1810Sigor@sysoev.ru size_t length;
1820Sigor@sysoev.ru
1830Sigor@sysoev.ru length = 0;
1840Sigor@sysoev.ru
1850Sigor@sysoev.ru while (b != NULL) {
186*1271Sigor@sysoev.ru if (!nxt_buf_is_sync(b)) {
187*1271Sigor@sysoev.ru length += b->mem.free - b->mem.pos;
188*1271Sigor@sysoev.ru }
189*1271Sigor@sysoev.ru
1900Sigor@sysoev.ru b = b->next;
1910Sigor@sysoev.ru }
1920Sigor@sysoev.ru
1930Sigor@sysoev.ru return length;
1940Sigor@sysoev.ru }
1950Sigor@sysoev.ru
1960Sigor@sysoev.ru
1970Sigor@sysoev.ru static void
nxt_buf_completion(nxt_task_t * task,void * obj,void * data)1981Sigor@sysoev.ru nxt_buf_completion(nxt_task_t *task, void *obj, void *data)
1990Sigor@sysoev.ru {
20065Sigor@sysoev.ru nxt_mp_t *mp;
2011269Sigor@sysoev.ru nxt_buf_t *b, *next, *parent;
2020Sigor@sysoev.ru
2030Sigor@sysoev.ru b = obj;
2040Sigor@sysoev.ru
2051Sigor@sysoev.ru nxt_debug(task, "buf completion: %p %p", b, b->mem.start);
2060Sigor@sysoev.ru
207564Svbart@nginx.com nxt_assert(data == b->parent);
208122Smax.romanov@nginx.com
2091269Sigor@sysoev.ru do {
2101269Sigor@sysoev.ru next = b->next;
2111269Sigor@sysoev.ru parent = b->parent;
2121269Sigor@sysoev.ru mp = b->data;
2130Sigor@sysoev.ru
2141269Sigor@sysoev.ru nxt_mp_free(mp, b);
2151269Sigor@sysoev.ru
2161269Sigor@sysoev.ru nxt_buf_parent_completion(task, parent);
2171269Sigor@sysoev.ru
2181269Sigor@sysoev.ru b = next;
2191269Sigor@sysoev.ru } while (b != NULL);
2201267Sigor@sysoev.ru }
2211267Sigor@sysoev.ru
2221267Sigor@sysoev.ru
2231267Sigor@sysoev.ru void
nxt_buf_parent_completion(nxt_task_t * task,nxt_buf_t * parent)2241267Sigor@sysoev.ru nxt_buf_parent_completion(nxt_task_t *task, nxt_buf_t *parent)
2251267Sigor@sysoev.ru {
2260Sigor@sysoev.ru if (parent != NULL) {
2271Sigor@sysoev.ru nxt_debug(task, "parent retain:%uD", parent->retain);
2280Sigor@sysoev.ru
2290Sigor@sysoev.ru parent->retain--;
2300Sigor@sysoev.ru
2310Sigor@sysoev.ru if (parent->retain == 0) {
2320Sigor@sysoev.ru parent->mem.pos = parent->mem.free;
2330Sigor@sysoev.ru
2341Sigor@sysoev.ru parent->completion_handler(task, parent, parent->parent);
2350Sigor@sysoev.ru }
2360Sigor@sysoev.ru }
2370Sigor@sysoev.ru }
238122Smax.romanov@nginx.com
239122Smax.romanov@nginx.com
240122Smax.romanov@nginx.com nxt_int_t
nxt_buf_ts_handle(nxt_task_t * task,void * obj,void * data)241122Smax.romanov@nginx.com nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data)
242122Smax.romanov@nginx.com {
243122Smax.romanov@nginx.com nxt_buf_t *b;
244122Smax.romanov@nginx.com nxt_buf_ts_t *ts;
245122Smax.romanov@nginx.com
246122Smax.romanov@nginx.com b = obj;
247122Smax.romanov@nginx.com
248564Svbart@nginx.com nxt_assert(b->is_ts != 0);
249122Smax.romanov@nginx.com
250122Smax.romanov@nginx.com ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE);
251122Smax.romanov@nginx.com
252122Smax.romanov@nginx.com if (ts->engine != task->thread->engine) {
253122Smax.romanov@nginx.com
254122Smax.romanov@nginx.com nxt_debug(task, "buf ts: %p current engine is %p, expected %p",
255122Smax.romanov@nginx.com b, task->thread->engine, ts->engine);
256122Smax.romanov@nginx.com
257122Smax.romanov@nginx.com ts->work.handler = b->completion_handler;
258122Smax.romanov@nginx.com ts->work.obj = obj;
259122Smax.romanov@nginx.com ts->work.data = data;
260122Smax.romanov@nginx.com
261122Smax.romanov@nginx.com nxt_event_engine_post(ts->engine, &ts->work);
262122Smax.romanov@nginx.com
263122Smax.romanov@nginx.com return 1;
264122Smax.romanov@nginx.com }
265122Smax.romanov@nginx.com
266122Smax.romanov@nginx.com return 0;
267122Smax.romanov@nginx.com }
268122Smax.romanov@nginx.com
269122Smax.romanov@nginx.com
270122Smax.romanov@nginx.com static void
nxt_buf_ts_completion(nxt_task_t * task,void * obj,void * data)271122Smax.romanov@nginx.com nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data)
272122Smax.romanov@nginx.com {
273122Smax.romanov@nginx.com nxt_mp_t *mp;
2741269Sigor@sysoev.ru nxt_buf_t *b, *next, *parent;
275122Smax.romanov@nginx.com
276122Smax.romanov@nginx.com b = obj;
277122Smax.romanov@nginx.com
278122Smax.romanov@nginx.com if (nxt_buf_ts_handle(task, obj, data)) {
279122Smax.romanov@nginx.com return;
280122Smax.romanov@nginx.com }
281122Smax.romanov@nginx.com
282122Smax.romanov@nginx.com nxt_debug(task, "buf ts completion: %p %p", b, b->mem.start);
283122Smax.romanov@nginx.com
284564Svbart@nginx.com nxt_assert(data == b->parent);
285122Smax.romanov@nginx.com
2861269Sigor@sysoev.ru do {
2871269Sigor@sysoev.ru next = b->next;
2881269Sigor@sysoev.ru parent = b->parent;
2891269Sigor@sysoev.ru mp = b->data;
290122Smax.romanov@nginx.com
2911269Sigor@sysoev.ru nxt_mp_free(mp, b);
2921269Sigor@sysoev.ru nxt_mp_release(mp);
2931269Sigor@sysoev.ru
2941269Sigor@sysoev.ru nxt_buf_parent_completion(task, parent);
2951269Sigor@sysoev.ru
2961269Sigor@sysoev.ru b = next;
2971269Sigor@sysoev.ru } while (b != NULL);
298122Smax.romanov@nginx.com }
299352Smax.romanov@nginx.com
300352Smax.romanov@nginx.com
301352Smax.romanov@nginx.com nxt_buf_t *
nxt_buf_make_plain(nxt_mp_t * mp,nxt_buf_t * src,size_t size)302352Smax.romanov@nginx.com nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size)
303352Smax.romanov@nginx.com {
304352Smax.romanov@nginx.com nxt_buf_t *b, *i;
305352Smax.romanov@nginx.com
306352Smax.romanov@nginx.com if (nxt_slow_path(size == 0)) {
307352Smax.romanov@nginx.com for (i = src; i != NULL; i = i->next) {
308352Smax.romanov@nginx.com size += nxt_buf_used_size(i);
309352Smax.romanov@nginx.com }
310352Smax.romanov@nginx.com }
311352Smax.romanov@nginx.com
312352Smax.romanov@nginx.com b = nxt_buf_mem_alloc(mp, size, 0);
313352Smax.romanov@nginx.com
314352Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) {
315352Smax.romanov@nginx.com return NULL;
316352Smax.romanov@nginx.com }
317352Smax.romanov@nginx.com
318352Smax.romanov@nginx.com for (i = src; i != NULL; i = i->next) {
319613Svbart@nginx.com if (nxt_slow_path(nxt_buf_mem_free_size(&b->mem)
320613Svbart@nginx.com < nxt_buf_used_size(i)))
321613Svbart@nginx.com {
322352Smax.romanov@nginx.com break;
323352Smax.romanov@nginx.com }
324352Smax.romanov@nginx.com
325352Smax.romanov@nginx.com b->mem.free = nxt_cpymem(b->mem.free, i->mem.pos, nxt_buf_used_size(i));
326352Smax.romanov@nginx.com }
327352Smax.romanov@nginx.com
328352Smax.romanov@nginx.com return b;
329352Smax.romanov@nginx.com }
330