about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2021-01-30 17:28:08 -0500
committerRich Felker <dalias@aerifal.cx>2021-01-30 17:28:08 -0500
commit9b77aaca86b53c367f23505c24dd3c02e240efad (patch)
tree7922f847a292971a7dbe61f68acd503d9a58a371 /src
parent98b9df994c85dcb6a8a5a9099495dd44c7cf2bce (diff)
downloadmusl-9b77aaca86b53c367f23505c24dd3c02e240efad.tar.gz
musl-9b77aaca86b53c367f23505c24dd3c02e240efad.tar.xz
musl-9b77aaca86b53c367f23505c24dd3c02e240efad.zip
oldmalloc: preserve errno across free
as an outcome of Austin Group issue #385, future versions of the
standard will require free not to alter the value of errno. save and
restore it individually around the calls to madvise and munmap so that
the cost is not imposed on calls to free that do not result in any
syscall.
Diffstat (limited to 'src')
-rw-r--r--src/malloc/oldmalloc/malloc.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/src/malloc/oldmalloc/malloc.c b/src/malloc/oldmalloc/malloc.c
index a5cbdb68..25d00d44 100644
--- a/src/malloc/oldmalloc/malloc.c
+++ b/src/malloc/oldmalloc/malloc.c
@@ -481,12 +481,14 @@ void __bin_chunk(struct chunk *self)
 	if (size > RECLAIM && (size^(size-osize)) > size-osize) {
 		uintptr_t a = (uintptr_t)self + SIZE_ALIGN+PAGE_SIZE-1 & -PAGE_SIZE;
 		uintptr_t b = (uintptr_t)next - SIZE_ALIGN & -PAGE_SIZE;
+		int e = errno;
 #if 1
 		__madvise((void *)a, b-a, MADV_DONTNEED);
 #else
 		__mmap((void *)a, b-a, PROT_READ|PROT_WRITE,
 			MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0);
 #endif
+		errno = e;
 	}
 
 	unlock_bin(i);
@@ -499,7 +501,9 @@ static void unmap_chunk(struct chunk *self)
 	size_t len = CHUNK_SIZE(self) + extra;
 	/* Crash on double free */
 	if (extra & 1) a_crash();
+	int e = errno;
 	__munmap(base, len);
+	errno = e;
 }
 
 void free(void *p)