1 2 /* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7 #include <nxt_main.h> 8 9 10 static void nxt_buf_completion(nxt_task_t *task, void *obj, void *data); 11 12 13 nxt_buf_t * 14 nxt_buf_mem_alloc(nxt_mem_pool_t *mp, size_t size, nxt_uint_t flags) 15 { 16 nxt_buf_t *b; 17 18 b = nxt_mem_cache_zalloc0(mp, NXT_BUF_MEM_SIZE); 19 if (nxt_slow_path(b == NULL)) { 20 return NULL; 21 } 22 23 b->data = mp; 24 b->completion_handler = nxt_buf_completion; 25 b->size = NXT_BUF_MEM_SIZE; 26 27 if (size != 0) { 28 b->mem.start = nxt_mem_buf(mp, &size, flags); 29 if (nxt_slow_path(b->mem.start == NULL)) { 30 return NULL; 31 } 32 33 b->mem.pos = b->mem.start; 34 b->mem.free = b->mem.start; 35 b->mem.end = b->mem.start + size; 36 } 37 38 return b; 39 } 40 41 42 nxt_buf_t * 43 nxt_buf_file_alloc(nxt_mem_pool_t *mp, size_t size, nxt_uint_t flags) 44 { 45 nxt_buf_t *b; 46 47 b = nxt_mem_cache_zalloc0(mp, NXT_BUF_FILE_SIZE); 48 if (nxt_slow_path(b == NULL)) { 49 return NULL; 50 } 51 52 b->data = mp; 53 b->completion_handler = nxt_buf_completion; 54 b->size = NXT_BUF_FILE_SIZE; 55 nxt_buf_set_file(b); 56 57 if (size != 0) { 58 b->mem.start = nxt_mem_buf(mp, &size, flags); 59 if (nxt_slow_path(b->mem.start == NULL)) { 60 return NULL; 61 } 62 63 b->mem.pos = b->mem.start; 64 b->mem.free = b->mem.start; 65 b->mem.end = b->mem.start + size; 66 } 67 68 return b; 69 } 70 71 72 nxt_buf_t * 73 nxt_buf_mmap_alloc(nxt_mem_pool_t *mp, size_t size) 74 { 75 nxt_buf_t *b; 76 77 b = nxt_mem_cache_zalloc0(mp, NXT_BUF_MMAP_SIZE); 78 79 if (nxt_fast_path(b != NULL)) { 80 b->data = mp; 81 b->completion_handler = nxt_buf_completion; 82 b->size = NXT_BUF_MMAP_SIZE; 83 84 nxt_buf_set_file(b); 85 nxt_buf_set_mmap(b); 86 nxt_buf_mem_set_size(&b->mem, size); 87 } 88 89 return b; 90 } 91 92 93 nxt_buf_t * 94 nxt_buf_sync_alloc(nxt_mem_pool_t *mp, nxt_uint_t flags) 95 { 96 nxt_buf_t *b; 97 98 b = nxt_mem_cache_zalloc0(mp, NXT_BUF_SYNC_SIZE); 99 100 if (nxt_fast_path(b != NULL)) { 101 b->data = mp; 102 b->completion_handler = nxt_buf_completion; 103 b->size = NXT_BUF_SYNC_SIZE; 104 105 nxt_buf_set_sync(b); 106 b->is_nobuf = ((flags & NXT_BUF_SYNC_NOBUF) != 0); 107 b->is_flush = ((flags & NXT_BUF_SYNC_FLUSH) != 0); 108 b->is_last = ((flags & NXT_BUF_SYNC_LAST) != 0); 109 } 110 111 return b; 112 } 113 114 115 void 116 nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in) 117 { 118 nxt_buf_t *b, **prev; 119 120 prev = head; 121 122 for (b = *head; b != NULL; b = b->next) { 123 prev = &b->next; 124 } 125 126 *prev = in; 127 } 128 129 130 size_t 131 nxt_buf_chain_length(nxt_buf_t *b) 132 { 133 size_t length; 134 135 length = 0; 136 137 while (b != NULL) { 138 length += b->mem.free - b->mem.pos; 139 b = b->next; 140 } 141 142 return length; 143 } 144 145 146 static void 147 nxt_buf_completion(nxt_task_t *task, void *obj, void *data) 148 { 149 nxt_buf_t *b, *parent; 150 nxt_mem_pool_t *mp; 151 152 b = obj; 153 parent = data; 154 155 nxt_debug(task, "buf completion: %p %p", b, b->mem.start); 156 157 mp = b->data; 158 nxt_buf_free(mp, b); 159 160 if (parent != NULL) { 161 nxt_debug(task, "parent retain:%uD", parent->retain); 162 163 parent->retain--; 164 165 if (parent->retain == 0) { 166 parent->mem.pos = parent->mem.free; 167 168 parent->completion_handler(task, parent, parent->parent); 169 } 170 } 171 } 172