libthr malloc: support recursion on thr_malloc_umtx.

One possible way the recursion can happen is during fork: suppose
that fork is called from early code that did not triggered
jemalloc(3) initialization yet. Then we lock thr_malloc lock, and
call malloc_prefork() that might require initialization of jemalloc
pthread_mutexes, calling into libthr malloc. It is safe to allow
recursion for this occurence.

PR:	252579
Reported by:	Vasily Postnicov <shamaz.mazum@gmail.com>
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Konstantin Belousov 2021-01-12 11:02:37 +02:00
parent 57f22c828e
commit 85d028223b

View File

@ -41,6 +41,7 @@ int npagesizes;
size_t *pagesizes;
static size_t pagesizes_d[2];
static struct umutex thr_malloc_umtx;
static u_int thr_malloc_umtx_level;
void
__thr_malloc_init(void)
@ -60,11 +61,16 @@ __thr_malloc_init(void)
static void
thr_malloc_lock(struct pthread *curthread)
{
uint32_t curtid;
if (curthread == NULL)
return;
curthread->locklevel++;
_thr_umutex_lock(&thr_malloc_umtx, TID(curthread));
curtid = TID(curthread);
if ((uint32_t)thr_malloc_umtx.m_owner == curtid)
thr_malloc_umtx_level++;
else
_thr_umutex_lock(&thr_malloc_umtx, curtid);
}
static void
@ -73,7 +79,10 @@ thr_malloc_unlock(struct pthread *curthread)
if (curthread == NULL)
return;
_thr_umutex_unlock(&thr_malloc_umtx, TID(curthread));
if (thr_malloc_umtx_level > 0)
thr_malloc_umtx_level--;
else
_thr_umutex_unlock(&thr_malloc_umtx, TID(curthread));
curthread->locklevel--;
_thr_ast(curthread);
}