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