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