Our qsort() is inappropriate for kernel use because it makes recursive

calls. Replace it with a kheapsort() function in kernel. Pointed out
by tron@.
This commit is contained in:
ad 2008-11-16 16:15:58 +00:00
parent 974cf03d8d
commit c6555ead19
5 changed files with 37 additions and 20 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: heapsort.c,v 1.16 2008/03/11 18:04:59 rmind Exp $ */
/* $NetBSD: heapsort.c,v 1.1 2008/11/16 16:15:58 ad Exp $ */
/*-
* Copyright (c) 1991, 1993
@ -46,10 +46,15 @@
#if 0
static char sccsid[] = "from: @(#)heapsort.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: heapsort.c,v 1.16 2008/03/11 18:04:59 rmind Exp $");
__RCSID("$NetBSD: heapsort.c,v 1.1 2008/11/16 16:15:58 ad Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#ifdef _KERNEL
#include <sys/types.h>
#include <lib/libkern/libkern.h>
#else /* _KERNEL */
#include "namespace.h"
#include <sys/types.h>
@ -65,6 +70,7 @@ __RCSID("$NetBSD: heapsort.c,v 1.16 2008/03/11 18:04:59 rmind Exp $");
#ifdef __weak_alias
__weak_alias(heapsort,_heapsort)
#endif
#endif /* _KERNEL */
/*
* Swap two areas of size number of bytes. Although qsort(3) permits random
@ -161,13 +167,22 @@ __weak_alias(heapsort,_heapsort)
* a data set that will trigger the worst case is nonexistent. Heapsort's
* only advantage over quicksort is that it requires little additional memory.
*/
#ifdef _KERNEL
int
kheapsort(void *vbase, size_t nmemb, size_t size,
int (*compar)(const void *, const void *), void *k)
#else
int
heapsort(void *vbase, size_t nmemb, size_t size,
int (*compar) __P((const void *, const void *)))
int (*compar)(const void *, const void *))
#endif
{
size_t cnt, i, j, l;
char tmp, *tmp1, *tmp2;
char *base, *k, *p, *t;
char *base, *p, *t;
#ifndef _KERNEL
char *k;
#endif
_DIAGASSERT(vbase != NULL);
_DIAGASSERT(compar != NULL);
@ -176,12 +191,16 @@ heapsort(void *vbase, size_t nmemb, size_t size,
return (0);
if (!size) {
#ifndef _KERNEL
errno = EINVAL;
#endif
return (-1);
}
#ifndef _KERNEL
if ((k = malloc(size)) == NULL)
return (-1);
#endif
/*
* Items are numbered from 1 to nmemb, so offset from size bytes
@ -203,6 +222,8 @@ heapsort(void *vbase, size_t nmemb, size_t size,
--nmemb;
SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2);
}
#ifndef _KERNEL
free(k);
#endif
return (0);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: qsort.c,v 1.1 2008/11/16 15:01:26 ad Exp $ */
/* $NetBSD: qsort.c,v 1.17 2008/11/16 16:15:58 ad Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -34,21 +34,15 @@
#if 0
static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: qsort.c,v 1.1 2008/11/16 15:01:26 ad Exp $");
__RCSID("$NetBSD: qsort.c,v 1.17 2008/11/16 16:15:58 ad Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#ifdef _LIBC
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#endif
#ifdef _KERNEL
#include <lib/libkern/libkern.h>
#endif
static inline char *med3 __P((char *, char *, char *,
int (*)(const void *, const void *)));

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_ksyms.c,v 1.45 2008/11/16 15:29:53 ad Exp $ */
/* $NetBSD: kern_ksyms.c,v 1.46 2008/11/16 16:15:58 ad Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -71,7 +71,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.45 2008/11/16 15:29:53 ad Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.46 2008/11/16 16:15:58 ad Exp $");
#ifdef _KERNEL
#include "opt_ddb.h"
@ -250,7 +250,7 @@ addsymtab(const char *name, void *symstart, size_t symsize,
void *strstart, size_t strsize, struct ksyms_symtab *tab,
void *newstart)
{
Elf_Sym *sym, *nsym;
Elf_Sym *sym, *nsym, ts;
int i, j, n, nglob;
char *str;
@ -316,7 +316,8 @@ addsymtab(const char *name, void *symstart, size_t symsize,
tab->sd_symsize = n * sizeof(Elf_Sym);
tab->sd_nglob = nglob;
addsymtab_strstart = str;
qsort(nsym, n, sizeof(Elf_Sym), addsymtab_compar);
if (kheapsort(nsym, n, sizeof(Elf_Sym), addsymtab_compar, &ts) != 0)
panic("addsymtab");
/* ksymsread() is unlocked, so membar. */
membar_producer();

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.90 2008/11/16 15:01:26 ad Exp $
# $NetBSD: Makefile,v 1.91 2008/11/16 16:15:58 ad Exp $
LIB= kern
NOPIC= # defined
@ -55,7 +55,7 @@ SRCS+= strtoll.c strtoull.c strtoumax.c
SRCS+= xlat_mbr_fstype.c
SRCS+= rb.c qsort.c
SRCS+= rb.c heapsort.c
# Files to clean up
CLEANFILES+= lib${LIB}.o lib${LIB}.po

View File

@ -1,4 +1,4 @@
/* $NetBSD: libkern.h,v 1.83 2008/11/16 15:01:26 ad Exp $ */
/* $NetBSD: libkern.h,v 1.84 2008/11/16 16:15:58 ad Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -340,5 +340,6 @@ u_long strtoul __P((const char *, char **, int));
long long strtoll __P((const char *, char **, int));
unsigned long long strtoull __P((const char *, char **, int));
uintmax_t strtoumax __P((const char *, char **, int));
void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
int kheapsort(void *, size_t, size_t, int (*)(const void *, const void *),
void *);
#endif /* !_LIB_LIBKERN_LIBKERN_H_ */