1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2019 The FreeBSD Foundation 5 * All rights reserved. 6 * 7 * This software was developed by Konstantin Belousov <kib@FreeBSD.org> 8 * under sponsorship from the FreeBSD Foundation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #include <sys/types.h> 34 #include <sys/mman.h> 35 #include <rtld_malloc.h> 36 #include "thr_private.h" 37 38 int npagesizes; 39 size_t *pagesizes; 40 static size_t pagesizes_d[2]; 41 static struct umutex thr_malloc_umtx; 42 static u_int thr_malloc_umtx_level; 43 44 void 45 __thr_malloc_init(void) 46 { 47 48 if (npagesizes != 0) 49 return; 50 npagesizes = getpagesizes(pagesizes_d, nitems(pagesizes_d)); 51 if (npagesizes == -1) { 52 PANIC("Unable to read page sizes"); 53 } 54 pagesizes = pagesizes_d; 55 _thr_umutex_init(&thr_malloc_umtx); 56 } 57 58 static void 59 thr_malloc_lock(struct pthread *curthread) 60 { 61 uint32_t curtid; 62 63 if (curthread == NULL) 64 return; 65 curthread->locklevel++; 66 curtid = TID(curthread); 67 if ((uint32_t)thr_malloc_umtx.m_owner == curtid) 68 thr_malloc_umtx_level++; 69 else 70 _thr_umutex_lock(&thr_malloc_umtx, curtid); 71 } 72 73 static void 74 thr_malloc_unlock(struct pthread *curthread) 75 { 76 77 if (curthread == NULL) 78 return; 79 if (thr_malloc_umtx_level > 0) 80 thr_malloc_umtx_level--; 81 else 82 _thr_umutex_unlock(&thr_malloc_umtx, TID(curthread)); 83 curthread->locklevel--; 84 _thr_ast(curthread); 85 } 86 87 void * 88 __thr_calloc(size_t num, size_t size) 89 { 90 struct pthread *curthread; 91 void *res; 92 93 curthread = _get_curthread(); 94 thr_malloc_lock(curthread); 95 res = __crt_calloc(num, size); 96 thr_malloc_unlock(curthread); 97 return (res); 98 } 99 100 void 101 __thr_free(void *cp) 102 { 103 struct pthread *curthread; 104 105 curthread = _get_curthread(); 106 thr_malloc_lock(curthread); 107 __crt_free(cp); 108 thr_malloc_unlock(curthread); 109 } 110 111 void * 112 __thr_malloc(size_t nbytes) 113 { 114 struct pthread *curthread; 115 void *res; 116 117 curthread = _get_curthread(); 118 thr_malloc_lock(curthread); 119 res = __crt_malloc(nbytes); 120 thr_malloc_unlock(curthread); 121 return (res); 122 } 123 124 void * 125 __thr_realloc(void *cp, size_t nbytes) 126 { 127 struct pthread *curthread; 128 void *res; 129 130 curthread = _get_curthread(); 131 thr_malloc_lock(curthread); 132 res = __crt_realloc(cp, nbytes); 133 thr_malloc_unlock(curthread); 134 return (res); 135 } 136 137 void 138 __thr_malloc_prefork(struct pthread *curthread) 139 { 140 141 _thr_umutex_lock(&thr_malloc_umtx, TID(curthread)); 142 } 143 144 void 145 __thr_malloc_postfork(struct pthread *curthread) 146 { 147 148 _thr_umutex_unlock(&thr_malloc_umtx, TID(curthread)); 149 } 150