| 187 size_t newcap |
188 size_t newcap |
| 188 ) { |
189 ) { |
| 189 if (newcap <= buffer->capacity) { |
190 if (newcap <= buffer->capacity) { |
| 190 return 0; |
191 return 0; |
| 191 } |
192 } |
| |
193 |
| |
194 unsigned long pagesize = sysconf(_SC_PAGESIZE); |
| |
195 // if page size is larger than 64 KB - for some reason - truncate to 64 KB |
| |
196 if (pagesize > 65536) pagesize = 65536; |
| |
197 if (newcap < pagesize) { |
| |
198 // when smaller as one page, map to the next power of two |
| |
199 newcap--; |
| |
200 newcap |= newcap >> 1; |
| |
201 newcap |= newcap >> 2; |
| |
202 newcap |= newcap >> 4; |
| |
203 // last operation only needed for pages larger 4096 bytes |
| |
204 // but if/else would be more expensive than just doing this |
| |
205 newcap |= newcap >> 8; |
| |
206 newcap++; |
| |
207 } else { |
| |
208 // otherwise, map to a multiple of the page size |
| |
209 newcap -= newcap % pagesize; |
| |
210 newcap += pagesize; |
| |
211 // note: if newcap is already page aligned, |
| |
212 // this gives a full additional page (which is good) |
| |
213 } |
| |
214 |
| 192 |
215 |
| 193 const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND; |
216 const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND; |
| 194 if (buffer->flags & force_copy_flags) { |
217 if (buffer->flags & force_copy_flags) { |
| 195 void *newspace = cxMalloc(buffer->allocator, newcap); |
218 void *newspace = cxMalloc(buffer->allocator, newcap); |
| 196 if (NULL == newspace) return -1; |
219 if (NULL == newspace) return -1; |