xref: /unit/src/nxt_buf.h (revision 2084:7d479274f334)
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #ifndef _NXT_BUF_H_INCLUDED_
8 #define _NXT_BUF_H_INCLUDED_
9 
10 
11 /*
12  * There are four types of buffers.  They are different sizes, so they
13  * should be allocated by appropriate nxt_buf_XXX_alloc() function.
14  *
15  * 1) Memory-only buffers, their size is less than nxt_buf_t size, it
16  *    is equal to offsetof(nxt_buf_t, file_pos), that is it is nxt_buf_t
17  *    without file and mmap part.  The buffers are frequently used, so
18  *    the reduction allows to save 20-32 bytes depending on platform.
19  *
20  * 2) Memory/file buffers, on Unix their size is exactly nxt_buf_t size,
21  *    since nxt_mem_map_file_ctx_t() is empty macro.  On Windows the size
22  *    equals offsetof(nxt_buf_t, mmap), that is it is nxt_buf_t without
23  *    memory map context part.  The buffers can contain both memory and
24  *    file pointers at once, or only memory or file pointers.
25  *
26  * 3) Memory mapped buffers are similar to the memory/file buffers.  Their
27  *    size is exactly nxt_buf_t size.  The buffers can contain both memory
28  *    and file pointers at once, or only memory or file pointers.  If a
29  *    buffer is not currently mapped in memory, its mapping size is stored
30  *    in the mem.end field and available via nxt_buf_mem_size() macro.
31  *
32  * 4) Sync buffers, their size is the same size as memory-only buffers
33  *    size.  A sync buffer can be smaller but for memory pool cache
34  *    purpose it is better to allocate it as frequently used memory-only
35  *    buffer.  The buffers are used to synchronize pipeline processing
36  *    completion, because data buffers in the pipeline can be completed
37  *    and freed before their final output will even be passed to a peer.
38  *    For this purpose a sync buffer is allocated with the stop flag which
39  *    stops buffer chain completion processing on the sync buffer in
40  *    nxt_sendbuf_update() and nxt_sendbuf_completion().
41  *    Clearing the stop flag allows to continue completion processing.
42  *
43  *    The last flag means the end of the output and must be set only
44  *    in a sync buffer.  The last flag is not permitted in memory and
45  *    file buffers since it requires special handling while conversion
46  *    one buffer to another.
47  *
48  *    The nxt_buf_used_size() macro treats a sync buffer as a memory-only
49  *    buffer which has NULL pointers, thus the buffer content size is zero.
50  *    If allocated size of sync buffer would be lesser than memory-only
51  *    buffer, then the special memory flag would be required because
52  *    currently presence of memory part is indicated by non-NULL pointer
53  *    to a content in memory.
54  *
55  *    All types of buffers can have the flush flag that means the buffer
56  *    should be sent as much as possible.
57  */
58 
59 typedef struct {
60     u_char                  *pos;
61     u_char                  *free;
62     u_char                  *start;
63     u_char                  *end;
64 } nxt_buf_mem_t;
65 
66 
67 struct nxt_buf_s {
68     void                    *data;
69     nxt_work_handler_t      completion_handler;
70     void                    *parent;
71 
72     /*
73      * The next link, flags, and nxt_buf_mem_t should
74      * reside together to improve cache locality.
75      */
76     nxt_buf_t               *next;
77 
78     uint32_t                retain;
79 
80     uint8_t                 cache_hint;
81 
82     uint8_t                 is_file:1;
83     uint8_t                 is_mmap:1;
84     uint8_t                 is_port_mmap:1;
85     uint8_t                 is_sync:1;
86     uint8_t                 is_nobuf:1;
87     uint8_t                 is_flush:1;
88     uint8_t                 is_last:1;
89     uint8_t                 is_port_mmap_sent:1;
90     uint8_t                 is_ts:1;
91 
92     nxt_buf_mem_t           mem;
93 
94     /* The file and mmap parts are not allocated by nxt_buf_mem_alloc(). */
95     nxt_file_t              *file;
96     nxt_off_t               file_pos;
97     nxt_off_t               file_end;
98 
99     /* The mmap part is not allocated by nxt_buf_file_alloc(). */
100     nxt_mem_map_file_ctx_t  (mmap)
101 };
102 
103 
104 #define NXT_BUF_SYNC_SIZE       offsetof(nxt_buf_t, mem.free)
105 #define NXT_BUF_MEM_SIZE        offsetof(nxt_buf_t, file)
106 #define NXT_BUF_FILE_SIZE       sizeof(nxt_buf_t)
107 #define NXT_BUF_MMAP_SIZE       NXT_BUF_FILE_SIZE
108 #define NXT_BUF_PORT_MMAP_SIZE  NXT_BUF_MEM_SIZE
109 
110 
111 #define NXT_BUF_SYNC_NOBUF  1
112 #define NXT_BUF_SYNC_FLUSH  2
113 #define NXT_BUF_SYNC_LAST   4
114 
115 
116 #define nxt_buf_is_mem(b)                                                     \
117     ((b)->mem.pos != NULL)
118 
119 
120 #define nxt_buf_is_file(b)                                                    \
121     ((b)->is_file)
122 
123 #define nxt_buf_set_file(b)                                                   \
124     (b)->is_file = 1
125 
126 #define nxt_buf_clear_file(b)                                                 \
127     (b)->is_file = 0
128 
129 
130 #define nxt_buf_is_mmap(b)                                                    \
131     ((b)->is_mmap)
132 
133 #define nxt_buf_set_mmap(b)                                                   \
134     (b)->is_mmap = 1
135 
136 #define nxt_buf_clear_mmap(b)                                                 \
137     (b)->is_mmap = 0
138 
139 
140 #define nxt_buf_is_port_mmap(b)                                               \
141     ((b)->is_port_mmap)
142 
143 #define nxt_buf_set_port_mmap(b)                                              \
144     (b)->is_port_mmap = 1
145 
146 #define nxt_buf_clear_port_mmap(b)                                            \
147     (b)->is_port_mmap = 0
148 
149 
150 #define nxt_buf_is_sync(b)                                                    \
151     ((b)->is_sync)
152 
153 #define nxt_buf_set_sync(b)                                                   \
154     (b)->is_sync = 1
155 
156 #define nxt_buf_clear_sync(b)                                                 \
157     (b)->is_sync = 0
158 
159 
160 #define nxt_buf_is_nobuf(b)                                                   \
161     ((b)->is_nobuf)
162 
163 #define nxt_buf_set_nobuf(b)                                                  \
164     (b)->is_nobuf = 1
165 
166 #define nxt_buf_clear_nobuf(b)                                                \
167     (b)->is_nobuf = 0
168 
169 
170 #define nxt_buf_is_flush(b)                                                   \
171     ((b)->is_flush)
172 
173 #define nxt_buf_set_flush(b)                                                  \
174     (b)->is_flush = 1
175 
176 #define nxt_buf_clear_flush(b)                                                \
177     (b)->is_flush = 0
178 
179 
180 #define nxt_buf_is_last(b)                                                    \
181     ((b)->is_last)
182 
183 #define nxt_buf_set_last(b)                                                   \
184     (b)->is_last = 1
185 
186 #define nxt_buf_clear_last(b)                                                 \
187     (b)->is_last = 0
188 
189 
190 #define nxt_buf_mem_set_size(bm, size)                                        \
191     do {                                                                      \
192         (bm)->start = 0;                                                      \
193         (bm)->end = (void *) size;                                            \
194     } while (0)
195 
196 
197 #define nxt_buf_mem_size(bm)                                                  \
198     ((bm)->end - (bm)->start)
199 
200 
201 #define nxt_buf_mem_used_size(bm)                                             \
202     ((bm)->free - (bm)->pos)
203 
204 
205 #define nxt_buf_mem_free_size(bm)                                             \
206     ((bm)->end - (bm)->free)
207 
208 
209 #define nxt_buf_used_size(b)                                                  \
210     (nxt_buf_is_file(b) ? (b)->file_end - (b)->file_pos:                      \
211                           nxt_buf_mem_used_size(&(b)->mem))
212 
213 
214 NXT_EXPORT void nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size);
215 NXT_EXPORT nxt_buf_t *nxt_buf_mem_alloc(nxt_mp_t *mp, size_t size,
216     nxt_uint_t flags);
217 NXT_EXPORT nxt_buf_t *nxt_buf_mem_ts_alloc(nxt_task_t *task, nxt_mp_t *mp,
218     size_t size);
219 NXT_EXPORT nxt_buf_t *nxt_buf_file_alloc(nxt_mp_t *mp, size_t size,
220     nxt_uint_t flags);
221 NXT_EXPORT nxt_buf_t *nxt_buf_mmap_alloc(nxt_mp_t *mp, size_t size);
222 NXT_EXPORT nxt_buf_t *nxt_buf_sync_alloc(nxt_mp_t *mp, nxt_uint_t flags);
223 
224 NXT_EXPORT nxt_int_t nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data);
225 
226 NXT_EXPORT void nxt_buf_parent_completion(nxt_task_t *task, nxt_buf_t *parent);
227 NXT_EXPORT nxt_buf_t *nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src,
228     size_t size);
229 
230 nxt_inline nxt_buf_t *
nxt_buf_chk_make_plain(nxt_mp_t * mp,nxt_buf_t * src,size_t size)231 nxt_buf_chk_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size)
232 {
233     if (nxt_slow_path(src != NULL && src->next != NULL)) {
234         return nxt_buf_make_plain(mp, src, size);
235     }
236 
237     return src;
238 }
239 
240 #define nxt_buf_free(mp, b)                                                   \
241     nxt_mp_free((mp), (b))
242 
243 
244 NXT_EXPORT void nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in);
245 NXT_EXPORT size_t nxt_buf_chain_length(nxt_buf_t *b);
246 
247 nxt_inline nxt_buf_t *
nxt_buf_cpy(nxt_buf_t * b,const void * src,size_t length)248 nxt_buf_cpy(nxt_buf_t *b, const void *src, size_t length)
249 {
250     nxt_memcpy(b->mem.free, src, length);
251     b->mem.free += length;
252 
253     return b;
254 }
255 
256 nxt_inline nxt_buf_t *
nxt_buf_cpystr(nxt_buf_t * b,const nxt_str_t * str)257 nxt_buf_cpystr(nxt_buf_t *b, const nxt_str_t *str)
258 {
259     return nxt_buf_cpy(b, str->start, str->length);
260 }
261 
262 
263 nxt_inline void
nxt_buf_dummy_completion(nxt_task_t * task,void * obj,void * data)264 nxt_buf_dummy_completion(nxt_task_t *task, void *obj, void *data)
265 {
266 }
267 
268 
269 #endif /* _NXT_BUF_H_INCLIDED_ */
270