xref: /unit/src/nxt_malloc.c (revision 2072:9697718d7022)
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