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