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