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