xref: /freebsd-src/lib/libthr/thread/thr_malloc.c (revision 5c2bc3db201a4fe8d7911cf816bea104d5dc2138)
1381c2d2eSKonstantin Belousov /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3381c2d2eSKonstantin Belousov  *
4381c2d2eSKonstantin Belousov  * Copyright (c) 2019 The FreeBSD Foundation
5381c2d2eSKonstantin Belousov  *
6381c2d2eSKonstantin Belousov  * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
7381c2d2eSKonstantin Belousov  * under sponsorship from the FreeBSD Foundation.
8381c2d2eSKonstantin Belousov  *
9381c2d2eSKonstantin Belousov  * Redistribution and use in source and binary forms, with or without
10381c2d2eSKonstantin Belousov  * modification, are permitted provided that the following conditions
11381c2d2eSKonstantin Belousov  * are met:
12381c2d2eSKonstantin Belousov  * 1. Redistributions of source code must retain the above copyright
13381c2d2eSKonstantin Belousov  *    notice, this list of conditions and the following disclaimer.
14381c2d2eSKonstantin Belousov  * 2. Redistributions in binary form must reproduce the above copyright
15381c2d2eSKonstantin Belousov  *    notice, this list of conditions and the following disclaimer in the
16381c2d2eSKonstantin Belousov  *    documentation and/or other materials provided with the distribution.
17381c2d2eSKonstantin Belousov  *
18381c2d2eSKonstantin Belousov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19381c2d2eSKonstantin Belousov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20381c2d2eSKonstantin Belousov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21381c2d2eSKonstantin Belousov  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22381c2d2eSKonstantin Belousov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23381c2d2eSKonstantin Belousov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24381c2d2eSKonstantin Belousov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25381c2d2eSKonstantin Belousov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26381c2d2eSKonstantin Belousov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27381c2d2eSKonstantin Belousov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28381c2d2eSKonstantin Belousov  * SUCH DAMAGE.
29381c2d2eSKonstantin Belousov  */
30381c2d2eSKonstantin Belousov 
31381c2d2eSKonstantin Belousov #include <sys/types.h>
32381c2d2eSKonstantin Belousov #include <sys/mman.h>
33381c2d2eSKonstantin Belousov #include <rtld_malloc.h>
34381c2d2eSKonstantin Belousov #include "thr_private.h"
35381c2d2eSKonstantin Belousov 
36381c2d2eSKonstantin Belousov int npagesizes;
37381c2d2eSKonstantin Belousov size_t *pagesizes;
38381c2d2eSKonstantin Belousov static size_t pagesizes_d[2];
39381c2d2eSKonstantin Belousov static struct umutex thr_malloc_umtx;
4085d02822SKonstantin Belousov static u_int thr_malloc_umtx_level;
41381c2d2eSKonstantin Belousov 
42381c2d2eSKonstantin Belousov void
43381c2d2eSKonstantin Belousov __thr_malloc_init(void)
44381c2d2eSKonstantin Belousov {
45381c2d2eSKonstantin Belousov 
46e4314da2SKonstantin Belousov 	if (npagesizes != 0)
47e4314da2SKonstantin Belousov 		return;
48381c2d2eSKonstantin Belousov 	npagesizes = getpagesizes(pagesizes_d, nitems(pagesizes_d));
49381c2d2eSKonstantin Belousov 	if (npagesizes == -1) {
50c7904405SAndrew Turner 		PANIC("Unable to read page sizes");
51381c2d2eSKonstantin Belousov 	}
52381c2d2eSKonstantin Belousov 	pagesizes = pagesizes_d;
53381c2d2eSKonstantin Belousov 	_thr_umutex_init(&thr_malloc_umtx);
54381c2d2eSKonstantin Belousov }
55381c2d2eSKonstantin Belousov 
56381c2d2eSKonstantin Belousov static void
57381c2d2eSKonstantin Belousov thr_malloc_lock(struct pthread *curthread)
58381c2d2eSKonstantin Belousov {
5985d02822SKonstantin Belousov 	uint32_t curtid;
60381c2d2eSKonstantin Belousov 
61e4314da2SKonstantin Belousov 	if (curthread == NULL)
62e4314da2SKonstantin Belousov 		return;
63381c2d2eSKonstantin Belousov 	curthread->locklevel++;
6485d02822SKonstantin Belousov 	curtid = TID(curthread);
6585d02822SKonstantin Belousov 	if ((uint32_t)thr_malloc_umtx.m_owner == curtid)
6685d02822SKonstantin Belousov 		thr_malloc_umtx_level++;
6785d02822SKonstantin Belousov 	else
6885d02822SKonstantin Belousov 		_thr_umutex_lock(&thr_malloc_umtx, curtid);
69381c2d2eSKonstantin Belousov }
70381c2d2eSKonstantin Belousov 
71381c2d2eSKonstantin Belousov static void
72381c2d2eSKonstantin Belousov thr_malloc_unlock(struct pthread *curthread)
73381c2d2eSKonstantin Belousov {
74381c2d2eSKonstantin Belousov 
75e4314da2SKonstantin Belousov 	if (curthread == NULL)
76e4314da2SKonstantin Belousov 		return;
7785d02822SKonstantin Belousov 	if (thr_malloc_umtx_level > 0)
7885d02822SKonstantin Belousov 		thr_malloc_umtx_level--;
7985d02822SKonstantin Belousov 	else
80381c2d2eSKonstantin Belousov 		_thr_umutex_unlock(&thr_malloc_umtx, TID(curthread));
81381c2d2eSKonstantin Belousov 	curthread->locklevel--;
82381c2d2eSKonstantin Belousov 	_thr_ast(curthread);
83381c2d2eSKonstantin Belousov }
84381c2d2eSKonstantin Belousov 
85381c2d2eSKonstantin Belousov void *
86381c2d2eSKonstantin Belousov __thr_calloc(size_t num, size_t size)
87381c2d2eSKonstantin Belousov {
88381c2d2eSKonstantin Belousov 	struct pthread *curthread;
89381c2d2eSKonstantin Belousov 	void *res;
90381c2d2eSKonstantin Belousov 
91381c2d2eSKonstantin Belousov 	curthread = _get_curthread();
92381c2d2eSKonstantin Belousov 	thr_malloc_lock(curthread);
93381c2d2eSKonstantin Belousov 	res = __crt_calloc(num, size);
94381c2d2eSKonstantin Belousov 	thr_malloc_unlock(curthread);
95381c2d2eSKonstantin Belousov 	return (res);
96381c2d2eSKonstantin Belousov }
97381c2d2eSKonstantin Belousov 
98381c2d2eSKonstantin Belousov void
99381c2d2eSKonstantin Belousov __thr_free(void *cp)
100381c2d2eSKonstantin Belousov {
101381c2d2eSKonstantin Belousov 	struct pthread *curthread;
102381c2d2eSKonstantin Belousov 
103381c2d2eSKonstantin Belousov 	curthread = _get_curthread();
104381c2d2eSKonstantin Belousov 	thr_malloc_lock(curthread);
105381c2d2eSKonstantin Belousov 	__crt_free(cp);
106381c2d2eSKonstantin Belousov 	thr_malloc_unlock(curthread);
107381c2d2eSKonstantin Belousov }
108381c2d2eSKonstantin Belousov 
109381c2d2eSKonstantin Belousov void *
110381c2d2eSKonstantin Belousov __thr_malloc(size_t nbytes)
111381c2d2eSKonstantin Belousov {
112381c2d2eSKonstantin Belousov 	struct pthread *curthread;
113381c2d2eSKonstantin Belousov 	void *res;
114381c2d2eSKonstantin Belousov 
115381c2d2eSKonstantin Belousov 	curthread = _get_curthread();
116381c2d2eSKonstantin Belousov 	thr_malloc_lock(curthread);
117381c2d2eSKonstantin Belousov 	res = __crt_malloc(nbytes);
118381c2d2eSKonstantin Belousov 	thr_malloc_unlock(curthread);
119381c2d2eSKonstantin Belousov 	return (res);
120381c2d2eSKonstantin Belousov }
121381c2d2eSKonstantin Belousov 
122381c2d2eSKonstantin Belousov void *
123381c2d2eSKonstantin Belousov __thr_realloc(void *cp, size_t nbytes)
124381c2d2eSKonstantin Belousov {
125381c2d2eSKonstantin Belousov 	struct pthread *curthread;
126381c2d2eSKonstantin Belousov 	void *res;
127381c2d2eSKonstantin Belousov 
128381c2d2eSKonstantin Belousov 	curthread = _get_curthread();
129381c2d2eSKonstantin Belousov 	thr_malloc_lock(curthread);
130381c2d2eSKonstantin Belousov 	res = __crt_realloc(cp, nbytes);
131381c2d2eSKonstantin Belousov 	thr_malloc_unlock(curthread);
132381c2d2eSKonstantin Belousov 	return (res);
133381c2d2eSKonstantin Belousov }
134381c2d2eSKonstantin Belousov 
135381c2d2eSKonstantin Belousov void
136381c2d2eSKonstantin Belousov __thr_malloc_prefork(struct pthread *curthread)
137381c2d2eSKonstantin Belousov {
138381c2d2eSKonstantin Belousov 
139381c2d2eSKonstantin Belousov 	_thr_umutex_lock(&thr_malloc_umtx, TID(curthread));
140381c2d2eSKonstantin Belousov }
141381c2d2eSKonstantin Belousov 
142381c2d2eSKonstantin Belousov void
143381c2d2eSKonstantin Belousov __thr_malloc_postfork(struct pthread *curthread)
144381c2d2eSKonstantin Belousov {
145381c2d2eSKonstantin Belousov 
146381c2d2eSKonstantin Belousov 	_thr_umutex_unlock(&thr_malloc_umtx, TID(curthread));
147381c2d2eSKonstantin Belousov }
148