From 692cd1a3b2610d446b7cdbbb8990b3004eba6c2c Mon Sep 17 00:00:00 2001 From: "Pedro F. Giffuni" Date: Mon, 23 Jan 2017 15:39:51 +0000 Subject: sort - Don't live-loop threads. Worker threads now use a pthread_cond_t to wait for work instead of burning the cpu up. Obtained from: DragonflyBSD (07774aea0ccf64a48fcfad8899e3bf7c8f18277a) MFC after: 2 weeks --- usr.bin/sort/radixsort.c | 52 ++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'usr.bin') diff --git a/usr.bin/sort/radixsort.c b/usr.bin/sort/radixsort.c index 79f4346eb3ec..62b946063f0f 100644 --- a/usr.bin/sort/radixsort.c +++ b/usr.bin/sort/radixsort.c @@ -83,12 +83,12 @@ static struct level_stack *g_ls; #if defined(SORT_THREADS) /* stack guarding mutex */ +static pthread_cond_t g_ls_cond; static pthread_mutex_t g_ls_mutex; /* counter: how many items are left */ static size_t sort_left; /* guarding mutex */ -static pthread_mutex_t sort_left_mutex; /* semaphore to count threads */ static sem_t mtsem; @@ -99,23 +99,25 @@ static sem_t mtsem; static inline void sort_left_dec(size_t n) { - - pthread_mutex_lock(&sort_left_mutex); + pthread_mutex_lock(&g_ls_mutex); sort_left -= n; - pthread_mutex_unlock(&sort_left_mutex); + if (sort_left == 0 && nthreads > 1) + pthread_cond_broadcast(&g_ls_cond); + pthread_mutex_unlock(&g_ls_mutex); } /* * Do we have something to sort ? + * + * This routine does not need to be locked. */ static inline bool have_sort_left(void) { bool ret; - pthread_mutex_lock(&sort_left_mutex); ret = (sort_left > 0); - pthread_mutex_unlock(&sort_left_mutex); + return (ret); } @@ -144,6 +146,11 @@ push_ls(struct sort_level *sl) new_ls->next = g_ls; g_ls = new_ls; +#if defined(SORT_THREADS) + if (nthreads > 1) + pthread_cond_signal(&g_ls_cond); +#endif + #if defined(SORT_THREADS) if (nthreads > 1) pthread_mutex_unlock(&g_ls_mutex); @@ -184,13 +191,19 @@ pop_ls_mt(void) pthread_mutex_lock(&g_ls_mutex); - if (g_ls) { - sl = g_ls->sl; - saved_ls = g_ls; - g_ls = g_ls->next; - } else { + for (;;) { + if (g_ls) { + sl = g_ls->sl; + saved_ls = g_ls; + g_ls = g_ls->next; + break; + } sl = NULL; saved_ls = NULL; + + if (have_sort_left() == 0) + break; + pthread_cond_wait(&g_ls_cond, &g_ls_mutex); } pthread_mutex_unlock(&g_ls_mutex); @@ -495,13 +508,8 @@ run_sort_cycle_mt(void) for (;;) { slc = pop_ls_mt(); - if (slc == NULL) { - if (have_sort_left()) { - pthread_yield(); - continue; - } + if (slc == NULL) break; - } run_sort_level_next(slc); } } @@ -512,9 +520,7 @@ run_sort_cycle_mt(void) static void* sort_thread(void* arg) { - run_sort_cycle_mt(); - sem_post(&mtsem); return (arg); @@ -610,8 +616,7 @@ run_top_sort_level(struct sort_level *sl) pthread_t pth; pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, - PTHREAD_DETACHED); + pthread_attr_setdetachstate(&attr, PTHREAD_DETACHED); for (;;) { int res = pthread_create(&pth, &attr, @@ -628,7 +633,7 @@ run_top_sort_level(struct sort_level *sl) pthread_attr_destroy(&attr); } - for(i = 0; i < nthreads; ++i) + for (i = 0; i < nthreads; ++i) sem_wait(&mtsem); } #endif /* defined(SORT_THREADS) */ @@ -651,7 +656,7 @@ run_sort(struct sort_list_item **base, size_t nmemb) pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ADAPTIVE_NP); pthread_mutex_init(&g_ls_mutex, &mattr); - pthread_mutex_init(&sort_left_mutex, &mattr); + pthread_cond_init(&g_ls_cond, NULL); pthread_mutexattr_destroy(&mattr); @@ -679,7 +684,6 @@ run_sort(struct sort_list_item **base, size_t nmemb) if (nthreads > 1) { sem_destroy(&mtsem); pthread_mutex_destroy(&g_ls_mutex); - pthread_mutex_destroy(&sort_left_mutex); } nthreads = nthreads_save; #endif -- cgit v1.2.3