Home | History | Annotate | Line # | Download | only in libbacktrace
      1      1.1  christos /* sort.c -- Sort without allocating memory
      2  1.1.1.2  christos    Copyright (C) 2012-2024 Free Software Foundation, Inc.
      3      1.1  christos    Written by Ian Lance Taylor, Google.
      4      1.1  christos 
      5      1.1  christos Redistribution and use in source and binary forms, with or without
      6      1.1  christos modification, are permitted provided that the following conditions are
      7      1.1  christos met:
      8      1.1  christos 
      9      1.1  christos     (1) Redistributions of source code must retain the above copyright
     10      1.1  christos     notice, this list of conditions and the following disclaimer.
     11      1.1  christos 
     12      1.1  christos     (2) Redistributions in binary form must reproduce the above copyright
     13      1.1  christos     notice, this list of conditions and the following disclaimer in
     14      1.1  christos     the documentation and/or other materials provided with the
     15      1.1  christos     distribution.
     16      1.1  christos 
     17      1.1  christos     (3) The name of the author may not be used to
     18      1.1  christos     endorse or promote products derived from this software without
     19      1.1  christos     specific prior written permission.
     20      1.1  christos 
     21      1.1  christos THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22      1.1  christos IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     23      1.1  christos WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     24      1.1  christos DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     25      1.1  christos INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     26      1.1  christos (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     27      1.1  christos SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28      1.1  christos HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     29      1.1  christos STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     30      1.1  christos IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31      1.1  christos POSSIBILITY OF SUCH DAMAGE.  */
     32      1.1  christos 
     33      1.1  christos #include "config.h"
     34      1.1  christos 
     35      1.1  christos #include <stddef.h>
     36      1.1  christos #include <sys/types.h>
     37      1.1  christos 
     38      1.1  christos #include "backtrace.h"
     39      1.1  christos #include "internal.h"
     40      1.1  christos 
     41      1.1  christos /* The GNU glibc version of qsort allocates memory, which we must not
     42      1.1  christos    do if we are invoked by a signal handler.  So provide our own
     43      1.1  christos    sort.  */
     44      1.1  christos 
     45      1.1  christos static void
     46      1.1  christos swap (char *a, char *b, size_t size)
     47      1.1  christos {
     48      1.1  christos   size_t i;
     49      1.1  christos 
     50      1.1  christos   for (i = 0; i < size; i++, a++, b++)
     51      1.1  christos     {
     52      1.1  christos       char t;
     53      1.1  christos 
     54      1.1  christos       t = *a;
     55      1.1  christos       *a = *b;
     56      1.1  christos       *b = t;
     57      1.1  christos     }
     58      1.1  christos }
     59      1.1  christos 
     60      1.1  christos void
     61      1.1  christos backtrace_qsort (void *basearg, size_t count, size_t size,
     62      1.1  christos 		 int (*compar) (const void *, const void *))
     63      1.1  christos {
     64      1.1  christos   char *base = (char *) basearg;
     65      1.1  christos   size_t i;
     66      1.1  christos   size_t mid;
     67      1.1  christos 
     68      1.1  christos  tail_recurse:
     69      1.1  christos   if (count < 2)
     70      1.1  christos     return;
     71      1.1  christos 
     72      1.1  christos   /* The symbol table and DWARF tables, which is all we use this
     73      1.1  christos      routine for, tend to be roughly sorted.  Pick the middle element
     74      1.1  christos      in the array as our pivot point, so that we are more likely to
     75      1.1  christos      cut the array in half for each recursion step.  */
     76      1.1  christos   swap (base, base + (count / 2) * size, size);
     77      1.1  christos 
     78      1.1  christos   mid = 0;
     79      1.1  christos   for (i = 1; i < count; i++)
     80      1.1  christos     {
     81      1.1  christos       if ((*compar) (base, base + i * size) > 0)
     82      1.1  christos 	{
     83      1.1  christos 	  ++mid;
     84      1.1  christos 	  if (i != mid)
     85      1.1  christos 	    swap (base + mid * size, base + i * size, size);
     86      1.1  christos 	}
     87      1.1  christos     }
     88      1.1  christos 
     89      1.1  christos   if (mid > 0)
     90      1.1  christos     swap (base, base + mid * size, size);
     91      1.1  christos 
     92      1.1  christos   /* Recurse with the smaller array, loop with the larger one.  That
     93      1.1  christos      ensures that our maximum stack depth is log count.  */
     94      1.1  christos   if (2 * mid < count)
     95      1.1  christos     {
     96      1.1  christos       backtrace_qsort (base, mid, size, compar);
     97      1.1  christos       base += (mid + 1) * size;
     98      1.1  christos       count -= mid + 1;
     99      1.1  christos       goto tail_recurse;
    100      1.1  christos     }
    101      1.1  christos   else
    102      1.1  christos     {
    103      1.1  christos       backtrace_qsort (base + (mid + 1) * size, count - (mid + 1),
    104      1.1  christos 		       size, compar);
    105      1.1  christos       count = mid;
    106      1.1  christos       goto tail_recurse;
    107      1.1  christos     }
    108      1.1  christos }
    109