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 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 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 * 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 * 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 * 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 * 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 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 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 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 parent = data; 2050Sigor@sysoev.ru 2061Sigor@sysoev.ru nxt_debug(task, "buf completion: %p %p", b, b->mem.start); 2070Sigor@sysoev.ru 208564Svbart@nginx.com nxt_assert(data == b->parent); 209122Smax.romanov@nginx.com 2101269Sigor@sysoev.ru do { 2111269Sigor@sysoev.ru next = b->next; 2121269Sigor@sysoev.ru parent = b->parent; 2131269Sigor@sysoev.ru mp = b->data; 2140Sigor@sysoev.ru 2151269Sigor@sysoev.ru nxt_mp_free(mp, b); 2161269Sigor@sysoev.ru 2171269Sigor@sysoev.ru nxt_buf_parent_completion(task, parent); 2181269Sigor@sysoev.ru 2191269Sigor@sysoev.ru b = next; 2201269Sigor@sysoev.ru } while (b != NULL); 2211267Sigor@sysoev.ru } 2221267Sigor@sysoev.ru 2231267Sigor@sysoev.ru 2241267Sigor@sysoev.ru void 2251267Sigor@sysoev.ru nxt_buf_parent_completion(nxt_task_t *task, nxt_buf_t *parent) 2261267Sigor@sysoev.ru { 2270Sigor@sysoev.ru if (parent != NULL) { 2281Sigor@sysoev.ru nxt_debug(task, "parent retain:%uD", parent->retain); 2290Sigor@sysoev.ru 2300Sigor@sysoev.ru parent->retain--; 2310Sigor@sysoev.ru 2320Sigor@sysoev.ru if (parent->retain == 0) { 2330Sigor@sysoev.ru parent->mem.pos = parent->mem.free; 2340Sigor@sysoev.ru 2351Sigor@sysoev.ru parent->completion_handler(task, parent, parent->parent); 2360Sigor@sysoev.ru } 2370Sigor@sysoev.ru } 2380Sigor@sysoev.ru } 239122Smax.romanov@nginx.com 240122Smax.romanov@nginx.com 241122Smax.romanov@nginx.com nxt_int_t 242122Smax.romanov@nginx.com nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data) 243122Smax.romanov@nginx.com { 244122Smax.romanov@nginx.com nxt_buf_t *b; 245122Smax.romanov@nginx.com nxt_buf_ts_t *ts; 246122Smax.romanov@nginx.com 247122Smax.romanov@nginx.com b = obj; 248122Smax.romanov@nginx.com 249564Svbart@nginx.com nxt_assert(b->is_ts != 0); 250122Smax.romanov@nginx.com 251122Smax.romanov@nginx.com ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); 252122Smax.romanov@nginx.com 253122Smax.romanov@nginx.com if (ts->engine != task->thread->engine) { 254122Smax.romanov@nginx.com 255122Smax.romanov@nginx.com nxt_debug(task, "buf ts: %p current engine is %p, expected %p", 256122Smax.romanov@nginx.com b, task->thread->engine, ts->engine); 257122Smax.romanov@nginx.com 258122Smax.romanov@nginx.com ts->work.handler = b->completion_handler; 259122Smax.romanov@nginx.com ts->work.obj = obj; 260122Smax.romanov@nginx.com ts->work.data = data; 261122Smax.romanov@nginx.com 262122Smax.romanov@nginx.com nxt_event_engine_post(ts->engine, &ts->work); 263122Smax.romanov@nginx.com 264122Smax.romanov@nginx.com return 1; 265122Smax.romanov@nginx.com } 266122Smax.romanov@nginx.com 267122Smax.romanov@nginx.com return 0; 268122Smax.romanov@nginx.com } 269122Smax.romanov@nginx.com 270122Smax.romanov@nginx.com 271122Smax.romanov@nginx.com static void 272122Smax.romanov@nginx.com nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data) 273122Smax.romanov@nginx.com { 274122Smax.romanov@nginx.com nxt_mp_t *mp; 2751269Sigor@sysoev.ru nxt_buf_t *b, *next, *parent; 276122Smax.romanov@nginx.com 277122Smax.romanov@nginx.com b = obj; 278122Smax.romanov@nginx.com parent = data; 279122Smax.romanov@nginx.com 280122Smax.romanov@nginx.com if (nxt_buf_ts_handle(task, obj, data)) { 281122Smax.romanov@nginx.com return; 282122Smax.romanov@nginx.com } 283122Smax.romanov@nginx.com 284122Smax.romanov@nginx.com nxt_debug(task, "buf ts completion: %p %p", b, b->mem.start); 285122Smax.romanov@nginx.com 286564Svbart@nginx.com nxt_assert(data == b->parent); 287122Smax.romanov@nginx.com 2881269Sigor@sysoev.ru do { 2891269Sigor@sysoev.ru next = b->next; 2901269Sigor@sysoev.ru parent = b->parent; 2911269Sigor@sysoev.ru mp = b->data; 292122Smax.romanov@nginx.com 2931269Sigor@sysoev.ru nxt_mp_free(mp, b); 2941269Sigor@sysoev.ru nxt_mp_release(mp); 2951269Sigor@sysoev.ru 2961269Sigor@sysoev.ru nxt_buf_parent_completion(task, parent); 2971269Sigor@sysoev.ru 2981269Sigor@sysoev.ru b = next; 2991269Sigor@sysoev.ru } while (b != NULL); 300122Smax.romanov@nginx.com } 301352Smax.romanov@nginx.com 302352Smax.romanov@nginx.com 303352Smax.romanov@nginx.com nxt_buf_t * 304352Smax.romanov@nginx.com nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size) 305352Smax.romanov@nginx.com { 306352Smax.romanov@nginx.com nxt_buf_t *b, *i; 307352Smax.romanov@nginx.com 308352Smax.romanov@nginx.com if (nxt_slow_path(size == 0)) { 309352Smax.romanov@nginx.com for (i = src; i != NULL; i = i->next) { 310352Smax.romanov@nginx.com size += nxt_buf_used_size(i); 311352Smax.romanov@nginx.com } 312352Smax.romanov@nginx.com } 313352Smax.romanov@nginx.com 314352Smax.romanov@nginx.com b = nxt_buf_mem_alloc(mp, size, 0); 315352Smax.romanov@nginx.com 316352Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 317352Smax.romanov@nginx.com return NULL; 318352Smax.romanov@nginx.com } 319352Smax.romanov@nginx.com 320352Smax.romanov@nginx.com for (i = src; i != NULL; i = i->next) { 321613Svbart@nginx.com if (nxt_slow_path(nxt_buf_mem_free_size(&b->mem) 322613Svbart@nginx.com < nxt_buf_used_size(i))) 323613Svbart@nginx.com { 324352Smax.romanov@nginx.com break; 325352Smax.romanov@nginx.com } 326352Smax.romanov@nginx.com 327352Smax.romanov@nginx.com b->mem.free = nxt_cpymem(b->mem.free, i->mem.pos, nxt_buf_used_size(i)); 328352Smax.romanov@nginx.com } 329352Smax.romanov@nginx.com 330352Smax.romanov@nginx.com return b; 331352Smax.romanov@nginx.com } 332