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) { 76*613Svbart@nginx.com b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE 77*613Svbart@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) { 1860Sigor@sysoev.ru length += b->mem.free - b->mem.pos; 1870Sigor@sysoev.ru b = b->next; 1880Sigor@sysoev.ru } 1890Sigor@sysoev.ru 1900Sigor@sysoev.ru return length; 1910Sigor@sysoev.ru } 1920Sigor@sysoev.ru 1930Sigor@sysoev.ru 1940Sigor@sysoev.ru static void 1951Sigor@sysoev.ru nxt_buf_completion(nxt_task_t *task, void *obj, void *data) 1960Sigor@sysoev.ru { 19765Sigor@sysoev.ru nxt_mp_t *mp; 19865Sigor@sysoev.ru nxt_buf_t *b, *parent; 1990Sigor@sysoev.ru 2000Sigor@sysoev.ru b = obj; 2010Sigor@sysoev.ru parent = data; 2020Sigor@sysoev.ru 2031Sigor@sysoev.ru nxt_debug(task, "buf completion: %p %p", b, b->mem.start); 2040Sigor@sysoev.ru 205564Svbart@nginx.com nxt_assert(data == b->parent); 206122Smax.romanov@nginx.com 2070Sigor@sysoev.ru mp = b->data; 208122Smax.romanov@nginx.com nxt_mp_free(mp, b); 2090Sigor@sysoev.ru 2100Sigor@sysoev.ru if (parent != NULL) { 2111Sigor@sysoev.ru nxt_debug(task, "parent retain:%uD", parent->retain); 2120Sigor@sysoev.ru 2130Sigor@sysoev.ru parent->retain--; 2140Sigor@sysoev.ru 2150Sigor@sysoev.ru if (parent->retain == 0) { 2160Sigor@sysoev.ru parent->mem.pos = parent->mem.free; 2170Sigor@sysoev.ru 2181Sigor@sysoev.ru parent->completion_handler(task, parent, parent->parent); 2190Sigor@sysoev.ru } 2200Sigor@sysoev.ru } 2210Sigor@sysoev.ru } 222122Smax.romanov@nginx.com 223122Smax.romanov@nginx.com 224122Smax.romanov@nginx.com nxt_int_t 225122Smax.romanov@nginx.com nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data) 226122Smax.romanov@nginx.com { 227122Smax.romanov@nginx.com nxt_buf_t *b; 228122Smax.romanov@nginx.com nxt_buf_ts_t *ts; 229122Smax.romanov@nginx.com 230122Smax.romanov@nginx.com b = obj; 231122Smax.romanov@nginx.com 232564Svbart@nginx.com nxt_assert(b->is_ts != 0); 233122Smax.romanov@nginx.com 234122Smax.romanov@nginx.com ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); 235122Smax.romanov@nginx.com 236122Smax.romanov@nginx.com if (ts->engine != task->thread->engine) { 237122Smax.romanov@nginx.com 238122Smax.romanov@nginx.com nxt_debug(task, "buf ts: %p current engine is %p, expected %p", 239122Smax.romanov@nginx.com b, task->thread->engine, ts->engine); 240122Smax.romanov@nginx.com 241122Smax.romanov@nginx.com ts->work.handler = b->completion_handler; 242122Smax.romanov@nginx.com ts->work.obj = obj; 243122Smax.romanov@nginx.com ts->work.data = data; 244122Smax.romanov@nginx.com 245122Smax.romanov@nginx.com nxt_event_engine_post(ts->engine, &ts->work); 246122Smax.romanov@nginx.com 247122Smax.romanov@nginx.com return 1; 248122Smax.romanov@nginx.com } 249122Smax.romanov@nginx.com 250122Smax.romanov@nginx.com return 0; 251122Smax.romanov@nginx.com } 252122Smax.romanov@nginx.com 253122Smax.romanov@nginx.com 254122Smax.romanov@nginx.com static void 255122Smax.romanov@nginx.com nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data) 256122Smax.romanov@nginx.com { 257122Smax.romanov@nginx.com nxt_mp_t *mp; 258122Smax.romanov@nginx.com nxt_buf_t *b, *parent; 259122Smax.romanov@nginx.com 260122Smax.romanov@nginx.com b = obj; 261122Smax.romanov@nginx.com parent = data; 262122Smax.romanov@nginx.com 263122Smax.romanov@nginx.com if (nxt_buf_ts_handle(task, obj, data)) { 264122Smax.romanov@nginx.com return; 265122Smax.romanov@nginx.com } 266122Smax.romanov@nginx.com 267122Smax.romanov@nginx.com nxt_debug(task, "buf ts completion: %p %p", b, b->mem.start); 268122Smax.romanov@nginx.com 269564Svbart@nginx.com nxt_assert(data == b->parent); 270122Smax.romanov@nginx.com 271122Smax.romanov@nginx.com mp = b->data; 272430Sigor@sysoev.ru nxt_mp_free(mp, b); 273430Sigor@sysoev.ru nxt_mp_release(mp); 274122Smax.romanov@nginx.com 275122Smax.romanov@nginx.com if (parent != NULL) { 276122Smax.romanov@nginx.com nxt_debug(task, "parent retain:%uD", parent->retain); 277122Smax.romanov@nginx.com 278122Smax.romanov@nginx.com parent->retain--; 279122Smax.romanov@nginx.com 280122Smax.romanov@nginx.com if (parent->retain == 0) { 281122Smax.romanov@nginx.com parent->mem.pos = parent->mem.free; 282122Smax.romanov@nginx.com 283122Smax.romanov@nginx.com parent->completion_handler(task, parent, parent->parent); 284122Smax.romanov@nginx.com } 285122Smax.romanov@nginx.com } 286122Smax.romanov@nginx.com } 287352Smax.romanov@nginx.com 288352Smax.romanov@nginx.com 289352Smax.romanov@nginx.com nxt_buf_t * 290352Smax.romanov@nginx.com nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size) 291352Smax.romanov@nginx.com { 292352Smax.romanov@nginx.com nxt_buf_t *b, *i; 293352Smax.romanov@nginx.com 294352Smax.romanov@nginx.com if (nxt_slow_path(size == 0)) { 295352Smax.romanov@nginx.com for (i = src; i != NULL; i = i->next) { 296352Smax.romanov@nginx.com size += nxt_buf_used_size(i); 297352Smax.romanov@nginx.com } 298352Smax.romanov@nginx.com } 299352Smax.romanov@nginx.com 300352Smax.romanov@nginx.com b = nxt_buf_mem_alloc(mp, size, 0); 301352Smax.romanov@nginx.com 302352Smax.romanov@nginx.com if (nxt_slow_path(b == NULL)) { 303352Smax.romanov@nginx.com return NULL; 304352Smax.romanov@nginx.com } 305352Smax.romanov@nginx.com 306352Smax.romanov@nginx.com for (i = src; i != NULL; i = i->next) { 307*613Svbart@nginx.com if (nxt_slow_path(nxt_buf_mem_free_size(&b->mem) 308*613Svbart@nginx.com < nxt_buf_used_size(i))) 309*613Svbart@nginx.com { 310352Smax.romanov@nginx.com break; 311352Smax.romanov@nginx.com } 312352Smax.romanov@nginx.com 313352Smax.romanov@nginx.com b->mem.free = nxt_cpymem(b->mem.free, i->mem.pos, nxt_buf_used_size(i)); 314352Smax.romanov@nginx.com } 315352Smax.romanov@nginx.com 316352Smax.romanov@nginx.com return b; 317352Smax.romanov@nginx.com } 318