[pacman-dev] [PATCH 1/2] Add _alpm_for_each_cpu() internal API.

Tavian Barnes tavianator at gmail.com
Mon Feb 21 17:38:34 EST 2011


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



More information about the pacman-dev mailing list