From: Mauro Carvalho Chehab <mchehab@redhat.com>
Date: Wed, 27 Feb 2013 08:01:42 +0000 (-0300)
Subject: edactool: add one thread per CPU
X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;p=users%2Fmchehab%2Fedactool.git

edactool: add one thread per CPU

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---

diff --git a/Makefile b/Makefile
index 9c70cca..fc931bd 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,8 @@
-CC=gcc
-CFLAGS = -Wall
-FILES = edactool
-TRACE_LIB = event-parse.o kbuffer-parse.o  parse-filter.o  parse-utils.o  trace-seq.o
+CC		= gcc
+CFLAGS		= -Wall
+LDFLAGS		= -lpthread
+FILES		= edactool
+TRACE_LIB	= event-parse.o kbuffer-parse.o  parse-filter.o  parse-utils.o  trace-seq.o
 
 default: $(FILES)
 
diff --git a/edactool.c b/edactool.c
index 48671c3..72ee092 100644
--- a/edactool.c
+++ b/edactool.c
@@ -25,6 +25,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <pthread.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -309,50 +310,63 @@ static int get_num_cpus(void)
 	return num_cpus;
 }
 
-static int handle_ras_events_cpu(struct pevent *pevent, int cpu, int page_size)
+struct pthread_data {
+	pthread_t	thread;
+	struct pevent	*pevent;
+	int		cpu;
+	int		page_size;
+};
+
+static void *handle_ras_events_cpu(void *priv)
 {
-	int rc, fd;
+	int fd;
 	struct kbuffer *kbuf;
 	void *page;
+	char pipe_raw[PATH_MAX];
+	struct pthread_data *data = priv;
 
-	page = malloc(page_size);
+	page = malloc(data->page_size);
 	if (!page) {
 		perror("Can't allocate page");
-		return errno;
+		return NULL;
 	}
-printf("Endian: %d\n", ENDIAN);
+
 	kbuf = kbuffer_alloc(KBUFFER_LSIZE_8, ENDIAN);
 	if (!kbuf) {
 		perror("Can't allocate kbuf");
 		free(page);
-		return errno;
+		return NULL;
 	}
 
-	printf("Number of CPUs: %d. For now, opening just cpu0\n",
-	       get_num_cpus());
-
 	/* FIXME: use select to open for all CPUs */
-	fd = open(DEBUGFS "tracing/per_cpu/cpu0/trace_pipe_raw",
-		  O_RDONLY);
+	snprintf(pipe_raw, sizeof(pipe_raw),
+		 DEBUGFS "tracing/per_cpu/cpu%d/trace_pipe_raw",
+		 data->cpu);
+
+	fd = open(pipe_raw, O_RDONLY);
 	if (fd < 0) {
 		perror("Can't open trace_pipe_raw");
 		kbuffer_free(kbuf);
 		free(page);
-		return errno;
+		return NULL;
 	}
 
-	rc = read_ras_event(fd, pevent, kbuf, page, page_size);
+	printf("Listening to events on cpu %d\n", data->cpu);
+
+	read_ras_event(fd, data->pevent, kbuf, page, data->page_size);
 
 	close(fd);
 	kbuffer_free(kbuf);
 	free(page);
-	return rc;
+
+	return NULL;
 }
 
 static int handle_ras_events(void)
 {
-	int rc, fd, size, page_size;
+	int rc, fd, size, page_size, i, cpus;
 	struct pevent *pevent;
+	struct pthread_data *data;
 	void *page;
 
 	/* Enable RAS events */
@@ -398,8 +412,33 @@ static int handle_ras_events(void)
 	if (rc)
 		goto free_pevent;
 
-	/* FIXME: start one thread per CPU */
-	rc = handle_ras_events_cpu(pevent, 0, page_size);
+	cpus = get_num_cpus();
+	data = calloc(sizeof(*data), cpus);
+	if (!data)
+		goto free_pevent;
+
+	printf("Opening one thread per cpu (%d threads)\n", cpus);
+	for (i = 0; i < cpus; i++) {
+		data[i].pevent = pevent;
+		data[i].cpu = i;
+		data[i].page_size = page_size;
+
+		rc = pthread_create(&data[i].thread, NULL,
+				    handle_ras_events_cpu,
+				    (void *)&data[i]);
+		if (rc) {
+			while (--i)
+				pthread_cancel(data[i].thread);
+			goto free_threads;
+		}
+	}
+
+	/* Wait for all threads to complete */
+	for (i = 0; i < cpus; i++)
+		pthread_join(data[i].thread, NULL);
+
+free_threads:
+	free(data);
 
 free_pevent:
 	pevent_free(pevent);