diff options
author | Igor Sysoev <igor@sysoev.ru> | 2017-01-17 20:00:00 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2017-01-17 20:00:00 +0300 |
commit | 16cbf3c076a0aca6d47adaf3f719493674cf2363 (patch) | |
tree | e6530480020f62a2bdbf249988ec3e2a751d3927 /src/nxt_buf.h | |
download | unit-16cbf3c076a0aca6d47adaf3f719493674cf2363.tar.gz unit-16cbf3c076a0aca6d47adaf3f719493674cf2363.tar.bz2 |
Initial version.
Diffstat (limited to 'src/nxt_buf.h')
-rw-r--r-- | src/nxt_buf.h | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/nxt_buf.h b/src/nxt_buf.h new file mode 100644 index 00000000..240a1d22 --- /dev/null +++ b/src/nxt_buf.h @@ -0,0 +1,246 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_BUF_H_INCLUDED_ +#define _NXT_BUF_H_INCLUDED_ + + +/* + * There are four types of buffers. They are different sizes, so they + * should be allocated by appropriate nxt_buf_XXX_alloc() function. + * + * 1) Memory-only buffers, their size is less than nxt_buf_t size, it + * is equal to offsetof(nxt_buf_t, file_pos), that is it is nxt_buf_t + * without file and mmap part. The buffers are frequently used, so + * the reduction allows to save 20-32 bytes depending on platform. + * + * 2) Memory/file buffers, on Unix their size is exactly nxt_buf_t size, + * since nxt_mem_map_file_ctx_t() is empty macro. On Windows the size + * equals offsetof(nxt_buf_t, mmap), that is it is nxt_buf_t without + * memory map context part. The buffers can contain both memory and + * file pointers at once, or only memory or file pointers. + * + * 3) Memory mapped buffers are similar to the memory/file buffers. Their + * size is exactly nxt_buf_t size. The buffers can contain both memory + * and file pointers at once, or only memory or file pointers. If a + * buffer is not currently mapped in memory, its mapping size is stored + * in the mem.end field and available via nxt_buf_mem_size() macro. + * + * 4) Sync buffers, their size is the same size as memory-only buffers + * size. A sync buffer can be smaller but for memory pool cache + * purpose it is better to allocate it as frequently used memory-only + * buffer. The buffers are used to synchronize pipeline processing + * completion, because data buffers in the pipeline can be completed + * and freed before their final output will even be passed to a peer. + * For this purpose a sync buffer is allocated with the stop flag which + * stops buffer chain completion processing on the sync buffer in + * nxt_sendbuf_update() and nxt_sendbuf_completion(). + * Clearing the stop flag allows to continue completion processing. + * + * The last flag means the end of the output and must be set only + * in a sync buffer. The last flag is not permitted in memory and + * file buffers since it requires special handling while conversion + * one buffer to another. + * + * The nxt_buf_used_size() macro treats a sync buffer as a memory-only + * buffer which has NULL pointers, thus the buffer content size is zero. + * If allocated size of sync buffer would be lesser than memory-only + * buffer, then the special memory flag would be required because + * currently presence of memory part is indicated by non-NULL pointer + * to a content in memory. + * + * All types of buffers can have the flush flag that means the buffer + * should be sent as much as possible. + */ + +typedef struct { + u_char *pos; + u_char *free; + u_char *start; + u_char *end; +} nxt_buf_mem_t; + + +struct nxt_buf_s { + void *data; + nxt_work_handler_t completion_handler; + nxt_buf_t *parent; + + /* + * The next link, flags, and nxt_buf_mem_t should + * reside together to improve cache locality. + */ + nxt_buf_t *next; + + uint32_t retain; + /* + * Used by nxt_mem_cache_free() to return buffer + * in appropriate memory pool cache. + */ + uint8_t size; + + uint8_t is_file; /* 1 bit */ + + uint16_t is_mmap:1; + + uint16_t is_sync:1; + uint16_t is_nobuf:1; + uint16_t is_flush:1; + uint16_t is_last:1; + + nxt_buf_mem_t mem; + + /* The file and mmap parts are not allocated by nxt_buf_mem_alloc(). */ + nxt_file_t *file; + nxt_off_t file_pos; + nxt_off_t file_end; + + /* The mmap part is not allocated by nxt_buf_file_alloc(). */ + nxt_mem_map_file_ctx_t (mmap) +}; + + +#define NXT_BUF_MEM_SIZE offsetof(nxt_buf_t, file) +#define NXT_BUF_SYNC_SIZE NXT_BUF_MEM_SIZE +#define NXT_BUF_MMAP_SIZE sizeof(nxt_buf_t) +#define NXT_BUF_FILE_SIZE sizeof(nxt_buf_t) + + +#define NXT_BUF_SYNC_NOBUF 1 +#define NXT_BUF_SYNC_FLUSH 2 +#define NXT_BUF_SYNC_LAST 4 + + +#define \ +nxt_buf_is_mem(b) \ + ((b)->mem.pos != NULL) + + +#define \ +nxt_buf_is_file(b) \ + ((b)->is_file) + +#define \ +nxt_buf_set_file(b) \ + (b)->is_file = 1 + +#define \ +nxt_buf_clear_file(b) \ + (b)->is_file = 0 + + +#define \ +nxt_buf_is_mmap(b) \ + ((b)->is_mmap) + +#define \ +nxt_buf_set_mmap(b) \ + (b)->is_mmap = 1 + +#define \ +nxt_buf_clear_mmap(b) \ + (b)->is_mmap = 0 + + +#define \ +nxt_buf_is_sync(b) \ + ((b)->is_sync) + +#define \ +nxt_buf_set_sync(b) \ + (b)->is_sync = 1 + +#define \ +nxt_buf_clear_sync(b) \ + (b)->is_sync = 0 + + +#define \ +nxt_buf_is_nobuf(b) \ + ((b)->is_nobuf) + +#define \ +nxt_buf_set_nobuf(b) \ + (b)->is_nobuf = 1 + +#define \ +nxt_buf_clear_nobuf(b) \ + (b)->is_nobuf = 0 + + +#define \ +nxt_buf_is_flush(b) \ + ((b)->is_flush) + +#define \ +nxt_buf_set_flush(b) \ + (b)->is_flush = 1 + +#define \ +nxt_buf_clear_flush(b) \ + (b)->is_flush = 0 + + +#define \ +nxt_buf_is_last(b) \ + ((b)->is_last) + +#define \ +nxt_buf_set_last(b) \ + (b)->is_last = 1 + +#define \ +nxt_buf_clear_last(b) \ + (b)->is_last = 0 + + +#define \ +nxt_buf_mem_set_size(bm, size) \ + do { \ + (bm)->start = 0; \ + (bm)->end = (void *) size; \ + } while (0) + + +#define \ +nxt_buf_mem_size(bm) \ + ((bm)->end - (bm)->start) + + +#define \ +nxt_buf_mem_used_size(bm) \ + ((bm)->free - (bm)->pos) + + +#define \ +nxt_buf_mem_free_size(bm) \ + ((bm)->end - (bm)->free) + + +#define \ +nxt_buf_used_size(b) \ + (nxt_buf_is_file(b) ? (b)->file_end - (b)->file_pos: \ + nxt_buf_mem_used_size(&(b)->mem)) + + +NXT_EXPORT nxt_buf_t *nxt_buf_mem_alloc(nxt_mem_pool_t *mp, size_t size, + nxt_uint_t flags); +NXT_EXPORT nxt_buf_t *nxt_buf_file_alloc(nxt_mem_pool_t *mp, size_t size, + nxt_uint_t flags); +NXT_EXPORT nxt_buf_t *nxt_buf_mmap_alloc(nxt_mem_pool_t *mp, size_t size); +NXT_EXPORT nxt_buf_t *nxt_buf_sync_alloc(nxt_mem_pool_t *mp, nxt_uint_t flags); + + +#define \ +nxt_buf_free(mp, b) \ + nxt_mem_cache_free0((mp), (b), (b)->size) + + +NXT_EXPORT void nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in); +NXT_EXPORT size_t nxt_buf_chain_length(nxt_buf_t *b); + + +#endif /* _NXT_BUF_H_INCLIDED_ */ |