xref: /unit/src/nxt_buf.h (revision 42:def41906e4a5)
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      * Used by nxt_mem_cache_free() to return buffer
81      * in appropriate memory pool cache.
82      */
83     uint8_t                 size;
84 
85     uint8_t                 is_file;     /* 1 bit */
86 
87     uint16_t                is_mmap:1;
88     uint16_t                is_port_mmap:1;
89 
90     uint16_t                is_sync:1;
91     uint16_t                is_nobuf:1;
92     uint16_t                is_flush:1;
93     uint16_t                is_last:1;
94     uint16_t                is_port_mmap_sent:1;
95 
96     nxt_buf_mem_t           mem;
97 
98     /* The file and mmap parts are not allocated by nxt_buf_mem_alloc(). */
99     nxt_file_t              *file;
100     nxt_off_t               file_pos;
101     nxt_off_t               file_end;
102 
103     /* The mmap part is not allocated by nxt_buf_file_alloc(). */
104     nxt_mem_map_file_ctx_t  (mmap)
105 };
106 
107 
108 #define NXT_BUF_MEM_SIZE        offsetof(nxt_buf_t, file)
109 #define NXT_BUF_SYNC_SIZE       NXT_BUF_MEM_SIZE
110 #define NXT_BUF_FILE_SIZE       sizeof(nxt_buf_t)
111 #define NXT_BUF_MMAP_SIZE       NXT_BUF_FILE_SIZE
112 #define NXT_BUF_PORT_MMAP_SIZE  NXT_BUF_MEM_SIZE
113 
114 
115 #define NXT_BUF_SYNC_NOBUF  1
116 #define NXT_BUF_SYNC_FLUSH  2
117 #define NXT_BUF_SYNC_LAST   4
118 
119 
120 #define                                                                       \
121 nxt_buf_is_mem(b)                                                             \
122     ((b)->mem.pos != NULL)
123 
124 
125 #define                                                                       \
126 nxt_buf_is_file(b)                                                            \
127     ((b)->is_file)
128 
129 #define                                                                       \
130 nxt_buf_set_file(b)                                                           \
131     (b)->is_file = 1
132 
133 #define                                                                       \
134 nxt_buf_clear_file(b)                                                         \
135     (b)->is_file = 0
136 
137 
138 #define                                                                       \
139 nxt_buf_is_mmap(b)                                                            \
140     ((b)->is_mmap)
141 
142 #define                                                                       \
143 nxt_buf_set_mmap(b)                                                           \
144     (b)->is_mmap = 1
145 
146 #define                                                                       \
147 nxt_buf_clear_mmap(b)                                                         \
148     (b)->is_mmap = 0
149 
150 
151 #define                                                                       \
152 nxt_buf_is_port_mmap(b)                                                       \
153     ((b)->is_port_mmap)
154 
155 #define                                                                       \
156 nxt_buf_set_port_mmap(b)                                                      \
157     (b)->is_port_mmap = 1
158 
159 #define                                                                       \
160 nxt_buf_clear_port_mmap(b)                                                    \
161     (b)->is_port_mmap = 0
162 
163 
164 #define                                                                       \
165 nxt_buf_is_sync(b)                                                            \
166     ((b)->is_sync)
167 
168 #define                                                                       \
169 nxt_buf_set_sync(b)                                                           \
170     (b)->is_sync = 1
171 
172 #define                                                                       \
173 nxt_buf_clear_sync(b)                                                         \
174     (b)->is_sync = 0
175 
176 
177 #define                                                                       \
178 nxt_buf_is_nobuf(b)                                                           \
179     ((b)->is_nobuf)
180 
181 #define                                                                       \
182 nxt_buf_set_nobuf(b)                                                          \
183     (b)->is_nobuf = 1
184 
185 #define                                                                       \
186 nxt_buf_clear_nobuf(b)                                                        \
187     (b)->is_nobuf = 0
188 
189 
190 #define                                                                       \
191 nxt_buf_is_flush(b)                                                           \
192     ((b)->is_flush)
193 
194 #define                                                                       \
195 nxt_buf_set_flush(b)                                                          \
196     (b)->is_flush = 1
197 
198 #define                                                                       \
199 nxt_buf_clear_flush(b)                                                        \
200     (b)->is_flush = 0
201 
202 
203 #define                                                                       \
204 nxt_buf_is_last(b)                                                            \
205     ((b)->is_last)
206 
207 #define                                                                       \
208 nxt_buf_set_last(b)                                                           \
209     (b)->is_last = 1
210 
211 #define                                                                       \
212 nxt_buf_clear_last(b)                                                         \
213    (b)->is_last = 0
214 
215 
216 #define                                                                       \
217 nxt_buf_mem_set_size(bm, size)                                                \
218     do {                                                                      \
219         (bm)->start = 0;                                                      \
220         (bm)->end = (void *) size;                                            \
221     } while (0)
222 
223 
224 #define                                                                       \
225 nxt_buf_mem_size(bm)                                                          \
226     ((bm)->end - (bm)->start)
227 
228 
229 #define                                                                       \
230 nxt_buf_mem_used_size(bm)                                                     \
231     ((bm)->free - (bm)->pos)
232 
233 
234 #define                                                                       \
235 nxt_buf_mem_free_size(bm)                                                     \
236     ((bm)->end - (bm)->free)
237 
238 
239 #define                                                                       \
240 nxt_buf_used_size(b)                                                          \
241     (nxt_buf_is_file(b) ? (b)->file_end - (b)->file_pos:                      \
242                           nxt_buf_mem_used_size(&(b)->mem))
243 
244 
245 NXT_EXPORT void nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size);
246 NXT_EXPORT nxt_buf_t *nxt_buf_mem_alloc(nxt_mem_pool_t *mp, size_t size,
247     nxt_uint_t flags);
248 NXT_EXPORT nxt_buf_t *nxt_buf_file_alloc(nxt_mem_pool_t *mp, size_t size,
249     nxt_uint_t flags);
250 NXT_EXPORT nxt_buf_t *nxt_buf_mmap_alloc(nxt_mem_pool_t *mp, size_t size);
251 NXT_EXPORT nxt_buf_t *nxt_buf_sync_alloc(nxt_mem_pool_t *mp, nxt_uint_t flags);
252 
253 
254 #define                                                                       \
255 nxt_buf_free(mp, b)                                                           \
256     nxt_mem_cache_free0((mp), (b), (b)->size)
257 
258 
259 NXT_EXPORT void nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in);
260 NXT_EXPORT size_t nxt_buf_chain_length(nxt_buf_t *b);
261 
262 
263 #endif /* _NXT_BUF_H_INCLIDED_ */
264