4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2015, Joyent, Inc. All rights reserved.
28 #include "thr_uberdata.h"
29 #include <sys/syscall.h>
31 extern long __systemcall6(sysret_t
*, int, ...);
34 * This is a small and simple power of two memory allocator that is
35 * used internally by libc. Allocations are fast and memory is never
36 * returned to the system, except for allocations of 64 Kbytes and larger,
37 * which are simply mmap()ed and munmap()ed as needed. Smaller allocations
38 * (minimum size is 64 bytes) are obtained from mmap() of 64K chunks
39 * broken up into unit allocations and maintained on free lists.
40 * The interface requires the caller to keep track of the size of an
41 * allocated block and to pass that size back when freeing a block.
43 * This allocator is called during initialization, from code called
44 * from the dynamic linker, so it must not call anything that might
45 * re-invoke the dynamic linker to resolve a symbol. That is,
46 * it must only call functions that are wholly private to libc.
48 * Also, this allocator must be unique across all link maps
49 * because pointers returned by lmalloc() are stored in the
50 * thread structure, which is constant across all link maps.
52 * Memory blocks returned by lmalloc() are initialized to zero.
55 #define MINSIZE 64 /* (1 << MINSHIFT) */
57 #define CHUNKSIZE (64 * 1024)
60 * bucketnum allocation size
74 * See "thr_uberdata.h" for the definition of bucket_t.
75 * The 10 (NBUCKETS) buckets are allocated in uberdata.
81 * On the very first lmalloc(), before any memory has been allocated,
82 * mmap() a 24K block of memory and carve out six 2K chunks, each
83 * of which is subdivided for the initial allocations from buckets
84 * 0, 1, 2, 3, 4 and 5, giving them initial numbers of elements
85 * 32, 16, 8, 4, 2 and 1, respectively. The remaining 12K is cut
86 * into one 4K buffer for bucket 6 and one 8K buffer for bucket 7.
88 * This results in almost all simple single-threaded processes,
89 * such as those employed in the kenbus test suite, having to
90 * allocate only this one 24K block during their lifetimes.
93 #define SUBCHUNKSIZE 2048
94 #define BASE_SIZE (24 * 1024)
97 initial_allocation(bucket_t
*bp
) /* &__uberdata.bucket[0] */
107 * We do this seemingly obtuse call to __systemcall6(SYS_mmap)
108 * instead of simply calling mmap() directly because, if the
109 * mmap() system call fails, we must make sure that __cerror()
110 * is not called, because that would call ___errno()
111 * which would dereference curthread and, because we are very
112 * early in libc initialization, curthread is NULL and we would
113 * draw a hard-to-debug SIGSEGV core dump, or worse.
114 * We opt to give a thread panic message instead.
116 if (__systemcall6(&rval
, SYS_mmap
, CHUNKSIZE
, BASE_SIZE
,
117 PROT_READ
| PROT_WRITE
| PROT_EXEC
,
118 MAP_PRIVATE
| MAP_ANON
| MAP_ALIGN
, -1L, (off_t
)0) != 0)
119 thr_panic("initial allocation failed; swap space exhausted?");
120 base
= (void *)rval
.sys_rval1
;
122 for (bucketnum
= 0; bucketnum
< 6; bucketnum
++, bp
++) {
123 size
= (size_t)MINSIZE
<< bucketnum
;
124 n
= SUBCHUNKSIZE
/ size
;
125 ptr
= (void *)((caddr_t
)base
+ bucketnum
* SUBCHUNKSIZE
);
127 ASSERT(bp
->free_list
== NULL
);
130 void *next
= (void *)((caddr_t
)ptr
+ size
);
131 *(void **)ptr
= next
;
134 *(void **)ptr
= NULL
;
137 ptr
= (void *)((caddr_t
)base
+ bucketnum
* SUBCHUNKSIZE
);
138 ASSERT(bp
->free_list
== NULL
);
141 ptr
= (void *)((caddr_t
)ptr
+ 2 * SUBCHUNKSIZE
);
143 ASSERT(bp
->free_list
== NULL
);
146 ASSERT(((caddr_t
)ptr
- (caddr_t
)base
+ 4 * SUBCHUNKSIZE
) == BASE_SIZE
);
150 * This highbit code is the same as the code in fls_impl().
151 * We inline it here for speed.
154 getbucketnum(size_t size
)
158 if (size
-- <= MINSIZE
)
162 if (size
& 0xffffffff00000000ul
)
163 highbit
+= 32, size
>>= 32;
165 if (size
& 0xffff0000)
166 highbit
+= 16, size
>>= 16;
168 highbit
+= 8, size
>>= 8;
170 highbit
+= 4, size
>>= 4;
172 highbit
+= 2, size
>>= 2;
176 ASSERT(highbit
> MINSHIFT
);
177 return (highbit
- MINSHIFT
);
183 int bucketnum
= getbucketnum(size
);
190 * ulwp_t structures must be allocated from a rwx mapping since it
191 * is a normal data object _and_ it contains instructions that are
192 * executed for user-land DTrace tracing with the fasttrap provider.
194 int prot
= PROT_READ
| PROT_WRITE
| PROT_EXEC
;
196 /* round size up to the proper power of 2 */
197 size
= (size_t)MINSIZE
<< bucketnum
;
199 if (bucketnum
>= NBUCKETS
) {
200 /* mmap() allocates memory already set to zero */
201 ptr
= mmap((void *)CHUNKSIZE
, size
, prot
,
202 MAP_PRIVATE
|MAP_ANON
|MAP_ALIGN
, -1, (off_t
)0);
203 if (ptr
== MAP_FAILED
)
208 if ((self
= __curthread()) == NULL
)
211 udp
= self
->ul_uberdata
;
213 if (udp
->bucket_init
== 0) {
214 ASSERT(udp
->nthreads
== 0);
215 initial_allocation(udp
->bucket
);
216 udp
->bucket_init
= 1;
219 bp
= &udp
->bucket
[bucketnum
];
221 lmutex_lock(&bp
->bucket_lock
);
223 if ((ptr
= bp
->free_list
) == NULL
) {
228 * Double the number of chunks mmap()ed each time,
229 * in case of large numbers of allocations.
236 bsize
= CHUNKSIZE
* bp
->chunks
;
238 ptr
= mmap((void *)CHUNKSIZE
, bsize
, prot
,
239 MAP_PRIVATE
|MAP_ANON
|MAP_ALIGN
, -1, (off_t
)0);
240 if (ptr
!= MAP_FAILED
)
242 /* try a smaller chunk allocation */
243 if ((bp
->chunks
>>= 1) == 0) {
245 lmutex_unlock(&bp
->bucket_lock
);
251 void *next
= (void *)((caddr_t
)ptr
+ size
);
252 *(void **)ptr
= next
;
255 *(void **)ptr
= NULL
;
258 bp
->free_list
= *(void **)ptr
;
260 lmutex_unlock(&bp
->bucket_lock
);
262 * We maintain the free list already zeroed except for the pointer
263 * stored at the head of the block (mmap() allocates memory already
264 * set to zero), so all we have to do is zero out the pointer.
266 *(void **)ptr
= NULL
;
271 lfree(void *ptr
, size_t size
)
273 int bucketnum
= getbucketnum(size
);
277 /* round size up to the proper power of 2 */
278 size
= (size_t)MINSIZE
<< bucketnum
;
280 if (bucketnum
>= NBUCKETS
) {
281 /* see comment below */
282 if (((uintptr_t)ptr
& (CHUNKSIZE
- 1)) != 0)
284 (void) munmap(ptr
, size
);
289 * If the low order bits are not all zero as expected, then panic.
290 * This can be caused by an application calling, for example,
291 * pthread_attr_destroy() without having first called
292 * pthread_attr_init() (thereby passing uninitialized data
293 * to pthread_attr_destroy() who then calls lfree() with
294 * the uninitialized data).
296 if (((uintptr_t)ptr
& (size
- 1)) != 0)
300 * Zeroing the memory here saves time later when reallocating it.
302 (void) memset(ptr
, 0, size
);
304 if ((self
= __curthread()) == NULL
)
305 bp
= &__uberdata
.bucket
[bucketnum
];
307 bp
= &self
->ul_uberdata
->bucket
[bucketnum
];
308 lmutex_lock(&bp
->bucket_lock
);
310 *(void **)ptr
= bp
->free_list
;
313 lmutex_unlock(&bp
->bucket_lock
);
317 thr_panic("lfree() called with a misaligned pointer");
321 * The following functions can be used internally to libc
322 * to make memory allocations in the style of malloc()/free()
323 * (where the size of the allocation is not remembered by the caller)
324 * but which are safe to use within critical sections, that is,
325 * sections of code bounded by enter_critical()/exit_critical(),
326 * lmutex_lock()/lmutex_unlock() or lrw_rdlock()/lrw_wrlock()/lrw_unlock().
328 * These functions must never be used to allocate memory that is
329 * passed out of libc, for example by strdup(), because it is a
330 * fatal error to free() an object allocated by libc_malloc().
331 * Such objects can only be freed by calling libc_free().
342 char private_align
[ALIGNMENT
];
346 libc_malloc(size_t size
)
348 private_header_t
*ptr
;
350 size
= (size_t)MINSIZE
<< getbucketnum(size
+ sizeof (*ptr
));
351 if ((ptr
= lmalloc(size
)) == NULL
)
353 ptr
->private_size
= size
;
358 libc_realloc(void *old
, size_t size
)
360 private_header_t
*ptr
;
363 size
= (size_t)MINSIZE
<< getbucketnum(size
+ sizeof (*ptr
));
364 if ((ptr
= lmalloc(size
)) == NULL
)
366 ptr
->private_size
= size
;
369 ptr
= (private_header_t
*)old
- 1;
370 if (size
>= ptr
->private_size
)
371 size
= ptr
->private_size
;
372 (void) memcpy(new, old
, size
- sizeof (*ptr
));
373 lfree(ptr
, ptr
->private_size
);
381 private_header_t
*ptr
;
384 ptr
= (private_header_t
*)p
- 1;
385 lfree(ptr
, ptr
->private_size
);
390 libc_strdup(const char *s1
)
392 char *s2
= libc_malloc(strlen(s1
) + 1);
395 (void) strcpy(s2
, s1
);