static void msort_r(uint8_t *in, uint8_t *out, size_t size, int l, int r, sort_cmp cmp) { if ((r - l) < 2) { return; } int m = (l + r) / 2; msort_r(out, in, size, l, m, cmp); msort_r(out, in, size, m, r, cmp); merge(in, out, size, l, m, r, cmp); }
void msort_noalloc(void *data, void *tmp, int num, size_t size, sort_cmp cmp) { memcpy(tmp, data, num * size); msort_r(tmp, data, size, 0, num, cmp); }
void *thread_run(void *ptr) { int retcode; struct thread_arg *arg = (struct thread_arg *) ptr; char **strings = arg->arr.strings; int len = arg->arr.len; int idx = arg->thread_idx; if (use_psort) { switch (selected_mt_sort_type) { case MT_HEAP_SORT: parallel_hsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, psort_internal_threads); break; case MT_TERNARY_HEAP_SORT: parallel_ternary_hsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, psort_internal_threads); break; case MT_QUICK_SORT: parallel_qsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, psort_internal_threads); break; case MT_FLASH_SORT: parallel_fsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, metric_str_full, (void *) NULL, psort_internal_threads); break; case MT_FLASH_SORT_BIN: parallel_fsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, metric_binary_printable_pref, (void *) NULL, psort_internal_threads); break; case MT_INSERTION_SORT: parallel_isort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, psort_internal_threads); break; case MT_MERGE_SORT: parallel_msort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, psort_internal_threads); break; default: /* should *never* happen: */ handle_error_myerrno(-1, -1, "wrong mt_sort_type", PROCESS_EXIT); } } else { switch (selected_mt_sort_type) { case MT_HEAP_SORT: hsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL); break; case MT_TERNARY_HEAP_SORT: ternary_hsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL); break; case MT_QUICK_SORT: qsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL); break; case MT_FLASH_SORT: fsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, metric_str_full, (void *) NULL); break; case MT_FLASH_SORT_BIN: fsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, metric_binary_printable_pref, (void *) NULL); break; case MT_INSERTION_SORT: isort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL); break; case MT_MERGE_SORT: msort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL); break; default: /* should *never* happen: */ handle_error_myerrno(-1, -1, "wrong mt_sort_type", PROCESS_EXIT); } } for (int step = 1; step < thread_count; step *= 2) { retcode = pthread_barrier_wait(& barrier); if (retcode == PTHREAD_BARRIER_SERIAL_THREAD) { pthread_mutex_lock(&output_mutex); /* printf("thread %ld (%d) is PTHREAD_BARRIER_SERIAL_THREAD=%d\n", (long) id, tid, retcode); */ pthread_mutex_unlock(&output_mutex); } else { handle_thread_error(retcode, "pthread_barrier_wait", THREAD_EXIT); } if (idx % (2*step) == 0) { int other_idx = idx + step; if (other_idx < thread_count) { int i = 0; int j = 0; int k = 0; int m = segments[idx].arr.len; int n = segments[other_idx].arr.len; int total_len = m + n; char_ptr *strings = malloc(total_len * sizeof(char_ptr)); char_ptr *left = segments[idx].arr.strings; char_ptr *right = segments[other_idx].arr.strings; while (i+j < total_len) { if (i >= m) { while (j < n) { strings[k++] = right[j++]; } } else if (j >= n) { while (i < m) { strings[k++] = left[i++]; } } else { if (strcmp(left[i], right[j]) <= 0) { strings[k++] = left[i++]; } else { strings[k++] = right[j++]; } } } segments[idx].arr.len = total_len; segments[idx].arr.strings = strings; segments[other_idx].arr.len = 0; segments[other_idx].arr.strings = NULL; } } } return (void *) NULL; }