smalloc.c revision c08e194db676bd9dcd0f43bacf2051c7c91a62df
1572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams/* 2572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * simple memory allocator, backed by mmap() so that it hands out memory 3572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * that can be shared across processes and threads 4572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams */ 5572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <sys/mman.h> 6572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <stdio.h> 7572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <stdlib.h> 8572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <assert.h> 9572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <string.h> 10572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <unistd.h> 11572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <sys/types.h> 12572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include <limits.h> 13572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 14572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include "mutex.h" 15572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 16572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#undef ENABLE_RESIZE /* define to enable pool resizing */ 17572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#define MP_SAFE /* define to made allocator thread safe */ 18572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 19572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#define INITIAL_SIZE 1048576 /* new pool size */ 20572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#define MAX_POOLS 32 /* maximum number of pools to setup */ 21572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 22572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsunsigned int smalloc_pool_size = INITIAL_SIZE; 23572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 24572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#ifdef ENABLE_RESIZE 25572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#define MAX_SIZE 8 * smalloc_pool_size 26572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic unsigned int resize_error; 27572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#endif 28572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 29572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstruct pool { 30572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams struct fio_mutex *lock; /* protects this pool */ 31572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams void *map; /* map of blocks */ 32572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams void *last; /* next free block hint */ 33572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams unsigned int size; /* size of pool */ 34572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams unsigned int room; /* size left in pool */ 35572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams unsigned int largest_block; /* largest block free */ 36572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams unsigned int free_since_compact; /* sfree() since compact() */ 37572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams int fd; /* memory backing fd */ 38572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams char file[PATH_MAX]; /* filename for fd */ 39572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}; 40572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 41572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic struct pool mp[MAX_POOLS]; 42572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic unsigned int nr_pools; 43572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic unsigned int last_pool; 44572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic struct fio_mutex *lock; 45572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 46572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstruct mem_hdr { 47572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams unsigned int size; 48572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}; 49572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 50572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline void pool_lock(struct pool *pool) 51572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 52572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (pool->lock) 53572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams fio_mutex_down(pool->lock); 54572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 55572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 56572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline void pool_unlock(struct pool *pool) 57572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 58572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (pool->lock) 59572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams fio_mutex_up(pool->lock); 60572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 61572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 62572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline void global_read_lock(void) 63572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 64572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (lock) 65572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams fio_mutex_down_read(lock); 66572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 67572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 68572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline void global_read_unlock(void) 69572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 70572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (lock) 71572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams fio_mutex_up_read(lock); 72572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 73572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 74572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline void global_write_lock(void) 75572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 76572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (lock) 77572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams fio_mutex_down_write(lock); 78572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 79572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 80572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline void global_write_unlock(void) 81572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 82572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (lock) 83572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams fio_mutex_up_write(lock); 84572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 85572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 86572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#define hdr_free(hdr) ((hdr)->size & 0x80000000) 87572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#define hdr_size(hdr) ((hdr)->size & ~0x80000000) 88572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#define hdr_mark_free(hdr) ((hdr)->size |= 0x80000000) 89572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 90572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline int ptr_valid(struct pool *pool, void *ptr) 91572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 92572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams return (ptr >= pool->map) && (ptr < pool->map + pool->size); 93572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 94572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 95572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline int __hdr_valid(struct pool *pool, struct mem_hdr *hdr, 96572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams unsigned int size) 97572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 98572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams return ptr_valid(pool, hdr) && ptr_valid(pool, (void *) hdr + size - 1); 99572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 100572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 101572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline int hdr_valid(struct pool *pool, struct mem_hdr *hdr) 102572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 103572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams return __hdr_valid(pool, hdr, hdr_size(hdr)); 104572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 105572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 1066a804605b99cab4ffa3cc55c691338fd4a5396eaJason Samsstatic inline int region_free(struct mem_hdr *hdr) 107572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 108572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams return hdr_free(hdr) || (!hdr_free(hdr) && !hdr_size(hdr)); 109572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 110572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 111572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline struct mem_hdr *__hdr_nxt(struct pool *pool, struct mem_hdr *hdr, 112572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams unsigned int size) 113572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 114572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams struct mem_hdr *nxt = (void *) hdr + size + sizeof(*hdr); 115572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 116572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (__hdr_valid(pool, nxt, size)) 117572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams return nxt; 118572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 119572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams return NULL; 120572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 121572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 122572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic inline struct mem_hdr *hdr_nxt(struct pool *pool, struct mem_hdr *hdr) 123572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 124572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams return __hdr_nxt(pool, hdr, hdr_size(hdr)); 125572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 126572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 127572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic void merge(struct pool *pool, struct mem_hdr *hdr, struct mem_hdr *nxt) 128572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 129572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams unsigned int hfree = hdr_free(hdr); 130572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams unsigned int nfree = hdr_free(nxt); 131572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 132572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams hdr->size = hdr_size(hdr) + hdr_size(nxt) + sizeof(*nxt); 133572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams nxt->size = 0; 134572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 135572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (hfree) 136572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams hdr_mark_free(hdr); 1376a804605b99cab4ffa3cc55c691338fd4a5396eaJason Sams if (nfree) 1386a804605b99cab4ffa3cc55c691338fd4a5396eaJason Sams hdr_mark_free(nxt); 1396a804605b99cab4ffa3cc55c691338fd4a5396eaJason Sams 1406a804605b99cab4ffa3cc55c691338fd4a5396eaJason Sams if (pool->last == nxt) 1416a804605b99cab4ffa3cc55c691338fd4a5396eaJason Sams pool->last = hdr; 1426a804605b99cab4ffa3cc55c691338fd4a5396eaJason Sams} 143572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 144f1d97e536561b4731997c85873dde3b3fb721cb2Stephen Hinesstatic int combine(struct pool *pool, struct mem_hdr *prv, struct mem_hdr *hdr) 145f1d97e536561b4731997c85873dde3b3fb721cb2Stephen Hines{ 146572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (prv && hdr_free(prv) && hdr_free(hdr)) { 147572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams merge(pool, prv, hdr); 148572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams return 1; 149572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams } 150572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 151572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams return 0; 152572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams} 153572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 154572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic int compact_pool(struct pool *pool) 155572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams{ 156572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams struct mem_hdr *hdr = pool->map, *nxt; 157572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams unsigned int compacted = 0; 158572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 159572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (pool->free_since_compact < 50) 160572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams return 1; 161572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams 162572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams while (hdr) { 163572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams nxt = hdr_nxt(pool, hdr); 164572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (!nxt) 165572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams break; 166572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams if (hdr_free(nxt) && hdr_free(hdr)) { 167572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams merge(pool, hdr, nxt); 168 compacted++; 169 continue; 170 } 171 hdr = hdr_nxt(pool, hdr); 172 } 173 174 pool->free_since_compact = 0; 175 return !!compacted; 176} 177 178static int resize_pool(struct pool *pool) 179{ 180#ifdef ENABLE_RESIZE 181 unsigned int new_size = pool->size << 1; 182 struct mem_hdr *hdr, *last_hdr; 183 void *ptr; 184 185 if (new_size >= MAX_SIZE || resize_error) 186 return 1; 187 188 if (ftruncate(pool->fd, new_size) < 0) 189 goto fail; 190 191 ptr = mremap(pool->map, pool->size, new_size, 0); 192 if (ptr == MAP_FAILED) 193 goto fail; 194 195 pool->map = ptr; 196 hdr = pool; 197 do { 198 last_hdr = hdr; 199 } while ((hdr = hdr_nxt(hdr)) != NULL); 200 201 if (hdr_free(last_hdr)) { 202 last_hdr->size = hdr_size(last_hdr) + new_size - pool_size; 203 hdr_mark_free(last_hdr); 204 } else { 205 struct mem_hdr *nxt; 206 207 nxt = (void *) last_hdr + hdr_size(last_hdr) + sizeof(*hdr); 208 nxt->size = new_size - pool_size - sizeof(*hdr); 209 hdr_mark_free(nxt); 210 } 211 212 pool_room += new_size - pool_size; 213 pool_size = new_size; 214 return 0; 215fail: 216 perror("resize"); 217 resize_error = 1; 218#else 219 return 1; 220#endif 221} 222 223static int add_pool(struct pool *pool, unsigned int alloc_size) 224{ 225 struct mem_hdr *hdr; 226 void *ptr; 227 int fd; 228 229 strcpy(pool->file, "/tmp/.fio_smalloc.XXXXXX"); 230 fd = mkstemp(pool->file); 231 if (fd < 0) 232 goto out_close; 233 234 alloc_size += sizeof(*hdr); 235 if (alloc_size > smalloc_pool_size) 236 pool->size = alloc_size; 237 else 238 pool->size = smalloc_pool_size; 239 240 if (ftruncate(fd, pool->size) < 0) 241 goto out_unlink; 242 243 ptr = mmap(NULL, pool->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 244 if (ptr == MAP_FAILED) 245 goto out_unlink; 246 247 memset(ptr, 0, pool->size); 248 pool->map = pool->last = ptr; 249 250#ifdef MP_SAFE 251 pool->lock = fio_mutex_init(1); 252 if (!pool->lock) 253 goto out_unlink; 254#endif 255 256 pool->fd = fd; 257 258 hdr = pool->map; 259 pool->room = hdr->size = pool->size - sizeof(*hdr); 260 pool->largest_block = pool->room; 261 hdr_mark_free(hdr); 262 global_write_lock(); 263 nr_pools++; 264 global_write_unlock(); 265 return 0; 266out_unlink: 267 if (pool->map) 268 munmap(pool->map, pool->size); 269 unlink(pool->file); 270out_close: 271 if (fd >= 0) 272 close(fd); 273 return 1; 274} 275 276void sinit(void) 277{ 278 int ret; 279 280#ifdef MP_SAFE 281 lock = fio_mutex_rw_init(); 282#endif 283 ret = add_pool(&mp[0], INITIAL_SIZE); 284 assert(!ret); 285} 286 287static void cleanup_pool(struct pool *pool) 288{ 289 unlink(pool->file); 290 close(pool->fd); 291 munmap(pool->map, pool->size); 292 293 if (pool->lock) 294 fio_mutex_remove(pool->lock); 295} 296 297void scleanup(void) 298{ 299 unsigned int i; 300 301 for (i = 0; i < nr_pools; i++) 302 cleanup_pool(&mp[i]); 303 304 if (lock) 305 fio_mutex_remove(lock); 306} 307 308static void sfree_pool(struct pool *pool, void *ptr) 309{ 310 struct mem_hdr *hdr, *nxt; 311 312 if (!ptr) 313 return; 314 315 assert(ptr_valid(pool, ptr)); 316 317 pool_lock(pool); 318 hdr = ptr - sizeof(*hdr); 319 assert(!hdr_free(hdr)); 320 hdr_mark_free(hdr); 321 pool->room -= hdr_size(hdr); 322 323 nxt = hdr_nxt(pool, hdr); 324 if (nxt && hdr_free(nxt)) 325 merge(pool, hdr, nxt); 326 327 if (hdr_size(hdr) > pool->largest_block) 328 pool->largest_block = hdr_size(hdr); 329 330 pool->free_since_compact++; 331 pool_unlock(pool); 332} 333 334void sfree(void *ptr) 335{ 336 struct pool *pool = NULL; 337 unsigned int i; 338 339 global_read_lock(); 340 341 for (i = 0; i < nr_pools; i++) { 342 if (ptr_valid(&mp[i], ptr)) { 343 pool = &mp[i]; 344 break; 345 } 346 } 347 348 global_read_unlock(); 349 350 assert(pool); 351 sfree_pool(pool, ptr); 352} 353 354static void *smalloc_pool(struct pool *pool, unsigned int size) 355{ 356 struct mem_hdr *hdr, *prv; 357 int did_restart = 0; 358 void *ret; 359 360 /* 361 * slight chance of race with sfree() here, but acceptable 362 */ 363 if (!size || size > pool->room + sizeof(*hdr) || 364 ((size > pool->largest_block) && pool->largest_block)) 365 return NULL; 366 367 pool_lock(pool); 368restart: 369 hdr = pool->last; 370 prv = NULL; 371 do { 372 if (combine(pool, prv, hdr)) 373 hdr = prv; 374 375 if (hdr_free(hdr) && hdr_size(hdr) >= size) 376 break; 377 378 prv = hdr; 379 } while ((hdr = hdr_nxt(pool, hdr)) != NULL); 380 381 if (!hdr) 382 goto fail; 383 384 /* 385 * more room, adjust next header if any 386 */ 387 if (hdr_size(hdr) - size >= 2 * sizeof(*hdr)) { 388 struct mem_hdr *nxt = __hdr_nxt(pool, hdr, size); 389 390 if (nxt) { 391 nxt->size = hdr_size(hdr) - size - sizeof(*hdr); 392 if (hdr_size(hdr) == pool->largest_block) 393 pool->largest_block = hdr_size(nxt); 394 hdr_mark_free(nxt); 395 } else 396 size = hdr_size(hdr); 397 } else 398 size = hdr_size(hdr); 399 400 if (size == hdr_size(hdr) && size == pool->largest_block) 401 pool->largest_block = 0; 402 403 /* 404 * also clears free bit 405 */ 406 hdr->size = size; 407 pool->last = hdr_nxt(pool, hdr); 408 if (!pool->last) 409 pool->last = pool->map; 410 pool->room -= size; 411 pool_unlock(pool); 412 413 ret = (void *) hdr + sizeof(*hdr); 414 memset(ret, 0, size); 415 return ret; 416fail: 417 /* 418 * if we fail to allocate, first compact the entries that we missed. 419 * if that also fails, increase the size of the pool 420 */ 421 ++did_restart; 422 if (did_restart <= 1) { 423 if (!compact_pool(pool)) { 424 pool->last = pool->map; 425 goto restart; 426 } 427 } 428 ++did_restart; 429 if (did_restart <= 2) { 430 if (!resize_pool(pool)) { 431 pool->last = pool->map; 432 goto restart; 433 } 434 } 435 pool_unlock(pool); 436 return NULL; 437} 438 439void *smalloc(unsigned int size) 440{ 441 unsigned int i; 442 443 global_read_lock(); 444 i = last_pool; 445 446 do { 447 for (; i < nr_pools; i++) { 448 void *ptr = smalloc_pool(&mp[i], size); 449 450 if (ptr) { 451 last_pool = i; 452 global_read_unlock(); 453 return ptr; 454 } 455 } 456 if (last_pool) { 457 last_pool = 0; 458 continue; 459 } 460 461 if (nr_pools + 1 >= MAX_POOLS) 462 break; 463 else { 464 i = nr_pools; 465 global_read_unlock(); 466 if (add_pool(&mp[nr_pools], size)) 467 goto out; 468 global_read_lock(); 469 } 470 } while (1); 471 472 global_read_unlock(); 473out: 474 return NULL; 475} 476 477char *smalloc_strdup(const char *str) 478{ 479 char *ptr; 480 481 ptr = smalloc(strlen(str) + 1); 482 strcpy(ptr, str); 483 return ptr; 484} 485