nxt_buf.c (1269:41331471eee7) nxt_buf.c (1271:d9c8ee25590a)
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) {
186 length += b->mem.free - b->mem.pos;
186 if (!nxt_buf_is_sync(b)) {
187 length += b->mem.free - b->mem.pos;
188 }
189
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}