Module Name:    src
Committed By:   riz
Date:           Sat Mar 13 00:53:33 UTC 2010

Modified Files:
        src/lib/libc/stdlib [netbsd-5]: jemalloc.c

Log Message:
Pull up following revision(s) (requested by enami in ticket #1327):
        lib/libc/stdlib/jemalloc.c: revision 1.21
Fix race condition on reallocation of huge category.
We need to remove the old region before mremap() since if it relesae the
old region, other thread may map it for the same huge category allocation
and insert it to the tree before we acquire a lock after mremap().
Fixes PR/42876.


To generate a diff of this commit:
cvs rdiff -u -r1.19 -r1.19.4.1 src/lib/libc/stdlib/jemalloc.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/stdlib/jemalloc.c
diff -u src/lib/libc/stdlib/jemalloc.c:1.19 src/lib/libc/stdlib/jemalloc.c:1.19.4.1
--- src/lib/libc/stdlib/jemalloc.c:1.19	Mon Jun 23 10:46:25 2008
+++ src/lib/libc/stdlib/jemalloc.c	Sat Mar 13 00:53:32 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: jemalloc.c,v 1.19 2008/06/23 10:46:25 ad Exp $	*/
+/*	$NetBSD: jemalloc.c,v 1.19.4.1 2010/03/13 00:53:32 riz Exp $	*/
 
 /*-
  * Copyright (C) 2006,2007 Jason Evans <jas...@freebsd.org>.
@@ -118,7 +118,7 @@
 
 #include <sys/cdefs.h>
 /* __FBSDID("$FreeBSD: src/lib/libc/stdlib/malloc.c,v 1.147 2007/06/15 22:00:16 jasone Exp $"); */ 
-__RCSID("$NetBSD: jemalloc.c,v 1.19 2008/06/23 10:46:25 ad Exp $");
+__RCSID("$NetBSD: jemalloc.c,v 1.19.4.1 2010/03/13 00:53:32 riz Exp $");
 
 #ifdef __FreeBSD__
 #include "libc_private.h"
@@ -2855,25 +2855,38 @@
 			/* size_t wrap-around */
 			return (NULL);
 		}
+
+		/*
+		 * Remove the old region from the tree now.  If mremap()
+		 * returns the region to the system, other thread may
+		 * map it for same huge allocation and insert it to the
+		 * tree before we acquire the mutex lock again.
+		 */
+		malloc_mutex_lock(&chunks_mtx);
+		key.chunk = __DECONST(void *, ptr);
+		/* LINTED */
+		node = RB_FIND(chunk_tree_s, &huge, &key);
+		assert(node != NULL);
+		assert(node->chunk == ptr);
+		assert(node->size == oldcsize);
+		RB_REMOVE(chunk_tree_s, &huge, node);
+		malloc_mutex_unlock(&chunks_mtx);
+
 		newptr = mremap(ptr, oldcsize, NULL, newcsize,
 		    MAP_ALIGNED(chunksize_2pow));
-		if (newptr != MAP_FAILED) {
+		if (newptr == MAP_FAILED) {
+			/* We still own the old region. */
+			malloc_mutex_lock(&chunks_mtx);
+			RB_INSERT(chunk_tree_s, &huge, node);
+			malloc_mutex_unlock(&chunks_mtx);
+		} else {
 			assert(CHUNK_ADDR2BASE(newptr) == newptr);
 
-			/* update tree */
+			/* Insert new or resized old region. */
 			malloc_mutex_lock(&chunks_mtx);
-			key.chunk = __DECONST(void *, ptr);
-			/* LINTED */
-			node = RB_FIND(chunk_tree_s, &huge, &key);
-			assert(node != NULL);
-			assert(node->chunk == ptr);
-			assert(node->size == oldcsize);
 			node->size = newcsize;
-			if (ptr != newptr) {
-				RB_REMOVE(chunk_tree_s, &huge, node);
-				node->chunk = newptr;
-				RB_INSERT(chunk_tree_s, &huge, node);
-			}
+			node->chunk = newptr;
+			RB_INSERT(chunk_tree_s, &huge, node);
 #ifdef MALLOC_STATS
 			huge_nralloc++;
 			huge_allocated += newcsize - oldcsize;

Reply via email to