diff options
author | Ulrich Drepper <drepper@redhat.com> | 2000-02-28 08:14:33 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2000-02-28 08:14:33 +0000 |
commit | 8358825c703091ef71f4e8a49d0186343c67368c (patch) | |
tree | cff4387b561bb0c0a1fac089a394d18eced17793 /stdlib/msort.c | |
parent | e5aa91c34ac93ad91b910b55fd8781c267a81780 (diff) | |
download | glibc-8358825c703091ef71f4e8a49d0186343c67368c.tar.gz glibc-8358825c703091ef71f4e8a49d0186343c67368c.tar.xz glibc-8358825c703091ef71f4e8a49d0186343c67368c.zip |
Update.
2000-02-28 Ulrich Drepper <drepper@redhat.com> * stdlib/msort.c (qsort): Limit the amount of memory spend on a temporary array for the mergesort.
Diffstat (limited to 'stdlib/msort.c')
-rw-r--r-- | stdlib/msort.c | 60 |
1 files changed, 49 insertions, 11 deletions
diff --git a/stdlib/msort.c b/stdlib/msort.c index c03f6f2982..d174edd3b7 100644 --- a/stdlib/msort.c +++ b/stdlib/msort.c @@ -1,6 +1,6 @@ /* An alternative to qsort, with an identical interface. This file is part of the GNU C Library. - Copyright (C) 1992, 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + Copyright (C) 1992, 1995-1997, 1999, 2000 Free Software Foundation, Inc. Written by Mike Haertel, September 1988. The GNU C Library is free software; you can redistribute it and/or @@ -21,6 +21,7 @@ #include <alloca.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include <memcopy.h> #include <errno.h> @@ -94,20 +95,57 @@ qsort (void *b, size_t n, size_t s, __compar_fn_t cmp) msort_with_tmp (b, n, s, cmp, __alloca (size)); else { - /* It's somewhat large, so malloc it. */ - int save = errno; - char *tmp = malloc (size); - if (tmp == NULL) + /* We should avoid allocating too much memory since this might + have to be backed up by swap space. */ + static long int phys_pages; + static int pagesize; + + if (phys_pages == 0) { - /* Couldn't get space, so use the slower algorithm - that doesn't need a temporary array. */ - _quicksort (b, n, s, cmp); + phys_pages = __sysconf (_SC_PHYS_PAGES); + + if (phys_pages == -1) + /* Error while determining the memory size. So let's + assume there is enough memory. Otherwise the + implementer should provide a complete implementation of + the `sysconf' function. */ + phys_pages = (long int) (~0ul >> 1); + + /* The following determines that we will never use more than + a quarter of the physical memory. */ + phys_pages /= 4; + + pagesize = __sysconf (_SC_PAGESIZE); } + + /* Just a comment here. We cannot compute + phys_pages * pagesize + and compare the needed amount of memory against this value. + The problem is that some systems might have more physical + memory then can be represented with a `size_t' value (when + measured in bytes. */ + + /* If the memory requirements are too high don't allocate memory. */ + if (size / pagesize > phys_pages) + _quicksort (b, n, s, cmp); else { - msort_with_tmp (b, n, s, cmp, tmp); - free (tmp); + /* It's somewhat large, so malloc it. */ + int save = errno; + char *tmp = malloc (size); + if (tmp == NULL) + { + /* Couldn't get space, so use the slower algorithm + that doesn't need a temporary array. */ + __set_errno (save); + _quicksort (b, n, s, cmp); + } + else + { + __set_errno (save); + msort_with_tmp (b, n, s, cmp, tmp); + free (tmp); + } } - __set_errno (save); } } |