1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_main.h> 8 9 10static void nxt_buf_completion(nxt_task_t *task, void *obj, void *data); 11static void nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data); 12 13 14typedef struct { 15 nxt_work_t work; 16 nxt_event_engine_t *engine; 17} nxt_buf_ts_t; 18 19 20void 21nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size) 22{ 23 b->mem.start = start; 24 b->mem.pos = start; 25 b->mem.free = start; 26 b->mem.end = nxt_pointer_to(start, size); 27} 28 29 30nxt_buf_t * 31nxt_buf_mem_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags) 32{ 33 nxt_buf_t *b; 34 35 b = nxt_mp_alloc(mp, NXT_BUF_MEM_SIZE + size); 36 if (nxt_slow_path(b == NULL)) { 37 return NULL; 38 } 39 40 nxt_memzero(b, NXT_BUF_MEM_SIZE); 41 42 b->data = mp; 43 b->completion_handler = nxt_buf_completion; 44 45 if (size != 0) { 46 b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); 47 b->mem.pos = b->mem.start; 48 b->mem.free = b->mem.start; 49 b->mem.end = b->mem.start + size; 50 } 51 52 return b; 53} 54 55 56nxt_buf_t * 57nxt_buf_mem_ts_alloc(nxt_task_t *task, nxt_mp_t *mp, size_t size) 58{ 59 nxt_buf_t *b; 60 nxt_buf_ts_t *ts; 61 62 b = nxt_mp_alloc(mp, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t) + size); 63 if (nxt_slow_path(b == NULL)) { 64 return NULL; 65 } 66 67 nxt_mp_retain(mp); 68 69 nxt_memzero(b, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t)); 70 71 b->data = mp; 72 b->completion_handler = nxt_buf_ts_completion; 73 b->is_ts = 1; 74 75 if (size != 0) { 76 b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE 77 + sizeof(nxt_buf_ts_t)); 78 b->mem.pos = b->mem.start; 79 b->mem.free = b->mem.start; 80 b->mem.end = b->mem.start + size; 81 } 82 83 ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); 84 ts->engine = task->thread->engine; 85 86 ts->work.handler = nxt_buf_ts_completion; 87 ts->work.task = task; 88 ts->work.obj = b; 89 ts->work.data = b->parent; 90 91 return b; 92} 93 94 95nxt_buf_t * 96nxt_buf_file_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags) 97{ 98 nxt_buf_t *b; 99 100 b = nxt_mp_alloc(mp, NXT_BUF_FILE_SIZE + size); 101 if (nxt_slow_path(b == NULL)) { 102 return NULL; 103 } 104 105 nxt_memzero(b, NXT_BUF_FILE_SIZE); 106 107 b->data = mp; 108 b->completion_handler = nxt_buf_completion; 109 nxt_buf_set_file(b); 110 111 if (size != 0) { 112 b->mem.start = nxt_pointer_to(b, NXT_BUF_FILE_SIZE); 113 b->mem.pos = b->mem.start; 114 b->mem.free = b->mem.start; 115 b->mem.end = b->mem.start + size; 116 } 117 118 return b; 119} 120 121 122nxt_buf_t * 123nxt_buf_mmap_alloc(nxt_mp_t *mp, size_t size) 124{ 125 nxt_buf_t *b; 126 127 b = nxt_mp_zalloc(mp, NXT_BUF_MMAP_SIZE); 128 129 if (nxt_fast_path(b != NULL)) { 130 b->data = mp; 131 b->completion_handler = nxt_buf_completion; 132 133 nxt_buf_set_file(b); 134 nxt_buf_set_mmap(b); 135 nxt_buf_mem_set_size(&b->mem, size); 136 } 137 138 return b; 139} 140 141 142nxt_buf_t * 143nxt_buf_sync_alloc(nxt_mp_t *mp, nxt_uint_t flags) 144{ 145 nxt_buf_t *b; 146 147 b = nxt_mp_zalloc(mp, NXT_BUF_MEM_SIZE); 148 149 if (nxt_fast_path(b != NULL)) { 150 b->data = mp; 151 b->completion_handler = nxt_buf_completion; 152 153 nxt_buf_set_sync(b); 154 b->is_nobuf = ((flags & NXT_BUF_SYNC_NOBUF) != 0); 155 b->is_flush = ((flags & NXT_BUF_SYNC_FLUSH) != 0); 156 b->is_last = ((flags & NXT_BUF_SYNC_LAST) != 0); 157 } 158 159 return b; 160} 161 162 163void 164nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in) 165{ 166 nxt_buf_t *b, **prev; 167 168 prev = head; 169 170 for (b = *head; b != NULL; b = b->next) { 171 prev = &b->next; 172 } 173 174 *prev = in; 175} 176 177 178size_t 179nxt_buf_chain_length(nxt_buf_t *b) 180{ 181 size_t length; 182 183 length = 0; 184 185 while (b != NULL) {
| 1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_main.h> 8 9 10static void nxt_buf_completion(nxt_task_t *task, void *obj, void *data); 11static void nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data); 12 13 14typedef struct { 15 nxt_work_t work; 16 nxt_event_engine_t *engine; 17} nxt_buf_ts_t; 18 19 20void 21nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size) 22{ 23 b->mem.start = start; 24 b->mem.pos = start; 25 b->mem.free = start; 26 b->mem.end = nxt_pointer_to(start, size); 27} 28 29 30nxt_buf_t * 31nxt_buf_mem_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags) 32{ 33 nxt_buf_t *b; 34 35 b = nxt_mp_alloc(mp, NXT_BUF_MEM_SIZE + size); 36 if (nxt_slow_path(b == NULL)) { 37 return NULL; 38 } 39 40 nxt_memzero(b, NXT_BUF_MEM_SIZE); 41 42 b->data = mp; 43 b->completion_handler = nxt_buf_completion; 44 45 if (size != 0) { 46 b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); 47 b->mem.pos = b->mem.start; 48 b->mem.free = b->mem.start; 49 b->mem.end = b->mem.start + size; 50 } 51 52 return b; 53} 54 55 56nxt_buf_t * 57nxt_buf_mem_ts_alloc(nxt_task_t *task, nxt_mp_t *mp, size_t size) 58{ 59 nxt_buf_t *b; 60 nxt_buf_ts_t *ts; 61 62 b = nxt_mp_alloc(mp, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t) + size); 63 if (nxt_slow_path(b == NULL)) { 64 return NULL; 65 } 66 67 nxt_mp_retain(mp); 68 69 nxt_memzero(b, NXT_BUF_MEM_SIZE + sizeof(nxt_buf_ts_t)); 70 71 b->data = mp; 72 b->completion_handler = nxt_buf_ts_completion; 73 b->is_ts = 1; 74 75 if (size != 0) { 76 b->mem.start = nxt_pointer_to(b, NXT_BUF_MEM_SIZE 77 + sizeof(nxt_buf_ts_t)); 78 b->mem.pos = b->mem.start; 79 b->mem.free = b->mem.start; 80 b->mem.end = b->mem.start + size; 81 } 82 83 ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); 84 ts->engine = task->thread->engine; 85 86 ts->work.handler = nxt_buf_ts_completion; 87 ts->work.task = task; 88 ts->work.obj = b; 89 ts->work.data = b->parent; 90 91 return b; 92} 93 94 95nxt_buf_t * 96nxt_buf_file_alloc(nxt_mp_t *mp, size_t size, nxt_uint_t flags) 97{ 98 nxt_buf_t *b; 99 100 b = nxt_mp_alloc(mp, NXT_BUF_FILE_SIZE + size); 101 if (nxt_slow_path(b == NULL)) { 102 return NULL; 103 } 104 105 nxt_memzero(b, NXT_BUF_FILE_SIZE); 106 107 b->data = mp; 108 b->completion_handler = nxt_buf_completion; 109 nxt_buf_set_file(b); 110 111 if (size != 0) { 112 b->mem.start = nxt_pointer_to(b, NXT_BUF_FILE_SIZE); 113 b->mem.pos = b->mem.start; 114 b->mem.free = b->mem.start; 115 b->mem.end = b->mem.start + size; 116 } 117 118 return b; 119} 120 121 122nxt_buf_t * 123nxt_buf_mmap_alloc(nxt_mp_t *mp, size_t size) 124{ 125 nxt_buf_t *b; 126 127 b = nxt_mp_zalloc(mp, NXT_BUF_MMAP_SIZE); 128 129 if (nxt_fast_path(b != NULL)) { 130 b->data = mp; 131 b->completion_handler = nxt_buf_completion; 132 133 nxt_buf_set_file(b); 134 nxt_buf_set_mmap(b); 135 nxt_buf_mem_set_size(&b->mem, size); 136 } 137 138 return b; 139} 140 141 142nxt_buf_t * 143nxt_buf_sync_alloc(nxt_mp_t *mp, nxt_uint_t flags) 144{ 145 nxt_buf_t *b; 146 147 b = nxt_mp_zalloc(mp, NXT_BUF_MEM_SIZE); 148 149 if (nxt_fast_path(b != NULL)) { 150 b->data = mp; 151 b->completion_handler = nxt_buf_completion; 152 153 nxt_buf_set_sync(b); 154 b->is_nobuf = ((flags & NXT_BUF_SYNC_NOBUF) != 0); 155 b->is_flush = ((flags & NXT_BUF_SYNC_FLUSH) != 0); 156 b->is_last = ((flags & NXT_BUF_SYNC_LAST) != 0); 157 } 158 159 return b; 160} 161 162 163void 164nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in) 165{ 166 nxt_buf_t *b, **prev; 167 168 prev = head; 169 170 for (b = *head; b != NULL; b = b->next) { 171 prev = &b->next; 172 } 173 174 *prev = in; 175} 176 177 178size_t 179nxt_buf_chain_length(nxt_buf_t *b) 180{ 181 size_t length; 182 183 length = 0; 184 185 while (b != NULL) {
|
187 b = b->next; 188 } 189 190 return length; 191} 192 193 194static void 195nxt_buf_completion(nxt_task_t *task, void *obj, void *data) 196{ 197 nxt_mp_t *mp; 198 nxt_buf_t *b, *next, *parent; 199 200 b = obj; 201 parent = data; 202 203 nxt_debug(task, "buf completion: %p %p", b, b->mem.start); 204 205 nxt_assert(data == b->parent); 206 207 do { 208 next = b->next; 209 parent = b->parent; 210 mp = b->data; 211 212 nxt_mp_free(mp, b); 213 214 nxt_buf_parent_completion(task, parent); 215 216 b = next; 217 } while (b != NULL); 218} 219 220 221void 222nxt_buf_parent_completion(nxt_task_t *task, nxt_buf_t *parent) 223{ 224 if (parent != NULL) { 225 nxt_debug(task, "parent retain:%uD", parent->retain); 226 227 parent->retain--; 228 229 if (parent->retain == 0) { 230 parent->mem.pos = parent->mem.free; 231 232 parent->completion_handler(task, parent, parent->parent); 233 } 234 } 235} 236 237 238nxt_int_t 239nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data) 240{ 241 nxt_buf_t *b; 242 nxt_buf_ts_t *ts; 243 244 b = obj; 245 246 nxt_assert(b->is_ts != 0); 247 248 ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); 249 250 if (ts->engine != task->thread->engine) { 251 252 nxt_debug(task, "buf ts: %p current engine is %p, expected %p", 253 b, task->thread->engine, ts->engine); 254 255 ts->work.handler = b->completion_handler; 256 ts->work.obj = obj; 257 ts->work.data = data; 258 259 nxt_event_engine_post(ts->engine, &ts->work); 260 261 return 1; 262 } 263 264 return 0; 265} 266 267 268static void 269nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data) 270{ 271 nxt_mp_t *mp; 272 nxt_buf_t *b, *next, *parent; 273 274 b = obj; 275 parent = data; 276 277 if (nxt_buf_ts_handle(task, obj, data)) { 278 return; 279 } 280 281 nxt_debug(task, "buf ts completion: %p %p", b, b->mem.start); 282 283 nxt_assert(data == b->parent); 284 285 do { 286 next = b->next; 287 parent = b->parent; 288 mp = b->data; 289 290 nxt_mp_free(mp, b); 291 nxt_mp_release(mp); 292 293 nxt_buf_parent_completion(task, parent); 294 295 b = next; 296 } while (b != NULL); 297} 298 299 300nxt_buf_t * 301nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size) 302{ 303 nxt_buf_t *b, *i; 304 305 if (nxt_slow_path(size == 0)) { 306 for (i = src; i != NULL; i = i->next) { 307 size += nxt_buf_used_size(i); 308 } 309 } 310 311 b = nxt_buf_mem_alloc(mp, size, 0); 312 313 if (nxt_slow_path(b == NULL)) { 314 return NULL; 315 } 316 317 for (i = src; i != NULL; i = i->next) { 318 if (nxt_slow_path(nxt_buf_mem_free_size(&b->mem) 319 < nxt_buf_used_size(i))) 320 { 321 break; 322 } 323 324 b->mem.free = nxt_cpymem(b->mem.free, i->mem.pos, nxt_buf_used_size(i)); 325 } 326 327 return b; 328}
| 190 b = b->next; 191 } 192 193 return length; 194} 195 196 197static void 198nxt_buf_completion(nxt_task_t *task, void *obj, void *data) 199{ 200 nxt_mp_t *mp; 201 nxt_buf_t *b, *next, *parent; 202 203 b = obj; 204 parent = data; 205 206 nxt_debug(task, "buf completion: %p %p", b, b->mem.start); 207 208 nxt_assert(data == b->parent); 209 210 do { 211 next = b->next; 212 parent = b->parent; 213 mp = b->data; 214 215 nxt_mp_free(mp, b); 216 217 nxt_buf_parent_completion(task, parent); 218 219 b = next; 220 } while (b != NULL); 221} 222 223 224void 225nxt_buf_parent_completion(nxt_task_t *task, nxt_buf_t *parent) 226{ 227 if (parent != NULL) { 228 nxt_debug(task, "parent retain:%uD", parent->retain); 229 230 parent->retain--; 231 232 if (parent->retain == 0) { 233 parent->mem.pos = parent->mem.free; 234 235 parent->completion_handler(task, parent, parent->parent); 236 } 237 } 238} 239 240 241nxt_int_t 242nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data) 243{ 244 nxt_buf_t *b; 245 nxt_buf_ts_t *ts; 246 247 b = obj; 248 249 nxt_assert(b->is_ts != 0); 250 251 ts = nxt_pointer_to(b, NXT_BUF_MEM_SIZE); 252 253 if (ts->engine != task->thread->engine) { 254 255 nxt_debug(task, "buf ts: %p current engine is %p, expected %p", 256 b, task->thread->engine, ts->engine); 257 258 ts->work.handler = b->completion_handler; 259 ts->work.obj = obj; 260 ts->work.data = data; 261 262 nxt_event_engine_post(ts->engine, &ts->work); 263 264 return 1; 265 } 266 267 return 0; 268} 269 270 271static void 272nxt_buf_ts_completion(nxt_task_t *task, void *obj, void *data) 273{ 274 nxt_mp_t *mp; 275 nxt_buf_t *b, *next, *parent; 276 277 b = obj; 278 parent = data; 279 280 if (nxt_buf_ts_handle(task, obj, data)) { 281 return; 282 } 283 284 nxt_debug(task, "buf ts completion: %p %p", b, b->mem.start); 285 286 nxt_assert(data == b->parent); 287 288 do { 289 next = b->next; 290 parent = b->parent; 291 mp = b->data; 292 293 nxt_mp_free(mp, b); 294 nxt_mp_release(mp); 295 296 nxt_buf_parent_completion(task, parent); 297 298 b = next; 299 } while (b != NULL); 300} 301 302 303nxt_buf_t * 304nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size) 305{ 306 nxt_buf_t *b, *i; 307 308 if (nxt_slow_path(size == 0)) { 309 for (i = src; i != NULL; i = i->next) { 310 size += nxt_buf_used_size(i); 311 } 312 } 313 314 b = nxt_buf_mem_alloc(mp, size, 0); 315 316 if (nxt_slow_path(b == NULL)) { 317 return NULL; 318 } 319 320 for (i = src; i != NULL; i = i->next) { 321 if (nxt_slow_path(nxt_buf_mem_free_size(&b->mem) 322 < nxt_buf_used_size(i))) 323 { 324 break; 325 } 326 327 b->mem.free = nxt_cpymem(b->mem.free, i->mem.pos, nxt_buf_used_size(i)); 328 } 329 330 return b; 331}
|