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