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