summaryrefslogtreecommitdiff
path: root/src/sna/sna_threads.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-02-22 14:34:05 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2014-02-22 16:58:58 +0000
commit64fc1bb9c87e95ff484ecd11f391b1c0d556d584 (patch)
tree588dd8dd1a8ab862ea7e22c596d25d2bdf835490 /src/sna/sna_threads.c
parent900499bff962a63e1d9b5f808d1deb65d55754a2 (diff)
sna: Allow SIGBUS/SEGV to kill the thread
To handle sigtrapping of the threads, we allow the threads to handle their async signals and upon hitting the trap, we kill the thread. All the rest of the threads are reaped by the main xserver thread afterwards. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna/sna_threads.c')
-rw-r--r--src/sna/sna_threads.c81
1 files changed, 48 insertions, 33 deletions
diff --git a/src/sna/sna_threads.c b/src/sna/sna_threads.c
index a15e66a8..eac69640 100644
--- a/src/sna/sna_threads.c
+++ b/src/sna/sna_threads.c
@@ -53,7 +53,9 @@ static void *__run__(void *arg)
/* Disable all signals in the slave threads as X uses them for IO */
sigfillset(&signals);
- pthread_sigmask(SIG_BLOCK, &signals, NULL);
+ sigdelset(&signals, SIGBUS);
+ sigdelset(&signals, SIGSEGV);
+ pthread_sigmask(SIG_SETMASK, &signals, NULL);
pthread_mutex_lock(&t->mutex);
while (1) {
@@ -66,6 +68,7 @@ static void *__run__(void *arg)
pthread_mutex_lock(&t->mutex);
t->func = NULL;
+ t->arg = NULL;
pthread_cond_signal(&t->cond);
}
pthread_mutex_unlock(&t->mutex);
@@ -141,7 +144,7 @@ void sna_threads_init(void)
if (threads == NULL)
goto bail;
- for (n = 0; n < max_threads; n++) {
+ for (n = 1; n < max_threads; n++) {
pthread_mutex_init(&threads[n].mutex, NULL);
pthread_cond_init(&threads[n].cond, NULL);
@@ -151,41 +154,46 @@ void sna_threads_init(void)
goto bail;
}
+ threads[0].thread = pthread_self();
return;
bail:
max_threads = 0;
}
-void sna_threads_run(void (*func)(void *arg), void *arg)
+void sna_threads_run(int id, void (*func)(void *arg), void *arg)
{
- int n;
-
assert(max_threads > 0);
+ assert(pthread_self() == threads[0].thread);
+ assert(id > 0 && id < max_threads);
- for (n = 0; n < max_threads; n++) {
- if (threads[n].func)
- continue;
+ assert(threads[id].func == NULL);
- pthread_mutex_lock(&threads[n].mutex);
- if (threads[n].func) {
- pthread_mutex_unlock(&threads[n].mutex);
- continue;
- }
+ pthread_mutex_lock(&threads[id].mutex);
+ threads[id].func = func;
+ threads[id].arg = arg;
+ pthread_cond_signal(&threads[id].cond);
+ pthread_mutex_unlock(&threads[id].mutex);
+}
- goto execute;
- }
+void sna_threads_trap(int sig)
+{
+ pthread_t t = pthread_self();
+ int n;
- n = rand() % max_threads;
- pthread_mutex_lock(&threads[n].mutex);
- while (threads[n].func)
- pthread_cond_wait(&threads[n].cond, &threads[n].mutex);
+ if (t == threads[0].thread)
+ return;
+
+ for (n = 1; threads[n].thread != t; n++)
+ ;
-execute:
- threads[n].func = func;
- threads[n].arg = arg;
+ pthread_mutex_lock(&threads[n].mutex);
+ threads[n].func = NULL;
+ threads[n].arg = &threads[n];
pthread_cond_signal(&threads[n].cond);
pthread_mutex_unlock(&threads[n].mutex);
+
+ pthread_exit(&sig);
}
void sna_threads_wait(void)
@@ -193,15 +201,21 @@ void sna_threads_wait(void)
int n;
assert(max_threads > 0);
+ assert(pthread_self() == threads[0].thread);
- for (n = 0; n < max_threads; n++) {
- if (threads[n].func == NULL)
- continue;
+ for (n = 1; n < max_threads; n++) {
+ if (threads[n].func != NULL) {
+ pthread_mutex_lock(&threads[n].mutex);
+ while (threads[n].func)
+ pthread_cond_wait(&threads[n].cond, &threads[n].mutex);
+ pthread_mutex_unlock(&threads[n].mutex);
+ }
- pthread_mutex_lock(&threads[n].mutex);
- while (threads[n].func)
- pthread_cond_wait(&threads[n].cond, &threads[n].mutex);
- pthread_mutex_unlock(&threads[n].mutex);
+ if (threads[n].arg != NULL) {
+ ERR(("%s: thread %d died\n", __func__, n));
+ sna_threads_kill();
+ return;
+ }
}
}
@@ -209,13 +223,14 @@ void sna_threads_kill(void)
{
int n;
- ERR(("kill %d threads\n", max_threads));
+ ERR(("%s: kill %d threads\n", __func__, max_threads));
assert(max_threads > 0);
+ assert(pthread_self() == threads[0].thread);
- for (n = 0; n < max_threads; n++)
+ for (n = 1; n < max_threads; n++)
pthread_cancel(threads[n].thread);
- for (n = 0; n < max_threads; n++)
+ for (n = 1; n < max_threads; n++)
pthread_join(threads[n].thread, NULL);
max_threads = 0;
@@ -316,7 +331,7 @@ void sna_image_composite(pixman_op_t op,
data[n].dst_y = y;
y += dy;
- sna_threads_run(thread_composite, &data[n]);
+ sna_threads_run(n, thread_composite, &data[n]);
}
assert(y < dst_y + height);