diff options
Diffstat (limited to 'src/lib/libc/stdlib/malloc.c')
| -rw-r--r-- | src/lib/libc/stdlib/malloc.c | 147 |
1 files changed, 128 insertions, 19 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index 6aba00e4a0..6f646934b2 100644 --- a/src/lib/libc/stdlib/malloc.c +++ b/src/lib/libc/stdlib/malloc.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: malloc.c,v 1.141 2012/02/29 08:44:14 otto Exp $ */ | 1 | /* $OpenBSD: malloc.c,v 1.142 2012/06/18 17:03:51 matthew Exp $ */ |
| 2 | /* | 2 | /* |
| 3 | * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> | 3 | * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> |
| 4 | * | 4 | * |
| @@ -389,7 +389,7 @@ map(struct dir_info *d, size_t sz, int zero_fill) | |||
| 389 | wrterror("internal struct corrupt", NULL); | 389 | wrterror("internal struct corrupt", NULL); |
| 390 | if (sz != PAGEROUND(sz)) { | 390 | if (sz != PAGEROUND(sz)) { |
| 391 | wrterror("map round", NULL); | 391 | wrterror("map round", NULL); |
| 392 | return NULL; | 392 | return MAP_FAILED; |
| 393 | } | 393 | } |
| 394 | if (psz > d->free_regions_size) { | 394 | if (psz > d->free_regions_size) { |
| 395 | p = MMAP(sz); | 395 | p = MMAP(sz); |
| @@ -1295,8 +1295,10 @@ orealloc(void *p, size_t newsz, void *f) | |||
| 1295 | STATS_SETF(r, f); | 1295 | STATS_SETF(r, f); |
| 1296 | STATS_INC(g_pool->cheap_reallocs); | 1296 | STATS_INC(g_pool->cheap_reallocs); |
| 1297 | return p; | 1297 | return p; |
| 1298 | } else if (q != MAP_FAILED) | 1298 | } else if (q != MAP_FAILED) { |
| 1299 | munmap(q, rnewsz - roldsz); | 1299 | if (munmap(q, rnewsz - roldsz)) |
| 1300 | wrterror("munmap", q); | ||
| 1301 | } | ||
| 1300 | } | 1302 | } |
| 1301 | } else if (rnewsz < roldsz) { | 1303 | } else if (rnewsz < roldsz) { |
| 1302 | if (mopts.malloc_guard) { | 1304 | if (mopts.malloc_guard) { |
| @@ -1413,29 +1415,136 @@ calloc(size_t nmemb, size_t size) | |||
| 1413 | return r; | 1415 | return r; |
| 1414 | } | 1416 | } |
| 1415 | 1417 | ||
| 1418 | static void * | ||
| 1419 | mapalign(struct dir_info *d, size_t alignment, size_t sz, int zero_fill) | ||
| 1420 | { | ||
| 1421 | void *p, *q; | ||
| 1422 | |||
| 1423 | if (alignment < MALLOC_PAGESIZE || alignment & (alignment - 1) != 0) { | ||
| 1424 | wrterror("mapalign bad alignment", NULL); | ||
| 1425 | return MAP_FAILED; | ||
| 1426 | } | ||
| 1427 | if (sz != PAGEROUND(sz)) { | ||
| 1428 | wrterror("mapalign round", NULL); | ||
| 1429 | return MAP_FAILED; | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | /* Allocate sz + alignment bytes of memory, which must include a | ||
| 1433 | * subrange of size bytes that is properly aligned. Unmap the | ||
| 1434 | * other bytes, and then return that subrange. | ||
| 1435 | */ | ||
| 1436 | |||
| 1437 | /* We need sz + alignment to fit into a size_t. */ | ||
| 1438 | if (alignment > SIZE_MAX - sz) | ||
| 1439 | return MAP_FAILED; | ||
| 1440 | |||
| 1441 | p = map(d, sz + alignment, zero_fill); | ||
| 1442 | if (p == MAP_FAILED) | ||
| 1443 | return MAP_FAILED; | ||
| 1444 | q = (void *)(((uintptr_t)p + alignment - 1) & ~(alignment - 1)); | ||
| 1445 | if (q != p) { | ||
| 1446 | if (munmap(p, q - p)) | ||
| 1447 | wrterror("munmap", p); | ||
| 1448 | } | ||
| 1449 | if (munmap(q + sz, alignment - (q - p))) | ||
| 1450 | wrterror("munmap", q + sz); | ||
| 1451 | malloc_used -= alignment; | ||
| 1452 | |||
| 1453 | return q; | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | static void * | ||
| 1457 | omemalign(size_t alignment, size_t sz, int zero_fill, void *f) | ||
| 1458 | { | ||
| 1459 | size_t psz; | ||
| 1460 | void *p; | ||
| 1461 | |||
| 1462 | if (alignment <= MALLOC_PAGESIZE) { | ||
| 1463 | /* | ||
| 1464 | * max(size, alignment) is enough to assure the requested alignment, | ||
| 1465 | * since the allocator always allocates power-of-two blocks. | ||
| 1466 | */ | ||
| 1467 | if (sz < alignment) | ||
| 1468 | sz = alignment; | ||
| 1469 | return omalloc(sz, zero_fill, f); | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | if (sz >= SIZE_MAX - mopts.malloc_guard - MALLOC_PAGESIZE) { | ||
| 1473 | errno = ENOMEM; | ||
| 1474 | return NULL; | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | sz += mopts.malloc_guard; | ||
| 1478 | psz = PAGEROUND(sz); | ||
| 1479 | |||
| 1480 | p = mapalign(g_pool, alignment, psz, zero_fill); | ||
| 1481 | if (p == NULL) { | ||
| 1482 | errno = ENOMEM; | ||
| 1483 | return NULL; | ||
| 1484 | } | ||
| 1485 | |||
| 1486 | if (insert(g_pool, p, sz, f)) { | ||
| 1487 | unmap(g_pool, p, psz); | ||
| 1488 | errno = ENOMEM; | ||
| 1489 | return NULL; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | if (mopts.malloc_guard) { | ||
| 1493 | if (mprotect((char *)p + psz - mopts.malloc_guard, | ||
| 1494 | mopts.malloc_guard, PROT_NONE)) | ||
| 1495 | wrterror("mprotect", NULL); | ||
| 1496 | malloc_guarded += mopts.malloc_guard; | ||
| 1497 | } | ||
| 1498 | |||
| 1499 | if (mopts.malloc_junk) { | ||
| 1500 | if (zero_fill) | ||
| 1501 | memset((char *)p + sz - mopts.malloc_guard, | ||
| 1502 | SOME_JUNK, psz - sz); | ||
| 1503 | else | ||
| 1504 | memset(p, SOME_JUNK, psz - mopts.malloc_guard); | ||
| 1505 | } | ||
| 1506 | |||
| 1507 | return p; | ||
| 1508 | } | ||
| 1509 | |||
| 1416 | int | 1510 | int |
| 1417 | posix_memalign(void **memptr, size_t alignment, size_t size) | 1511 | posix_memalign(void **memptr, size_t alignment, size_t size) |
| 1418 | { | 1512 | { |
| 1419 | void *result; | 1513 | int res, saved_errno = errno; |
| 1514 | void *r; | ||
| 1420 | 1515 | ||
| 1421 | /* Make sure that alignment is a large enough power of 2. */ | 1516 | /* Make sure that alignment is a large enough power of 2. */ |
| 1422 | if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *) || | 1517 | if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *)) |
| 1423 | alignment > MALLOC_PAGESIZE) | ||
| 1424 | return EINVAL; | 1518 | return EINVAL; |
| 1425 | 1519 | ||
| 1426 | /* | 1520 | _MALLOC_LOCK(); |
| 1427 | * max(size, alignment) is enough to assure the requested alignment, | 1521 | malloc_func = " in posix_memalign():"; |
| 1428 | * since the allocator always allocates power-of-two blocks. | 1522 | if (g_pool == NULL) { |
| 1429 | */ | 1523 | if (malloc_init() != 0) |
| 1430 | if (size < alignment) | 1524 | goto err; |
| 1431 | size = alignment; | 1525 | } |
| 1432 | result = malloc(size); | 1526 | if (malloc_active++) { |
| 1433 | 1527 | malloc_recurse(); | |
| 1434 | if (result == NULL) | 1528 | goto err; |
| 1435 | return ENOMEM; | 1529 | } |
| 1436 | 1530 | r = omemalign(alignment, size, mopts.malloc_zero, CALLER); | |
| 1437 | *memptr = result; | 1531 | malloc_active--; |
| 1532 | _MALLOC_UNLOCK(); | ||
| 1533 | if (r == NULL) { | ||
| 1534 | if (mopts.malloc_xmalloc) { | ||
| 1535 | wrterror("out of memory", NULL); | ||
| 1536 | errno = ENOMEM; | ||
| 1537 | } | ||
| 1538 | goto err; | ||
| 1539 | } | ||
| 1540 | errno = saved_errno; | ||
| 1541 | *memptr = r; | ||
| 1438 | return 0; | 1542 | return 0; |
| 1543 | |||
| 1544 | err: | ||
| 1545 | res = errno; | ||
| 1546 | errno = saved_errno; | ||
| 1547 | return res; | ||
| 1439 | } | 1548 | } |
| 1440 | 1549 | ||
| 1441 | #ifdef MALLOC_STATS | 1550 | #ifdef MALLOC_STATS |
