xref: /unit/src/nxt_buf.h (revision 1940)
10Sigor@sysoev.ru 
20Sigor@sysoev.ru /*
30Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
40Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
50Sigor@sysoev.ru  */
60Sigor@sysoev.ru 
70Sigor@sysoev.ru #ifndef _NXT_BUF_H_INCLUDED_
80Sigor@sysoev.ru #define _NXT_BUF_H_INCLUDED_
90Sigor@sysoev.ru 
100Sigor@sysoev.ru 
110Sigor@sysoev.ru /*
120Sigor@sysoev.ru  * There are four types of buffers.  They are different sizes, so they
130Sigor@sysoev.ru  * should be allocated by appropriate nxt_buf_XXX_alloc() function.
140Sigor@sysoev.ru  *
150Sigor@sysoev.ru  * 1) Memory-only buffers, their size is less than nxt_buf_t size, it
160Sigor@sysoev.ru  *    is equal to offsetof(nxt_buf_t, file_pos), that is it is nxt_buf_t
170Sigor@sysoev.ru  *    without file and mmap part.  The buffers are frequently used, so
180Sigor@sysoev.ru  *    the reduction allows to save 20-32 bytes depending on platform.
190Sigor@sysoev.ru  *
200Sigor@sysoev.ru  * 2) Memory/file buffers, on Unix their size is exactly nxt_buf_t size,
210Sigor@sysoev.ru  *    since nxt_mem_map_file_ctx_t() is empty macro.  On Windows the size
220Sigor@sysoev.ru  *    equals offsetof(nxt_buf_t, mmap), that is it is nxt_buf_t without
230Sigor@sysoev.ru  *    memory map context part.  The buffers can contain both memory and
240Sigor@sysoev.ru  *    file pointers at once, or only memory or file pointers.
250Sigor@sysoev.ru  *
260Sigor@sysoev.ru  * 3) Memory mapped buffers are similar to the memory/file buffers.  Their
270Sigor@sysoev.ru  *    size is exactly nxt_buf_t size.  The buffers can contain both memory
280Sigor@sysoev.ru  *    and file pointers at once, or only memory or file pointers.  If a
290Sigor@sysoev.ru  *    buffer is not currently mapped in memory, its mapping size is stored
300Sigor@sysoev.ru  *    in the mem.end field and available via nxt_buf_mem_size() macro.
310Sigor@sysoev.ru  *
320Sigor@sysoev.ru  * 4) Sync buffers, their size is the same size as memory-only buffers
330Sigor@sysoev.ru  *    size.  A sync buffer can be smaller but for memory pool cache
340Sigor@sysoev.ru  *    purpose it is better to allocate it as frequently used memory-only
350Sigor@sysoev.ru  *    buffer.  The buffers are used to synchronize pipeline processing
360Sigor@sysoev.ru  *    completion, because data buffers in the pipeline can be completed
370Sigor@sysoev.ru  *    and freed before their final output will even be passed to a peer.
380Sigor@sysoev.ru  *    For this purpose a sync buffer is allocated with the stop flag which
390Sigor@sysoev.ru  *    stops buffer chain completion processing on the sync buffer in
400Sigor@sysoev.ru  *    nxt_sendbuf_update() and nxt_sendbuf_completion().
410Sigor@sysoev.ru  *    Clearing the stop flag allows to continue completion processing.
420Sigor@sysoev.ru  *
430Sigor@sysoev.ru  *    The last flag means the end of the output and must be set only
440Sigor@sysoev.ru  *    in a sync buffer.  The last flag is not permitted in memory and
450Sigor@sysoev.ru  *    file buffers since it requires special handling while conversion
460Sigor@sysoev.ru  *    one buffer to another.
470Sigor@sysoev.ru  *
480Sigor@sysoev.ru  *    The nxt_buf_used_size() macro treats a sync buffer as a memory-only
490Sigor@sysoev.ru  *    buffer which has NULL pointers, thus the buffer content size is zero.
500Sigor@sysoev.ru  *    If allocated size of sync buffer would be lesser than memory-only
510Sigor@sysoev.ru  *    buffer, then the special memory flag would be required because
520Sigor@sysoev.ru  *    currently presence of memory part is indicated by non-NULL pointer
530Sigor@sysoev.ru  *    to a content in memory.
540Sigor@sysoev.ru  *
550Sigor@sysoev.ru  *    All types of buffers can have the flush flag that means the buffer
560Sigor@sysoev.ru  *    should be sent as much as possible.
570Sigor@sysoev.ru  */
580Sigor@sysoev.ru 
590Sigor@sysoev.ru typedef struct {
600Sigor@sysoev.ru     u_char                  *pos;
610Sigor@sysoev.ru     u_char                  *free;
620Sigor@sysoev.ru     u_char                  *start;
630Sigor@sysoev.ru     u_char                  *end;
640Sigor@sysoev.ru } nxt_buf_mem_t;
650Sigor@sysoev.ru 
660Sigor@sysoev.ru 
670Sigor@sysoev.ru struct nxt_buf_s {
680Sigor@sysoev.ru     void                    *data;
690Sigor@sysoev.ru     nxt_work_handler_t      completion_handler;
7042Smax.romanov@nginx.com     void                    *parent;
710Sigor@sysoev.ru 
720Sigor@sysoev.ru     /*
730Sigor@sysoev.ru      * The next link, flags, and nxt_buf_mem_t should
740Sigor@sysoev.ru      * reside together to improve cache locality.
750Sigor@sysoev.ru      */
760Sigor@sysoev.ru     nxt_buf_t               *next;
770Sigor@sysoev.ru 
780Sigor@sysoev.ru     uint32_t                retain;
790Sigor@sysoev.ru 
801267Sigor@sysoev.ru     uint8_t                 cache_hint;
810Sigor@sysoev.ru 
821267Sigor@sysoev.ru     uint8_t                 is_file:1;
831267Sigor@sysoev.ru     uint8_t                 is_mmap:1;
841267Sigor@sysoev.ru     uint8_t                 is_port_mmap:1;
851267Sigor@sysoev.ru     uint8_t                 is_sync:1;
861267Sigor@sysoev.ru     uint8_t                 is_nobuf:1;
871267Sigor@sysoev.ru     uint8_t                 is_flush:1;
881267Sigor@sysoev.ru     uint8_t                 is_last:1;
891267Sigor@sysoev.ru     uint8_t                 is_port_mmap_sent:1;
901267Sigor@sysoev.ru     uint8_t                 is_ts:1;
910Sigor@sysoev.ru 
920Sigor@sysoev.ru     nxt_buf_mem_t           mem;
930Sigor@sysoev.ru 
940Sigor@sysoev.ru     /* The file and mmap parts are not allocated by nxt_buf_mem_alloc(). */
950Sigor@sysoev.ru     nxt_file_t              *file;
960Sigor@sysoev.ru     nxt_off_t               file_pos;
970Sigor@sysoev.ru     nxt_off_t               file_end;
980Sigor@sysoev.ru 
990Sigor@sysoev.ru     /* The mmap part is not allocated by nxt_buf_file_alloc(). */
1000Sigor@sysoev.ru     nxt_mem_map_file_ctx_t  (mmap)
1010Sigor@sysoev.ru };
1020Sigor@sysoev.ru 
1030Sigor@sysoev.ru 
104608Sigor@sysoev.ru #define NXT_BUF_SYNC_SIZE       offsetof(nxt_buf_t, mem.free)
10542Smax.romanov@nginx.com #define NXT_BUF_MEM_SIZE        offsetof(nxt_buf_t, file)
10642Smax.romanov@nginx.com #define NXT_BUF_FILE_SIZE       sizeof(nxt_buf_t)
10742Smax.romanov@nginx.com #define NXT_BUF_MMAP_SIZE       NXT_BUF_FILE_SIZE
10842Smax.romanov@nginx.com #define NXT_BUF_PORT_MMAP_SIZE  NXT_BUF_MEM_SIZE
1090Sigor@sysoev.ru 
1100Sigor@sysoev.ru 
1110Sigor@sysoev.ru #define NXT_BUF_SYNC_NOBUF  1
1120Sigor@sysoev.ru #define NXT_BUF_SYNC_FLUSH  2
1130Sigor@sysoev.ru #define NXT_BUF_SYNC_LAST   4
1140Sigor@sysoev.ru 
1150Sigor@sysoev.ru 
1160Sigor@sysoev.ru #define                                                                       \
1170Sigor@sysoev.ru nxt_buf_is_mem(b)                                                             \
1180Sigor@sysoev.ru     ((b)->mem.pos != NULL)
1190Sigor@sysoev.ru 
1200Sigor@sysoev.ru 
1210Sigor@sysoev.ru #define                                                                       \
1220Sigor@sysoev.ru nxt_buf_is_file(b)                                                            \
1230Sigor@sysoev.ru     ((b)->is_file)
1240Sigor@sysoev.ru 
1250Sigor@sysoev.ru #define                                                                       \
1260Sigor@sysoev.ru nxt_buf_set_file(b)                                                           \
1270Sigor@sysoev.ru     (b)->is_file = 1
1280Sigor@sysoev.ru 
1290Sigor@sysoev.ru #define                                                                       \
1300Sigor@sysoev.ru nxt_buf_clear_file(b)                                                         \
1310Sigor@sysoev.ru     (b)->is_file = 0
1320Sigor@sysoev.ru 
1330Sigor@sysoev.ru 
1340Sigor@sysoev.ru #define                                                                       \
1350Sigor@sysoev.ru nxt_buf_is_mmap(b)                                                            \
1360Sigor@sysoev.ru     ((b)->is_mmap)
1370Sigor@sysoev.ru 
1380Sigor@sysoev.ru #define                                                                       \
1390Sigor@sysoev.ru nxt_buf_set_mmap(b)                                                           \
1400Sigor@sysoev.ru     (b)->is_mmap = 1
1410Sigor@sysoev.ru 
1420Sigor@sysoev.ru #define                                                                       \
1430Sigor@sysoev.ru nxt_buf_clear_mmap(b)                                                         \
1440Sigor@sysoev.ru     (b)->is_mmap = 0
1450Sigor@sysoev.ru 
1460Sigor@sysoev.ru 
1470Sigor@sysoev.ru #define                                                                       \
14842Smax.romanov@nginx.com nxt_buf_is_port_mmap(b)                                                       \
14942Smax.romanov@nginx.com     ((b)->is_port_mmap)
15042Smax.romanov@nginx.com 
15142Smax.romanov@nginx.com #define                                                                       \
15242Smax.romanov@nginx.com nxt_buf_set_port_mmap(b)                                                      \
15342Smax.romanov@nginx.com     (b)->is_port_mmap = 1
15442Smax.romanov@nginx.com 
15542Smax.romanov@nginx.com #define                                                                       \
15642Smax.romanov@nginx.com nxt_buf_clear_port_mmap(b)                                                    \
15742Smax.romanov@nginx.com     (b)->is_port_mmap = 0
15842Smax.romanov@nginx.com 
15942Smax.romanov@nginx.com 
16042Smax.romanov@nginx.com #define                                                                       \
1610Sigor@sysoev.ru nxt_buf_is_sync(b)                                                            \
1620Sigor@sysoev.ru     ((b)->is_sync)
1630Sigor@sysoev.ru 
1640Sigor@sysoev.ru #define                                                                       \
1650Sigor@sysoev.ru nxt_buf_set_sync(b)                                                           \
1660Sigor@sysoev.ru     (b)->is_sync = 1
1670Sigor@sysoev.ru 
1680Sigor@sysoev.ru #define                                                                       \
1690Sigor@sysoev.ru nxt_buf_clear_sync(b)                                                         \
1700Sigor@sysoev.ru     (b)->is_sync = 0
1710Sigor@sysoev.ru 
1720Sigor@sysoev.ru 
1730Sigor@sysoev.ru #define                                                                       \
1740Sigor@sysoev.ru nxt_buf_is_nobuf(b)                                                           \
1750Sigor@sysoev.ru     ((b)->is_nobuf)
1760Sigor@sysoev.ru 
1770Sigor@sysoev.ru #define                                                                       \
1780Sigor@sysoev.ru nxt_buf_set_nobuf(b)                                                          \
1790Sigor@sysoev.ru     (b)->is_nobuf = 1
1800Sigor@sysoev.ru 
1810Sigor@sysoev.ru #define                                                                       \
1820Sigor@sysoev.ru nxt_buf_clear_nobuf(b)                                                        \
1830Sigor@sysoev.ru     (b)->is_nobuf = 0
1840Sigor@sysoev.ru 
1850Sigor@sysoev.ru 
1860Sigor@sysoev.ru #define                                                                       \
1870Sigor@sysoev.ru nxt_buf_is_flush(b)                                                           \
1880Sigor@sysoev.ru     ((b)->is_flush)
1890Sigor@sysoev.ru 
1900Sigor@sysoev.ru #define                                                                       \
1910Sigor@sysoev.ru nxt_buf_set_flush(b)                                                          \
1920Sigor@sysoev.ru     (b)->is_flush = 1
1930Sigor@sysoev.ru 
1940Sigor@sysoev.ru #define                                                                       \
1950Sigor@sysoev.ru nxt_buf_clear_flush(b)                                                        \
1960Sigor@sysoev.ru     (b)->is_flush = 0
1970Sigor@sysoev.ru 
1980Sigor@sysoev.ru 
1990Sigor@sysoev.ru #define                                                                       \
2000Sigor@sysoev.ru nxt_buf_is_last(b)                                                            \
2010Sigor@sysoev.ru     ((b)->is_last)
2020Sigor@sysoev.ru 
2030Sigor@sysoev.ru #define                                                                       \
2040Sigor@sysoev.ru nxt_buf_set_last(b)                                                           \
2050Sigor@sysoev.ru     (b)->is_last = 1
2060Sigor@sysoev.ru 
2070Sigor@sysoev.ru #define                                                                       \
2080Sigor@sysoev.ru nxt_buf_clear_last(b)                                                         \
2091008Szelenkov@nginx.com     (b)->is_last = 0
2100Sigor@sysoev.ru 
2110Sigor@sysoev.ru 
2120Sigor@sysoev.ru #define                                                                       \
2130Sigor@sysoev.ru nxt_buf_mem_set_size(bm, size)                                                \
2140Sigor@sysoev.ru     do {                                                                      \
2150Sigor@sysoev.ru         (bm)->start = 0;                                                      \
2160Sigor@sysoev.ru         (bm)->end = (void *) size;                                            \
2170Sigor@sysoev.ru     } while (0)
2180Sigor@sysoev.ru 
2190Sigor@sysoev.ru 
2200Sigor@sysoev.ru #define                                                                       \
2210Sigor@sysoev.ru nxt_buf_mem_size(bm)                                                          \
2220Sigor@sysoev.ru     ((bm)->end - (bm)->start)
2230Sigor@sysoev.ru 
2240Sigor@sysoev.ru 
2250Sigor@sysoev.ru #define                                                                       \
2260Sigor@sysoev.ru nxt_buf_mem_used_size(bm)                                                     \
2270Sigor@sysoev.ru     ((bm)->free - (bm)->pos)
2280Sigor@sysoev.ru 
2290Sigor@sysoev.ru 
2300Sigor@sysoev.ru #define                                                                       \
2310Sigor@sysoev.ru nxt_buf_mem_free_size(bm)                                                     \
2320Sigor@sysoev.ru     ((bm)->end - (bm)->free)
2330Sigor@sysoev.ru 
2340Sigor@sysoev.ru 
2350Sigor@sysoev.ru #define                                                                       \
2360Sigor@sysoev.ru nxt_buf_used_size(b)                                                          \
2370Sigor@sysoev.ru     (nxt_buf_is_file(b) ? (b)->file_end - (b)->file_pos:                      \
2380Sigor@sysoev.ru                           nxt_buf_mem_used_size(&(b)->mem))
2390Sigor@sysoev.ru 
2400Sigor@sysoev.ru 
2414Sigor@sysoev.ru NXT_EXPORT void nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size);
24265Sigor@sysoev.ru NXT_EXPORT nxt_buf_t *nxt_buf_mem_alloc(nxt_mp_t *mp, size_t size,
2430Sigor@sysoev.ru     nxt_uint_t flags);
244122Smax.romanov@nginx.com NXT_EXPORT nxt_buf_t *nxt_buf_mem_ts_alloc(nxt_task_t *task, nxt_mp_t *mp,
245122Smax.romanov@nginx.com     size_t size);
24665Sigor@sysoev.ru NXT_EXPORT nxt_buf_t *nxt_buf_file_alloc(nxt_mp_t *mp, size_t size,
2470Sigor@sysoev.ru     nxt_uint_t flags);
24865Sigor@sysoev.ru NXT_EXPORT nxt_buf_t *nxt_buf_mmap_alloc(nxt_mp_t *mp, size_t size);
24965Sigor@sysoev.ru NXT_EXPORT nxt_buf_t *nxt_buf_sync_alloc(nxt_mp_t *mp, nxt_uint_t flags);
2500Sigor@sysoev.ru 
251122Smax.romanov@nginx.com NXT_EXPORT nxt_int_t nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data);
2520Sigor@sysoev.ru 
2531267Sigor@sysoev.ru NXT_EXPORT void nxt_buf_parent_completion(nxt_task_t *task, nxt_buf_t *parent);
254352Smax.romanov@nginx.com NXT_EXPORT nxt_buf_t *nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src,
255352Smax.romanov@nginx.com     size_t size);
256352Smax.romanov@nginx.com 
257352Smax.romanov@nginx.com nxt_inline nxt_buf_t *
258352Smax.romanov@nginx.com nxt_buf_chk_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size)
259352Smax.romanov@nginx.com {
260352Smax.romanov@nginx.com     if (nxt_slow_path(src != NULL && src->next != NULL)) {
261352Smax.romanov@nginx.com         return nxt_buf_make_plain(mp, src, size);
262352Smax.romanov@nginx.com     }
263352Smax.romanov@nginx.com 
264352Smax.romanov@nginx.com     return src;
265352Smax.romanov@nginx.com }
266352Smax.romanov@nginx.com 
2670Sigor@sysoev.ru #define                                                                       \
2680Sigor@sysoev.ru nxt_buf_free(mp, b)                                                           \
26965Sigor@sysoev.ru     nxt_mp_free((mp), (b))
2700Sigor@sysoev.ru 
2710Sigor@sysoev.ru 
2720Sigor@sysoev.ru NXT_EXPORT void nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in);
2730Sigor@sysoev.ru NXT_EXPORT size_t nxt_buf_chain_length(nxt_buf_t *b);
2740Sigor@sysoev.ru 
275141Smax.romanov@nginx.com nxt_inline nxt_buf_t *
276141Smax.romanov@nginx.com nxt_buf_cpy(nxt_buf_t *b, const void *src, size_t length)
277141Smax.romanov@nginx.com {
278141Smax.romanov@nginx.com     nxt_memcpy(b->mem.free, src, length);
279141Smax.romanov@nginx.com     b->mem.free += length;
280141Smax.romanov@nginx.com 
281141Smax.romanov@nginx.com     return b;
282141Smax.romanov@nginx.com }
283141Smax.romanov@nginx.com 
284141Smax.romanov@nginx.com nxt_inline nxt_buf_t *
285141Smax.romanov@nginx.com nxt_buf_cpystr(nxt_buf_t *b, const nxt_str_t *str)
286141Smax.romanov@nginx.com {
287141Smax.romanov@nginx.com     return nxt_buf_cpy(b, str->start, str->length);
288141Smax.romanov@nginx.com }
289141Smax.romanov@nginx.com 
2900Sigor@sysoev.ru 
291*1940Sz.hong@f5.com nxt_inline void
292*1940Sz.hong@f5.com nxt_buf_dummy_completion(nxt_task_t *task, void *obj, void *data)
293*1940Sz.hong@f5.com {
294*1940Sz.hong@f5.com }
295*1940Sz.hong@f5.com 
296*1940Sz.hong@f5.com 
2970Sigor@sysoev.ru #endif /* _NXT_BUF_H_INCLIDED_ */
298