10Sigor@sysoev.ru 20Sigor@sysoev.ru /* 30Sigor@sysoev.ru * Copyright (C) Igor Sysoev 40Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 50Sigor@sysoev.ru */ 60Sigor@sysoev.ru 70Sigor@sysoev.ru #include <nxt_main.h> 80Sigor@sysoev.ru 90Sigor@sysoev.ru 100Sigor@sysoev.ru static nxt_log_moderation_t nxt_malloc_log_moderation = { 110Sigor@sysoev.ru NXT_LOG_ALERT, 2, "memory allocation failed", NXT_LOG_MODERATION 120Sigor@sysoev.ru }; 130Sigor@sysoev.ru 140Sigor@sysoev.ru 150Sigor@sysoev.ru static nxt_log_t * 160Sigor@sysoev.ru nxt_malloc_log(void) 170Sigor@sysoev.ru { 180Sigor@sysoev.ru nxt_thread_t *thr; 190Sigor@sysoev.ru 200Sigor@sysoev.ru thr = nxt_thread(); 210Sigor@sysoev.ru 220Sigor@sysoev.ru if (thr != NULL && thr->log != NULL) { 230Sigor@sysoev.ru return thr->log; 240Sigor@sysoev.ru } 250Sigor@sysoev.ru 260Sigor@sysoev.ru return &nxt_main_log; 270Sigor@sysoev.ru } 280Sigor@sysoev.ru 290Sigor@sysoev.ru 300Sigor@sysoev.ru void * 310Sigor@sysoev.ru nxt_malloc(size_t size) 320Sigor@sysoev.ru { 330Sigor@sysoev.ru void *p; 340Sigor@sysoev.ru 350Sigor@sysoev.ru p = malloc(size); 360Sigor@sysoev.ru 370Sigor@sysoev.ru if (nxt_fast_path(p != NULL)) { 380Sigor@sysoev.ru nxt_log_debug(nxt_malloc_log(), "malloc(%uz): %p", size, p); 390Sigor@sysoev.ru 400Sigor@sysoev.ru } else { 41564Svbart@nginx.com nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), 42564Svbart@nginx.com "malloc(%uz) failed %E", size, nxt_errno); 430Sigor@sysoev.ru } 440Sigor@sysoev.ru 450Sigor@sysoev.ru return p; 460Sigor@sysoev.ru } 470Sigor@sysoev.ru 480Sigor@sysoev.ru 490Sigor@sysoev.ru void * 500Sigor@sysoev.ru nxt_zalloc(size_t size) 510Sigor@sysoev.ru { 520Sigor@sysoev.ru void *p; 530Sigor@sysoev.ru 540Sigor@sysoev.ru p = nxt_malloc(size); 550Sigor@sysoev.ru 560Sigor@sysoev.ru if (nxt_fast_path(p != NULL)) { 570Sigor@sysoev.ru nxt_memzero(p, size); 580Sigor@sysoev.ru } 590Sigor@sysoev.ru 600Sigor@sysoev.ru return p; 610Sigor@sysoev.ru } 620Sigor@sysoev.ru 630Sigor@sysoev.ru 640Sigor@sysoev.ru void * 650Sigor@sysoev.ru nxt_realloc(void *p, size_t size) 660Sigor@sysoev.ru { 670Sigor@sysoev.ru void *n; 680Sigor@sysoev.ru 690Sigor@sysoev.ru n = realloc(p, size); 700Sigor@sysoev.ru 710Sigor@sysoev.ru if (nxt_fast_path(n != NULL)) { 720Sigor@sysoev.ru nxt_log_debug(nxt_malloc_log(), "realloc(%p, %uz): %p", p, size, n); 730Sigor@sysoev.ru 740Sigor@sysoev.ru } else { 75564Svbart@nginx.com nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), 76564Svbart@nginx.com "realloc(%p, %uz) failed %E", 77564Svbart@nginx.com p, size, nxt_errno); 780Sigor@sysoev.ru } 790Sigor@sysoev.ru 800Sigor@sysoev.ru return n; 810Sigor@sysoev.ru } 820Sigor@sysoev.ru 830Sigor@sysoev.ru 84*1616Smax.romanov@nginx.com /* nxt_lvlhsh_* functions moved here to avoid references from nxt_lvlhsh.c. */ 85*1616Smax.romanov@nginx.com 86*1616Smax.romanov@nginx.com void * 87*1616Smax.romanov@nginx.com nxt_lvlhsh_alloc(void *data, size_t size) 88*1616Smax.romanov@nginx.com { 89*1616Smax.romanov@nginx.com return nxt_memalign(size, size); 90*1616Smax.romanov@nginx.com } 91*1616Smax.romanov@nginx.com 92*1616Smax.romanov@nginx.com 93*1616Smax.romanov@nginx.com void 94*1616Smax.romanov@nginx.com nxt_lvlhsh_free(void *data, void *p) 95*1616Smax.romanov@nginx.com { 96*1616Smax.romanov@nginx.com nxt_free(p); 97*1616Smax.romanov@nginx.com } 98*1616Smax.romanov@nginx.com 99*1616Smax.romanov@nginx.com 1000Sigor@sysoev.ru #if (NXT_DEBUG) 1010Sigor@sysoev.ru 1020Sigor@sysoev.ru void 1030Sigor@sysoev.ru nxt_free(void *p) 1040Sigor@sysoev.ru { 1050Sigor@sysoev.ru nxt_log_debug(nxt_malloc_log(), "free(%p)", p); 1060Sigor@sysoev.ru 1070Sigor@sysoev.ru free(p); 1080Sigor@sysoev.ru } 1090Sigor@sysoev.ru 1100Sigor@sysoev.ru 1110Sigor@sysoev.ru #endif 1120Sigor@sysoev.ru 1130Sigor@sysoev.ru 1140Sigor@sysoev.ru #if (NXT_HAVE_POSIX_MEMALIGN) 1150Sigor@sysoev.ru 1160Sigor@sysoev.ru /* 1170Sigor@sysoev.ru * posix_memalign() presents in Linux glibc 2.1.91, FreeBSD 7.0, 1180Sigor@sysoev.ru * Solaris 11, MacOSX 10.6 (Snow Leopard), NetBSD 5.0. 1190Sigor@sysoev.ru */ 1200Sigor@sysoev.ru 1210Sigor@sysoev.ru void * 1220Sigor@sysoev.ru nxt_memalign(size_t alignment, size_t size) 1230Sigor@sysoev.ru { 1240Sigor@sysoev.ru void *p; 1250Sigor@sysoev.ru nxt_err_t err; 1260Sigor@sysoev.ru 1270Sigor@sysoev.ru err = posix_memalign(&p, alignment, size); 1280Sigor@sysoev.ru 1290Sigor@sysoev.ru if (nxt_fast_path(err == 0)) { 1300Sigor@sysoev.ru nxt_thread_log_debug("posix_memalign(%uz, %uz): %p", 1310Sigor@sysoev.ru alignment, size, p); 1320Sigor@sysoev.ru return p; 1330Sigor@sysoev.ru } 1340Sigor@sysoev.ru 135564Svbart@nginx.com nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), 136564Svbart@nginx.com "posix_memalign(%uz, %uz) failed %E", 137564Svbart@nginx.com alignment, size, err); 1380Sigor@sysoev.ru return NULL; 1390Sigor@sysoev.ru } 1400Sigor@sysoev.ru 1410Sigor@sysoev.ru #elif (NXT_HAVE_MEMALIGN) 1420Sigor@sysoev.ru 1430Sigor@sysoev.ru /* memalign() presents in Solaris, HP-UX. */ 1440Sigor@sysoev.ru 1450Sigor@sysoev.ru void * 1460Sigor@sysoev.ru nxt_memalign(size_t alignment, size_t size) 1470Sigor@sysoev.ru { 1480Sigor@sysoev.ru void *p; 1490Sigor@sysoev.ru 1500Sigor@sysoev.ru p = memalign(alignment, size); 1510Sigor@sysoev.ru 1520Sigor@sysoev.ru if (nxt_fast_path(p != NULL)) { 1530Sigor@sysoev.ru nxt_thread_log_debug("memalign(%uz, %uz): %p", 1540Sigor@sysoev.ru alignment, size, p); 1550Sigor@sysoev.ru return p; 1560Sigor@sysoev.ru } 1570Sigor@sysoev.ru 158564Svbart@nginx.com nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), 159564Svbart@nginx.com "memalign(%uz, %uz) failed %E", 160564Svbart@nginx.com alignment, size, nxt_errno); 1610Sigor@sysoev.ru return NULL; 1620Sigor@sysoev.ru } 1630Sigor@sysoev.ru 1640Sigor@sysoev.ru #elif (NXT_FREEBSD) 1650Sigor@sysoev.ru 1660Sigor@sysoev.ru /* 1670Sigor@sysoev.ru * FreeBSD prior to 7.0 lacks posix_memalign(), but if a requested size 1680Sigor@sysoev.ru * is lesser than or equal to 4K, then phkmalloc aligns the size to the 1690Sigor@sysoev.ru * next highest power of 2 and allocates memory with the same alignment. 1700Sigor@sysoev.ru * Allocations larger than 2K are always aligned to 4K. 1710Sigor@sysoev.ru */ 1720Sigor@sysoev.ru 1730Sigor@sysoev.ru void * 1740Sigor@sysoev.ru nxt_memalign(size_t alignment, size_t size) 1750Sigor@sysoev.ru { 1760Sigor@sysoev.ru size_t aligned_size; 1770Sigor@sysoev.ru u_char *p; 1780Sigor@sysoev.ru nxt_err_t err; 1790Sigor@sysoev.ru 1800Sigor@sysoev.ru if (nxt_slow_path((alignment - 1) & alignment) != 0) { 1810Sigor@sysoev.ru /* Alignment must be a power of 2. */ 1820Sigor@sysoev.ru err = NXT_EINVAL; 1830Sigor@sysoev.ru goto fail; 1840Sigor@sysoev.ru } 1850Sigor@sysoev.ru 1860Sigor@sysoev.ru if (nxt_slow_path(alignment > 4096)) { 1870Sigor@sysoev.ru err = NXT_EOPNOTSUPP; 1880Sigor@sysoev.ru goto fail; 1890Sigor@sysoev.ru } 1900Sigor@sysoev.ru 1910Sigor@sysoev.ru if (nxt_fast_path(size <= 2048)) { 1920Sigor@sysoev.ru aligned_size = nxt_max(size, alignment); 1930Sigor@sysoev.ru 1940Sigor@sysoev.ru } else { 1950Sigor@sysoev.ru /* Align to 4096. */ 1960Sigor@sysoev.ru aligned_size = size; 1970Sigor@sysoev.ru } 1980Sigor@sysoev.ru 1990Sigor@sysoev.ru p = malloc(aligned_size); 2000Sigor@sysoev.ru 2010Sigor@sysoev.ru if (nxt_fast_path(p != NULL)) { 2020Sigor@sysoev.ru nxt_thread_log_debug("nxt_memalign(%uz, %uz): %p", alignment, size, p); 2030Sigor@sysoev.ru 2040Sigor@sysoev.ru } else { 205564Svbart@nginx.com nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(), 206564Svbart@nginx.com "malloc(%uz) failed %E", size, nxt_errno); 2070Sigor@sysoev.ru } 2080Sigor@sysoev.ru 2090Sigor@sysoev.ru return p; 2100Sigor@sysoev.ru 2110Sigor@sysoev.ru fail: 2120Sigor@sysoev.ru 2130Sigor@sysoev.ru nxt_thread_log_alert("nxt_memalign(%uz, %uz) failed %E", 2140Sigor@sysoev.ru alignment, size, err); 2150Sigor@sysoev.ru return NULL; 2160Sigor@sysoev.ru } 2170Sigor@sysoev.ru 2180Sigor@sysoev.ru #else 2190Sigor@sysoev.ru 2200Sigor@sysoev.ru #error no memalign() implementation. 2210Sigor@sysoev.ru 2220Sigor@sysoev.ru #endif 223