| 1491 | } |
| 1492 | |
| 1493 | void* cpp_memalign(size_t align, size_t size) { |
| 1494 | for (;;) { |
| 1495 | void* p = do_memalign(align, size); |
| 1496 | #ifdef PREANSINEW |
| 1497 | return p; |
| 1498 | #else |
| 1499 | if (UNLIKELY(p == NULL)) { // allocation failed |
| 1500 | // Get the current new handler. NB: this function is not |
| 1501 | // thread-safe. We make a feeble stab at making it so here, but |
| 1502 | // this lock only protects against tcmalloc interfering with |
| 1503 | // itself, not with other libraries calling set_new_handler. |
| 1504 | std::new_handler nh; |
| 1505 | { |
| 1506 | SpinLockHolder h(&set_new_handler_lock); |
| 1507 | nh = std::set_new_handler(0); |
| 1508 | (void) std::set_new_handler(nh); |
| 1509 | } |
| 1510 | #if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) |
| 1511 | if (nh) { |
| 1512 | // Since exceptions are disabled, we don't really know if new_handler |
| 1513 | // failed. Assume it will abort if it fails. |
| 1514 | (*nh)(); |
| 1515 | continue; |
| 1516 | } |
| 1517 | return 0; |
| 1518 | #else |
| 1519 | // If no new_handler is established, the allocation failed. |
| 1520 | if (!nh) |
| 1521 | return 0; |
| 1522 | |
| 1523 | // Otherwise, try the new_handler. If it returns, retry the |
| 1524 | // allocation. If it throws std::bad_alloc, fail the allocation. |
| 1525 | // if it throws something else, don't interfere. |
| 1526 | try { |
| 1527 | (*nh)(); |
| 1528 | } catch (const std::bad_alloc&) { |
| 1529 | return p; |
| 1530 | } |
| 1531 | #endif // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS) |
| 1532 | } else { // allocation success |
| 1533 | return p; |
| 1534 | } |
| 1535 | #endif // PREANSINEW |
| 1536 | } |
| 1537 | } |
| 1538 | |
| 1539 | } // end unnamed namespace |
| 1540 |
no test coverage detected