xref: /unit/src/nxt_buf.c (revision 26:567553fcbd06)
1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #include <nxt_main.h>
8 
9 
10 static void nxt_buf_completion(nxt_task_t *task, void *obj, void *data);
11 
12 
13 void
14 nxt_buf_mem_init(nxt_buf_t *b, void *start, size_t size)
15 {
16     b->size = NXT_BUF_MEM_SIZE;
17 
18     b->mem.start = start;
19     b->mem.pos = start;
20     b->mem.free = start;
21     b->mem.end = (u_char *) start + size;
22 }
23 
24 
25 nxt_buf_t *
26 nxt_buf_mem_alloc(nxt_mem_pool_t *mp, size_t size, nxt_uint_t flags)
27 {
28     nxt_buf_t  *b;
29 
30     b = nxt_mem_cache_zalloc0(mp, NXT_BUF_MEM_SIZE);
31     if (nxt_slow_path(b == NULL)) {
32         return NULL;
33     }
34 
35     b->data = mp;
36     b->completion_handler = nxt_buf_completion;
37     b->size = NXT_BUF_MEM_SIZE;
38 
39     if (size != 0) {
40         b->mem.start = nxt_mem_buf(mp, &size, flags);
41         if (nxt_slow_path(b->mem.start == NULL)) {
42             return NULL;
43         }
44 
45         b->mem.pos = b->mem.start;
46         b->mem.free = b->mem.start;
47         b->mem.end = b->mem.start + size;
48     }
49 
50     return b;
51 }
52 
53 
54 nxt_buf_t *
55 nxt_buf_file_alloc(nxt_mem_pool_t *mp, size_t size, nxt_uint_t flags)
56 {
57     nxt_buf_t  *b;
58 
59     b = nxt_mem_cache_zalloc0(mp, NXT_BUF_FILE_SIZE);
60     if (nxt_slow_path(b == NULL)) {
61         return NULL;
62     }
63 
64     b->data = mp;
65     b->completion_handler = nxt_buf_completion;
66     b->size = NXT_BUF_FILE_SIZE;
67     nxt_buf_set_file(b);
68 
69     if (size != 0) {
70         b->mem.start = nxt_mem_buf(mp, &size, flags);
71         if (nxt_slow_path(b->mem.start == NULL)) {
72             return NULL;
73         }
74 
75         b->mem.pos = b->mem.start;
76         b->mem.free = b->mem.start;
77         b->mem.end = b->mem.start + size;
78     }
79 
80     return b;
81 }
82 
83 
84 nxt_buf_t *
85 nxt_buf_mmap_alloc(nxt_mem_pool_t *mp, size_t size)
86 {
87     nxt_buf_t  *b;
88 
89     b = nxt_mem_cache_zalloc0(mp, NXT_BUF_MMAP_SIZE);
90 
91     if (nxt_fast_path(b != NULL)) {
92         b->data = mp;
93         b->completion_handler = nxt_buf_completion;
94         b->size = NXT_BUF_MMAP_SIZE;
95 
96         nxt_buf_set_file(b);
97         nxt_buf_set_mmap(b);
98         nxt_buf_mem_set_size(&b->mem, size);
99     }
100 
101     return b;
102 }
103 
104 
105 nxt_buf_t *
106 nxt_buf_sync_alloc(nxt_mem_pool_t *mp, nxt_uint_t flags)
107 {
108     nxt_buf_t  *b;
109 
110     b = nxt_mem_cache_zalloc0(mp, NXT_BUF_SYNC_SIZE);
111 
112     if (nxt_fast_path(b != NULL)) {
113         b->data = mp;
114         b->completion_handler = nxt_buf_completion;
115         b->size = NXT_BUF_SYNC_SIZE;
116 
117         nxt_buf_set_sync(b);
118         b->is_nobuf = ((flags & NXT_BUF_SYNC_NOBUF) != 0);
119         b->is_flush = ((flags & NXT_BUF_SYNC_FLUSH) != 0);
120         b->is_last = ((flags & NXT_BUF_SYNC_LAST) != 0);
121     }
122 
123     return b;
124 }
125 
126 
127 void
128 nxt_buf_chain_add(nxt_buf_t **head, nxt_buf_t *in)
129 {
130     nxt_buf_t  *b, **prev;
131 
132     prev = head;
133 
134     for (b = *head; b != NULL; b = b->next) {
135         prev = &b->next;
136     }
137 
138     *prev = in;
139 }
140 
141 
142 size_t
143 nxt_buf_chain_length(nxt_buf_t *b)
144 {
145     size_t  length;
146 
147     length = 0;
148 
149     while (b != NULL) {
150         length += b->mem.free - b->mem.pos;
151         b = b->next;
152     }
153 
154     return length;
155 }
156 
157 
158 static void
159 nxt_buf_completion(nxt_task_t *task, void *obj, void *data)
160 {
161     nxt_buf_t       *b, *parent;
162     nxt_mem_pool_t  *mp;
163 
164     b = obj;
165     parent = data;
166 
167     nxt_debug(task, "buf completion: %p %p", b, b->mem.start);
168 
169     mp = b->data;
170     nxt_buf_free(mp, b);
171 
172     if (parent != NULL) {
173         nxt_debug(task, "parent retain:%uD", parent->retain);
174 
175         parent->retain--;
176 
177         if (parent->retain == 0) {
178             parent->mem.pos = parent->mem.free;
179 
180             parent->completion_handler(task, parent, parent->parent);
181         }
182     }
183 }
184