xref: /unit/src/nxt_buf.c (revision 1:fdc027c56872)
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