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 116*2084Salx.manpages@gmail.com #define nxt_buf_is_mem(b) \ 1170Sigor@sysoev.ru ((b)->mem.pos != NULL) 1180Sigor@sysoev.ru 1190Sigor@sysoev.ru 120*2084Salx.manpages@gmail.com #define nxt_buf_is_file(b) \ 1210Sigor@sysoev.ru ((b)->is_file) 1220Sigor@sysoev.ru 123*2084Salx.manpages@gmail.com #define nxt_buf_set_file(b) \ 1240Sigor@sysoev.ru (b)->is_file = 1 1250Sigor@sysoev.ru 126*2084Salx.manpages@gmail.com #define nxt_buf_clear_file(b) \ 1270Sigor@sysoev.ru (b)->is_file = 0 1280Sigor@sysoev.ru 1290Sigor@sysoev.ru 130*2084Salx.manpages@gmail.com #define nxt_buf_is_mmap(b) \ 1310Sigor@sysoev.ru ((b)->is_mmap) 1320Sigor@sysoev.ru 133*2084Salx.manpages@gmail.com #define nxt_buf_set_mmap(b) \ 1340Sigor@sysoev.ru (b)->is_mmap = 1 1350Sigor@sysoev.ru 136*2084Salx.manpages@gmail.com #define nxt_buf_clear_mmap(b) \ 1370Sigor@sysoev.ru (b)->is_mmap = 0 1380Sigor@sysoev.ru 1390Sigor@sysoev.ru 140*2084Salx.manpages@gmail.com #define nxt_buf_is_port_mmap(b) \ 14142Smax.romanov@nginx.com ((b)->is_port_mmap) 14242Smax.romanov@nginx.com 143*2084Salx.manpages@gmail.com #define nxt_buf_set_port_mmap(b) \ 14442Smax.romanov@nginx.com (b)->is_port_mmap = 1 14542Smax.romanov@nginx.com 146*2084Salx.manpages@gmail.com #define nxt_buf_clear_port_mmap(b) \ 14742Smax.romanov@nginx.com (b)->is_port_mmap = 0 14842Smax.romanov@nginx.com 14942Smax.romanov@nginx.com 150*2084Salx.manpages@gmail.com #define nxt_buf_is_sync(b) \ 1510Sigor@sysoev.ru ((b)->is_sync) 1520Sigor@sysoev.ru 153*2084Salx.manpages@gmail.com #define nxt_buf_set_sync(b) \ 1540Sigor@sysoev.ru (b)->is_sync = 1 1550Sigor@sysoev.ru 156*2084Salx.manpages@gmail.com #define nxt_buf_clear_sync(b) \ 1570Sigor@sysoev.ru (b)->is_sync = 0 1580Sigor@sysoev.ru 1590Sigor@sysoev.ru 160*2084Salx.manpages@gmail.com #define nxt_buf_is_nobuf(b) \ 1610Sigor@sysoev.ru ((b)->is_nobuf) 1620Sigor@sysoev.ru 163*2084Salx.manpages@gmail.com #define nxt_buf_set_nobuf(b) \ 1640Sigor@sysoev.ru (b)->is_nobuf = 1 1650Sigor@sysoev.ru 166*2084Salx.manpages@gmail.com #define nxt_buf_clear_nobuf(b) \ 1670Sigor@sysoev.ru (b)->is_nobuf = 0 1680Sigor@sysoev.ru 1690Sigor@sysoev.ru 170*2084Salx.manpages@gmail.com #define nxt_buf_is_flush(b) \ 1710Sigor@sysoev.ru ((b)->is_flush) 1720Sigor@sysoev.ru 173*2084Salx.manpages@gmail.com #define nxt_buf_set_flush(b) \ 1740Sigor@sysoev.ru (b)->is_flush = 1 1750Sigor@sysoev.ru 176*2084Salx.manpages@gmail.com #define nxt_buf_clear_flush(b) \ 1770Sigor@sysoev.ru (b)->is_flush = 0 1780Sigor@sysoev.ru 1790Sigor@sysoev.ru 180*2084Salx.manpages@gmail.com #define nxt_buf_is_last(b) \ 1810Sigor@sysoev.ru ((b)->is_last) 1820Sigor@sysoev.ru 183*2084Salx.manpages@gmail.com #define nxt_buf_set_last(b) \ 1840Sigor@sysoev.ru (b)->is_last = 1 1850Sigor@sysoev.ru 186*2084Salx.manpages@gmail.com #define nxt_buf_clear_last(b) \ 1871008Szelenkov@nginx.com (b)->is_last = 0 1880Sigor@sysoev.ru 1890Sigor@sysoev.ru 190*2084Salx.manpages@gmail.com #define nxt_buf_mem_set_size(bm, size) \ 1910Sigor@sysoev.ru do { \ 1920Sigor@sysoev.ru (bm)->start = 0; \ 1930Sigor@sysoev.ru (bm)->end = (void *) size; \ 1940Sigor@sysoev.ru } while (0) 1950Sigor@sysoev.ru 1960Sigor@sysoev.ru 197*2084Salx.manpages@gmail.com #define nxt_buf_mem_size(bm) \ 1980Sigor@sysoev.ru ((bm)->end - (bm)->start) 1990Sigor@sysoev.ru 2000Sigor@sysoev.ru 201*2084Salx.manpages@gmail.com #define nxt_buf_mem_used_size(bm) \ 2020Sigor@sysoev.ru ((bm)->free - (bm)->pos) 2030Sigor@sysoev.ru 2040Sigor@sysoev.ru 205*2084Salx.manpages@gmail.com #define nxt_buf_mem_free_size(bm) \ 2060Sigor@sysoev.ru ((bm)->end - (bm)->free) 2070Sigor@sysoev.ru 2080Sigor@sysoev.ru 209*2084Salx.manpages@gmail.com #define nxt_buf_used_size(b) \ 2100Sigor@sysoev.ru (nxt_buf_is_file(b) ? (b)->file_end - (b)->file_pos: \ 2110Sigor@sysoev.ru nxt_buf_mem_used_size(&(b)->mem)) 2120Sigor@sysoev.ru 2130Sigor@sysoev.ru 2144Sigor@sysoev.ru NXT_EXPORT void nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size); 21565Sigor@sysoev.ru NXT_EXPORT nxt_buf_t *nxt_buf_mem_alloc(nxt_mp_t *mp, size_t size, 2160Sigor@sysoev.ru nxt_uint_t flags); 217122Smax.romanov@nginx.com NXT_EXPORT nxt_buf_t *nxt_buf_mem_ts_alloc(nxt_task_t *task, nxt_mp_t *mp, 218122Smax.romanov@nginx.com size_t size); 21965Sigor@sysoev.ru NXT_EXPORT nxt_buf_t *nxt_buf_file_alloc(nxt_mp_t *mp, size_t size, 2200Sigor@sysoev.ru nxt_uint_t flags); 22165Sigor@sysoev.ru NXT_EXPORT nxt_buf_t *nxt_buf_mmap_alloc(nxt_mp_t *mp, size_t size); 22265Sigor@sysoev.ru NXT_EXPORT nxt_buf_t *nxt_buf_sync_alloc(nxt_mp_t *mp, nxt_uint_t flags); 2230Sigor@sysoev.ru 224122Smax.romanov@nginx.com NXT_EXPORT nxt_int_t nxt_buf_ts_handle(nxt_task_t *task, void *obj, void *data); 2250Sigor@sysoev.ru 2261267Sigor@sysoev.ru NXT_EXPORT void nxt_buf_parent_completion(nxt_task_t *task, nxt_buf_t *parent); 227352Smax.romanov@nginx.com NXT_EXPORT nxt_buf_t *nxt_buf_make_plain(nxt_mp_t *mp, nxt_buf_t *src, 228352Smax.romanov@nginx.com size_t size); 229352Smax.romanov@nginx.com 230352Smax.romanov@nginx.com nxt_inline nxt_buf_t * 231352Smax.romanov@nginx.com nxt_buf_chk_make_plain(nxt_mp_t *mp, nxt_buf_t *src, size_t size) 232352Smax.romanov@nginx.com { 233352Smax.romanov@nginx.com if (nxt_slow_path(src != NULL && src->next != NULL)) { 234352Smax.romanov@nginx.com return nxt_buf_make_plain(mp, src, size); 235352Smax.romanov@nginx.com } 236352Smax.romanov@nginx.com 237352Smax.romanov@nginx.com return src; 238352Smax.romanov@nginx.com } 239352Smax.romanov@nginx.com 240*2084Salx.manpages@gmail.com #define nxt_buf_free(mp, b) \ 24165Sigor@sysoev.ru nxt_mp_free((mp), (b)) 2420Sigor@sysoev.ru 2430Sigor@sysoev.ru 2440Sigor@sysoev.ru NXT_EXPORT void nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in); 2450Sigor@sysoev.ru NXT_EXPORT size_t nxt_buf_chain_length(nxt_buf_t *b); 2460Sigor@sysoev.ru 247141Smax.romanov@nginx.com nxt_inline nxt_buf_t * 248141Smax.romanov@nginx.com nxt_buf_cpy(nxt_buf_t *b, const void *src, size_t length) 249141Smax.romanov@nginx.com { 250141Smax.romanov@nginx.com nxt_memcpy(b->mem.free, src, length); 251141Smax.romanov@nginx.com b->mem.free += length; 252141Smax.romanov@nginx.com 253141Smax.romanov@nginx.com return b; 254141Smax.romanov@nginx.com } 255141Smax.romanov@nginx.com 256141Smax.romanov@nginx.com nxt_inline nxt_buf_t * 257141Smax.romanov@nginx.com nxt_buf_cpystr(nxt_buf_t *b, const nxt_str_t *str) 258141Smax.romanov@nginx.com { 259141Smax.romanov@nginx.com return nxt_buf_cpy(b, str->start, str->length); 260141Smax.romanov@nginx.com } 261141Smax.romanov@nginx.com 2620Sigor@sysoev.ru 2631940Sz.hong@f5.com nxt_inline void 2641940Sz.hong@f5.com nxt_buf_dummy_completion(nxt_task_t *task, void *obj, void *data) 2651940Sz.hong@f5.com { 2661940Sz.hong@f5.com } 2671940Sz.hong@f5.com 2681940Sz.hong@f5.com 2690Sigor@sysoev.ru #endif /* _NXT_BUF_H_INCLIDED_ */ 270