1 2 /* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7 #include <nxt_main.h> 8 9 10 static nxt_log_moderation_t nxt_malloc_log_moderation = { 11 NXT_LOG_ALERT, 2, "memory allocation failed", NXT_LOG_MODERATION 12 }; 13 14 15 static nxt_log_t * 16 nxt_malloc_log(void) 17 { 18 nxt_thread_t *thr; 19 20 thr = nxt_thread(); 21 22 if (thr != NULL && thr->log != NULL) { 23 return thr->log; 24 } 25 26 return &nxt_main_log; 27 } 28 29 30 void * 31 nxt_malloc(size_t size) 32 { 33 void *p; 34 35 p = malloc(size); 36 37 if (nxt_fast_path(p != NULL)) { 38 nxt_log_debug(nxt_malloc_log(), "malloc(%uz): %p", size, p); 39 40 } else { 41 nxt_log_moderate(&nxt_malloc_log_moderation, 42 NXT_LOG_ALERT, nxt_malloc_log(), 43 "malloc(%uz) failed %E", size, nxt_errno); 44 } 45 46 return p; 47 } 48 49 50 void * 51 nxt_zalloc(size_t size) 52 { 53 void *p; 54 55 p = nxt_malloc(size); 56 57 if (nxt_fast_path(p != NULL)) { 58 nxt_memzero(p, size); 59 } 60 61 return p; 62 } 63 64 65 void * 66 nxt_realloc(void *p, size_t size) 67 { 68 void *n; 69 70 n = realloc(p, size); 71 72 if (nxt_fast_path(n != NULL)) { 73 nxt_log_debug(nxt_malloc_log(), "realloc(%p, %uz): %p", p, size, n); 74 75 } else { 76 nxt_log_moderate(&nxt_malloc_log_moderation, 77 NXT_LOG_ALERT, nxt_malloc_log(), 78 "realloc(%p, %uz) failed %E", p, size, nxt_errno); 79 } 80 81 return n; 82 } 83 84 85 #if (NXT_DEBUG) 86 87 void 88 nxt_free(void *p) 89 { 90 nxt_log_debug(nxt_malloc_log(), "free(%p)", p); 91 92 free(p); 93 } 94 95 96 #endif 97 98 99 #if (NXT_HAVE_POSIX_MEMALIGN) 100 101 /* 102 * posix_memalign() presents in Linux glibc 2.1.91, FreeBSD 7.0, 103 * Solaris 11, MacOSX 10.6 (Snow Leopard), NetBSD 5.0. 104 */ 105 106 void * 107 nxt_memalign(size_t alignment, size_t size) 108 { 109 void *p; 110 nxt_err_t err; 111 112 err = posix_memalign(&p, alignment, size); 113 114 if (nxt_fast_path(err == 0)) { 115 nxt_thread_log_debug("posix_memalign(%uz, %uz): %p", 116 alignment, size, p); 117 return p; 118 } 119 120 nxt_log_moderate(&nxt_malloc_log_moderation, 121 NXT_LOG_ALERT, nxt_malloc_log(), 122 "posix_memalign(%uz, %uz) failed %E", 123 alignment, size, err); 124 return NULL; 125 } 126 127 #elif (NXT_HAVE_MEMALIGN) 128 129 /* memalign() presents in Solaris, HP-UX. */ 130 131 void * 132 nxt_memalign(size_t alignment, size_t size) 133 { 134 void *p; 135 136 p = memalign(alignment, size); 137 138 if (nxt_fast_path(p != NULL)) { 139 nxt_thread_log_debug("memalign(%uz, %uz): %p", 140 alignment, size, p); 141 return p; 142 } 143 144 nxt_log_moderate(&nxt_malloc_log_moderation, 145 NXT_LOG_ALERT, nxt_malloc_log(), 146 "memalign(%uz, %uz) failed %E", 147 alignment, size, nxt_errno); 148 return NULL; 149 } 150 151 #elif (NXT_FREEBSD) 152 153 /* 154 * FreeBSD prior to 7.0 lacks posix_memalign(), but if a requested size 155 * is lesser than or equal to 4K, then phkmalloc aligns the size to the 156 * next highest power of 2 and allocates memory with the same alignment. 157 * Allocations larger than 2K are always aligned to 4K. 158 */ 159 160 void * 161 nxt_memalign(size_t alignment, size_t size) 162 { 163 size_t aligned_size; 164 u_char *p; 165 nxt_err_t err; 166 167 if (nxt_slow_path((alignment - 1) & alignment) != 0) { 168 /* Alignment must be a power of 2. */ 169 err = NXT_EINVAL; 170 goto fail; 171 } 172 173 if (nxt_slow_path(alignment > 4096)) { 174 err = NXT_EOPNOTSUPP; 175 goto fail; 176 } 177 178 if (nxt_fast_path(size <= 2048)) { 179 aligned_size = nxt_max(size, alignment); 180 181 } else { 182 /* Align to 4096. */ 183 aligned_size = size; 184 } 185 186 p = malloc(aligned_size); 187 188 if (nxt_fast_path(p != NULL)) { 189 nxt_thread_log_debug("nxt_memalign(%uz, %uz): %p", alignment, size, p); 190 191 } else { 192 nxt_log_moderate(&nxt_malloc_log_moderation, 193 NXT_LOG_ALERT, nxt_malloc_log(), 194 "malloc(%uz) failed %E", size, nxt_errno); 195 } 196 197 return p; 198 199 fail: 200 201 nxt_thread_log_alert("nxt_memalign(%uz, %uz) failed %E", 202 alignment, size, err); 203 return NULL; 204 } 205 206 #else 207 208 #error no memalign() implementation. 209 210 #endif 211