This function takes a callback which is called in a separate thread for every CPU core you have, to spread a parallel workload over the available cores. --- lib/libalpm/util.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/libalpm/util.h | 3 ++ 2 files changed, 56 insertions(+), 0 deletions(-) diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 458f750..4e5cf85 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -39,6 +39,7 @@ #include <sys/stat.h> #include <sys/wait.h> #include <locale.h> /* setlocale */ +#include <pthread.h> /* libarchive */ #include <archive.h> @@ -938,6 +939,58 @@ long _alpm_parsedate(const char *line) return(atol(line)); } +typedef struct { + _alpm_for_each_cpu_callback callback; + void *ptr; + int thread, numcpus; + int ret; +} _alpm_thread_payload; + +static void *_alpm_thread_callback(void *ptr) +{ + _alpm_thread_payload *payload = ptr; + payload->ret = payload->callback(payload->ptr, payload->thread, payload->numcpus); + return NULL; +} + +static int _alpm_numcpus() +{ +#ifdef _SC_NPROCESSORS_ONLN + long numcpus = sysconf(_SC_NPROCESSORS_ONLN); + if(numcpus >= 1) { + return numcpus; + } +#endif + + return 1; +} + +int _alpm_for_each_cpu(_alpm_for_each_cpu_callback callback, void *ptr) +{ + int numcpus = _alpm_numcpus(); + + pthread_t threads[numcpus]; + _alpm_thread_payload payloads[numcpus]; + for(int i = 0; i < numcpus; i++) { + payloads[i].callback = callback; + payloads[i].ptr = ptr; + payloads[i].thread = i; + payloads[i].numcpus = numcpus; + + pthread_create(&threads[i], NULL, _alpm_thread_callback, &payloads[i]); + } + + int ret = 0; + for(int i = 0; i < numcpus; i++) { + pthread_join(threads[i], NULL); + if(payloads[i].ret != 0) { + ret = payloads[i].ret; + } + } + + return ret; +} + #ifndef HAVE_STRNDUP /* A quick and dirty implementation derived from glibc */ static size_t strnlen(const char *s, size_t max) diff --git a/lib/libalpm/util.h b/lib/libalpm/util.h index 015e9bf..72cd5d7 100644 --- a/lib/libalpm/util.h +++ b/lib/libalpm/util.h @@ -98,6 +98,9 @@ int _alpm_splitname(const char *target, pmpkg_t *pkg); unsigned long _alpm_hash_sdbm(const char *str); long _alpm_parsedate(const char *line); +typedef int (*_alpm_for_each_cpu_callback)(void *ptr, int thread, int numcpus); +int _alpm_for_each_cpu(_alpm_for_each_cpu_callback callback, void *ptr); + #ifndef HAVE_STRSEP char *strsep(char **, const char *); #endif -- 1.7.4.1