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