Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the stock qsort implementation from libc #91

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 4 additions & 231 deletions dmalloc_tab.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,234 +224,6 @@ static int entry_cmp(const void *entry1_p, const void *entry2_p)
}
}

/*
* static void swap_bytes
*
* Swap the values between two items of a specified size.
*
* ARGUMENTS:
*
* item1_p -> Pointer to the first item.
*
* item2_p -> Pointer to the first item.
*
* ele_size -> Size of the two items.
*/
static void swap_bytes(unsigned char *item1_p, unsigned char *item2_p,
int ele_size)
{
unsigned char char_temp;

for (; ele_size > 0; ele_size--) {
char_temp = *item1_p;
*item1_p = *item2_p;
*item2_p = char_temp;
item1_p++;
item2_p++;
}
}

/*
* static void insert_sort
*
* Do an insertion sort which is faster for small numbers of items and
* better if the items are already sorted.
*
* ARGUMENTS:
*
* first_p <-> Start of the list that we are splitting.
*
* last_p <-> Last entry in the list that we are splitting.
*
* holder_p <-> Location of hold area we can store an entry.
*
* ele_size -> Size of the each element in the list.
*/
static void insert_sort(unsigned char *first_p, unsigned char *last_p,
unsigned char *holder_p,
const unsigned int ele_size)
{
unsigned char *inner_p, *outer_p;

for (outer_p = first_p + ele_size; outer_p <= last_p; ) {

/* look for the place to insert the entry */
for (inner_p = outer_p - ele_size;
inner_p >= first_p && entry_cmp(outer_p, inner_p) < 0;
inner_p -= ele_size) {
}
inner_p += ele_size;

/* do we need to insert the entry in? */
if (outer_p != inner_p) {
/*
* Now we shift the entry down into its place in the already
* sorted list.
*/
memcpy(holder_p, outer_p, ele_size);
memmove(inner_p + ele_size, inner_p, outer_p - inner_p);
memcpy(inner_p, holder_p, ele_size);
}

outer_p += ele_size;
}
}

/*
* static void split
*
* This sorts an array of longs via the quick sort algorithm (it's pretty quick)
*
* ARGUMENTS:
*
* first_p -> Start of the list that we are splitting.
*
* last_p -> Last entry in the list that we are splitting.
*
* ele_size -> Size of the each element in the list.
*/
static void split(unsigned char *first_p, unsigned char *last_p,
const unsigned int ele_size)
{
unsigned char *left_p, *right_p, *pivot_p, *left_last_p, *right_first_p;
unsigned char *firsts[MAX_QSORT_SPLITS], *lasts[MAX_QSORT_SPLITS];
mem_table_t pivot;
unsigned int width, split_c = 0, min_qsort_size, size1, size2;

min_qsort_size = MAX_QSORT_PARTITION * ele_size;

while (1) {

/* find the left, right, and mid point */
left_p = first_p;
right_p = last_p;
/* is there a faster way to find this? */
width = (last_p - first_p) / ele_size;
pivot_p = first_p + ele_size * (width >> 1);

/*
* Find which of the left, middle, and right elements is the
* median (Knuth vol3 p123).
*/
if (entry_cmp(first_p, pivot_p) > 0) {
swap_bytes(first_p, pivot_p, ele_size);
}
if (entry_cmp(pivot_p, last_p) > 0) {
swap_bytes(pivot_p, last_p, ele_size);
if (entry_cmp(first_p, pivot_p) > 0) {
swap_bytes(first_p, pivot_p, ele_size);
}
}

/*
* save our pivot so we don't have to worry about hitting and
* swapping it elsewhere while we iterate across the list below.
*/
memcpy(&pivot, pivot_p, ele_size);

do {

/* shift the left side up until we reach the pivot value */
while (entry_cmp(left_p, &pivot) < 0) {
left_p += ele_size;
}
/* shift the right side down until we reach the pivot value */
while (entry_cmp(&pivot, right_p) < 0) {
right_p -= ele_size;
}

/* if we met in the middle then we are done */
if (left_p == right_p) {
left_p += ele_size;
right_p -= ele_size;
break;
}
else if (left_p < right_p) {
/*
* swap the left and right since they both were on the wrong
* size of the pivot and continue
*/
swap_bytes(left_p, right_p, ele_size);
left_p += ele_size;
right_p -= ele_size;
}
} while (left_p <= right_p);

/* Rename variables to make more sense. This will get optimized out. */
right_first_p = left_p;
left_last_p = right_p;

/* determine the size of the left and right hand parts */
size1 = left_last_p - first_p;
size2 = last_p - right_first_p;

/* is the 1st half small enough to just insert-sort? */
if (size1 < min_qsort_size) {

/* use the pivot as our temporary space */
insert_sort(first_p, left_last_p, (unsigned char *)&pivot, ele_size);

/* is the 2nd part small as well? */
if (size2 < min_qsort_size) {

/* use the pivot as our temporary space */
insert_sort(right_first_p, last_p, (unsigned char *)&pivot, ele_size);

/* pop a partition off our stack */
if (split_c == 0) {
/* we are done */
return;
}
split_c--;
first_p = firsts[split_c];
last_p = lasts[split_c];
}
else {
/* we can just handle the right side immediately */
first_p = right_first_p;
/* last_p = last_p */
}
}
else if (size2 < min_qsort_size) {

/* use the pivot as our temporary space */
insert_sort(right_first_p, last_p, (unsigned char *)&pivot, ele_size);

/* we can just handle the left side immediately */
/* first_p = first_p */
last_p = left_last_p;
}
else {
/*
* neither partition is small, we'll have to push the larger one
* of them on the stack
*/
if (split_c >= MAX_QSORT_SPLITS) {
/* sanity check here -- we should never get here */
abort();
}
if (size1 > size2) {
/* push the left partition on the stack */
firsts[split_c] = first_p;
lasts[split_c] = left_last_p;
split_c++;
/* continue handling the right side */
first_p = right_first_p;
/* last_p = last_p */
}
else {
/* push the right partition on the stack */
firsts[split_c] = right_first_p;
lasts[split_c] = last_p;
split_c++;
/* continue handling the left side */
/* first_p = first_p */
last_p = left_last_p;
}
}
}
}

/*
* static void log_slot
*
Expand Down Expand Up @@ -672,9 +444,10 @@ void _dmalloc_table_log_info(mem_table_t *mem_table, const int log_n,
}

/* sort the entries by their total-size */
split((unsigned char *)mem_table->mt_entries,
(unsigned char *)(mem_table->mt_bounds_p - 1),
sizeof(*mem_table->mt_entries));
qsort(mem_table->mt_entries,
mem_table->mt_entry_n,
sizeof(*mem_table->mt_entries),
entry_cmp);

/* display the column headers */
if (in_use_column_b) {
Expand Down
17 changes: 0 additions & 17 deletions dmalloc_tab_loc.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,6 @@

#include "conf.h"

/*
* Maximum number of splits. This should mean that these routines can
* handle at least 2^128 different values (that's _quite_ a few). And
* then you can always increase the value.
*/
#define MAX_QSORT_SPLITS 128

/*
* Maximum number of entries that must be in list for it to be
* partitioned. If there are fewer elements then just do our
* insertion sort.
*/
#define MAX_QSORT_PARTITION 8

/* comparison function */
typedef int (*compare_t)(const void *element1_p, const void *element2_p);

/*
* void HASH_MIX
*
Expand Down