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 *
nxt_malloc_log(void)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 *
nxt_malloc(size_t size)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 *
nxt_zalloc(size_t size)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 *
nxt_realloc(void * p,size_t size)650Sigor@sysoev.ru nxt_realloc(void *p, size_t size)
660Sigor@sysoev.ru {
67*2072Sz.hong@f5.com void *n;
68*2072Sz.hong@f5.com uintptr_t ptr;
69*2072Sz.hong@f5.com
70*2072Sz.hong@f5.com /*
71*2072Sz.hong@f5.com * Workaround for a warning on GCC 12 about using "p" pointer in debug log
72*2072Sz.hong@f5.com * after realloc().
73*2072Sz.hong@f5.com */
74*2072Sz.hong@f5.com ptr = (uintptr_t) p;
750Sigor@sysoev.ru
760Sigor@sysoev.ru n = realloc(p, size);
770Sigor@sysoev.ru
780Sigor@sysoev.ru if (nxt_fast_path(n != NULL)) {
79*2072Sz.hong@f5.com nxt_log_debug(nxt_malloc_log(), "realloc(%p, %uz): %p", ptr, size, n);
800Sigor@sysoev.ru
810Sigor@sysoev.ru } else {
82564Svbart@nginx.com nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(),
83564Svbart@nginx.com "realloc(%p, %uz) failed %E",
84*2072Sz.hong@f5.com ptr, size, nxt_errno);
850Sigor@sysoev.ru }
860Sigor@sysoev.ru
870Sigor@sysoev.ru return n;
880Sigor@sysoev.ru }
890Sigor@sysoev.ru
900Sigor@sysoev.ru
911616Smax.romanov@nginx.com /* nxt_lvlhsh_* functions moved here to avoid references from nxt_lvlhsh.c. */
921616Smax.romanov@nginx.com
931616Smax.romanov@nginx.com void *
nxt_lvlhsh_alloc(void * data,size_t size)941616Smax.romanov@nginx.com nxt_lvlhsh_alloc(void *data, size_t size)
951616Smax.romanov@nginx.com {
961616Smax.romanov@nginx.com return nxt_memalign(size, size);
971616Smax.romanov@nginx.com }
981616Smax.romanov@nginx.com
991616Smax.romanov@nginx.com
1001616Smax.romanov@nginx.com void
nxt_lvlhsh_free(void * data,void * p)1011616Smax.romanov@nginx.com nxt_lvlhsh_free(void *data, void *p)
1021616Smax.romanov@nginx.com {
1031616Smax.romanov@nginx.com nxt_free(p);
1041616Smax.romanov@nginx.com }
1051616Smax.romanov@nginx.com
1061616Smax.romanov@nginx.com
1070Sigor@sysoev.ru #if (NXT_DEBUG)
1080Sigor@sysoev.ru
1090Sigor@sysoev.ru void
nxt_free(void * p)1100Sigor@sysoev.ru nxt_free(void *p)
1110Sigor@sysoev.ru {
1120Sigor@sysoev.ru nxt_log_debug(nxt_malloc_log(), "free(%p)", p);
1130Sigor@sysoev.ru
1140Sigor@sysoev.ru free(p);
1150Sigor@sysoev.ru }
1160Sigor@sysoev.ru
1170Sigor@sysoev.ru
1180Sigor@sysoev.ru #endif
1190Sigor@sysoev.ru
1200Sigor@sysoev.ru
1210Sigor@sysoev.ru #if (NXT_HAVE_POSIX_MEMALIGN)
1220Sigor@sysoev.ru
1230Sigor@sysoev.ru /*
1240Sigor@sysoev.ru * posix_memalign() presents in Linux glibc 2.1.91, FreeBSD 7.0,
1250Sigor@sysoev.ru * Solaris 11, MacOSX 10.6 (Snow Leopard), NetBSD 5.0.
1260Sigor@sysoev.ru */
1270Sigor@sysoev.ru
1280Sigor@sysoev.ru void *
nxt_memalign(size_t alignment,size_t size)1290Sigor@sysoev.ru nxt_memalign(size_t alignment, size_t size)
1300Sigor@sysoev.ru {
1310Sigor@sysoev.ru void *p;
1320Sigor@sysoev.ru nxt_err_t err;
1330Sigor@sysoev.ru
1340Sigor@sysoev.ru err = posix_memalign(&p, alignment, size);
1350Sigor@sysoev.ru
1360Sigor@sysoev.ru if (nxt_fast_path(err == 0)) {
1370Sigor@sysoev.ru nxt_thread_log_debug("posix_memalign(%uz, %uz): %p",
1380Sigor@sysoev.ru alignment, size, p);
1390Sigor@sysoev.ru return p;
1400Sigor@sysoev.ru }
1410Sigor@sysoev.ru
142564Svbart@nginx.com nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(),
143564Svbart@nginx.com "posix_memalign(%uz, %uz) failed %E",
144564Svbart@nginx.com alignment, size, err);
1450Sigor@sysoev.ru return NULL;
1460Sigor@sysoev.ru }
1470Sigor@sysoev.ru
1480Sigor@sysoev.ru #elif (NXT_HAVE_MEMALIGN)
1490Sigor@sysoev.ru
1500Sigor@sysoev.ru /* memalign() presents in Solaris, HP-UX. */
1510Sigor@sysoev.ru
1520Sigor@sysoev.ru void *
nxt_memalign(size_t alignment,size_t size)1530Sigor@sysoev.ru nxt_memalign(size_t alignment, size_t size)
1540Sigor@sysoev.ru {
1550Sigor@sysoev.ru void *p;
1560Sigor@sysoev.ru
1570Sigor@sysoev.ru p = memalign(alignment, size);
1580Sigor@sysoev.ru
1590Sigor@sysoev.ru if (nxt_fast_path(p != NULL)) {
1600Sigor@sysoev.ru nxt_thread_log_debug("memalign(%uz, %uz): %p",
1610Sigor@sysoev.ru alignment, size, p);
1620Sigor@sysoev.ru return p;
1630Sigor@sysoev.ru }
1640Sigor@sysoev.ru
165564Svbart@nginx.com nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(),
166564Svbart@nginx.com "memalign(%uz, %uz) failed %E",
167564Svbart@nginx.com alignment, size, nxt_errno);
1680Sigor@sysoev.ru return NULL;
1690Sigor@sysoev.ru }
1700Sigor@sysoev.ru
1710Sigor@sysoev.ru #elif (NXT_FREEBSD)
1720Sigor@sysoev.ru
1730Sigor@sysoev.ru /*
1740Sigor@sysoev.ru * FreeBSD prior to 7.0 lacks posix_memalign(), but if a requested size
1750Sigor@sysoev.ru * is lesser than or equal to 4K, then phkmalloc aligns the size to the
1760Sigor@sysoev.ru * next highest power of 2 and allocates memory with the same alignment.
1770Sigor@sysoev.ru * Allocations larger than 2K are always aligned to 4K.
1780Sigor@sysoev.ru */
1790Sigor@sysoev.ru
1800Sigor@sysoev.ru void *
nxt_memalign(size_t alignment,size_t size)1810Sigor@sysoev.ru nxt_memalign(size_t alignment, size_t size)
1820Sigor@sysoev.ru {
1830Sigor@sysoev.ru size_t aligned_size;
1840Sigor@sysoev.ru u_char *p;
1850Sigor@sysoev.ru nxt_err_t err;
1860Sigor@sysoev.ru
1870Sigor@sysoev.ru if (nxt_slow_path((alignment - 1) & alignment) != 0) {
1880Sigor@sysoev.ru /* Alignment must be a power of 2. */
1890Sigor@sysoev.ru err = NXT_EINVAL;
1900Sigor@sysoev.ru goto fail;
1910Sigor@sysoev.ru }
1920Sigor@sysoev.ru
1930Sigor@sysoev.ru if (nxt_slow_path(alignment > 4096)) {
1940Sigor@sysoev.ru err = NXT_EOPNOTSUPP;
1950Sigor@sysoev.ru goto fail;
1960Sigor@sysoev.ru }
1970Sigor@sysoev.ru
1980Sigor@sysoev.ru if (nxt_fast_path(size <= 2048)) {
1990Sigor@sysoev.ru aligned_size = nxt_max(size, alignment);
2000Sigor@sysoev.ru
2010Sigor@sysoev.ru } else {
2020Sigor@sysoev.ru /* Align to 4096. */
2030Sigor@sysoev.ru aligned_size = size;
2040Sigor@sysoev.ru }
2050Sigor@sysoev.ru
2060Sigor@sysoev.ru p = malloc(aligned_size);
2070Sigor@sysoev.ru
2080Sigor@sysoev.ru if (nxt_fast_path(p != NULL)) {
2090Sigor@sysoev.ru nxt_thread_log_debug("nxt_memalign(%uz, %uz): %p", alignment, size, p);
2100Sigor@sysoev.ru
2110Sigor@sysoev.ru } else {
212564Svbart@nginx.com nxt_log_alert_moderate(&nxt_malloc_log_moderation, nxt_malloc_log(),
213564Svbart@nginx.com "malloc(%uz) failed %E", size, nxt_errno);
2140Sigor@sysoev.ru }
2150Sigor@sysoev.ru
2160Sigor@sysoev.ru return p;
2170Sigor@sysoev.ru
2180Sigor@sysoev.ru fail:
2190Sigor@sysoev.ru
2200Sigor@sysoev.ru nxt_thread_log_alert("nxt_memalign(%uz, %uz) failed %E",
2210Sigor@sysoev.ru alignment, size, err);
2220Sigor@sysoev.ru return NULL;
2230Sigor@sysoev.ru }
2240Sigor@sysoev.ru
2250Sigor@sysoev.ru #else
2260Sigor@sysoev.ru
2270Sigor@sysoev.ru #error no memalign() implementation.
2280Sigor@sysoev.ru
2290Sigor@sysoev.ru #endif
230