void sna_threads_init(void);
int sna_use_threads (int width, int height, int threshold);
-void sna_threads_run(void (*func)(void *arg), void *arg);
+void sna_threads_run(int id, void (*func)(void *arg), void *arg);
+void sna_threads_trap(int sig);
void sna_threads_wait(void);
void sna_threads_kill(void);
static int sigtrap_handler(int sig)
{
- if (sigtrap) {
- /* XXX rate-limited squawk? */
+ /* XXX rate-limited squawk? */
+ DBG(("%s(sig=%d) sigtrap=%d\n", __FUNCTION__, sig, sigtrap));
+ sna_threads_trap(sig);
+
+ if (sigtrap)
siglongjmp(sigjmp[--sigtrap], sig);
- }
return -1;
}
/* 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) {
pthread_mutex_lock(&t->mutex);
t->func = NULL;
+ t->arg = NULL;
pthread_cond_signal(&t->cond);
}
pthread_mutex_unlock(&t->mutex);
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);
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)
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;
+ }
}
}
{
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;
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);
dy = (height + num_threads - 1) / num_threads;
num_threads -= (num_threads-1) * dy >= bounds.y2 - bounds.y1;
- for (n = 1; n < num_threads; n++) {
- threads[n] = threads[0];
- threads[n].ptr += (y - bounds.y1) * threads[n].stride;
- threads[n].bounds.y1 = y;
- threads[n].bounds.y2 = y += dy;
-
- sna_threads_run(rasterize_traps_thread, &threads[n]);
- }
+ if (sigtrap_get() == 0) {
+ for (n = 1; n < num_threads; n++) {
+ threads[n] = threads[0];
+ threads[n].ptr += (y - bounds.y1) * threads[n].stride;
+ threads[n].bounds.y1 = y;
+ threads[n].bounds.y2 = y += dy;
+
+ sna_threads_run(n, rasterize_traps_thread, &threads[n]);
+ }
- assert(y < threads[0].bounds.y2);
- threads[0].ptr += (y - bounds.y1) * threads[0].stride;
- threads[0].bounds.y1 = y;
- rasterize_traps_thread(&threads[0]);
+ assert(y < threads[0].bounds.y2);
+ threads[0].ptr += (y - bounds.y1) * threads[0].stride;
+ threads[0].bounds.y1 = y;
+ rasterize_traps_thread(&threads[0]);
- sna_threads_wait();
+ sna_threads_wait();
+ sigtrap_put();
+ } else
+ sna_threads_kill();
format = PIXMAN_a8;
depth = 8;
thread[i] = thread[0];
thread[i].y1 = y;
thread[i].y2 = y += dy;
- sna_threads_run(rectilinear_inplace_thread, &thread[i]);
+ sna_threads_run(i, rectilinear_inplace_thread, &thread[i]);
}
assert(y < clip.extents.y2);
threads[n].extents.y1 = y;
threads[n].extents.y2 = y += h;
- sna_threads_run(span_thread, &threads[n]);
+ sna_threads_run(n, span_thread, &threads[n]);
}
assert(y < threads[0].extents.y2);
threads[n].extents.y1 = y;
threads[n].extents.y2 = y += h;
- sna_threads_run(inplace_x8r8g8b8_thread, &threads[n]);
+ sna_threads_run(n, inplace_x8r8g8b8_thread, &threads[n]);
}
assert(y < threads[0].extents.y2);
threads[n].extents.y1 = y;
threads[n].extents.y2 = y += h;
- sna_threads_run(inplace_thread, &threads[n]);
+ sna_threads_run(n, inplace_thread, &threads[n]);
}
assert(y < threads[0].extents.y2);
threads[n].extents.y1 = y;
threads[n].extents.y2 = y += h;
- sna_threads_run(mono_span_thread, &threads[n]);
+ sna_threads_run(n, mono_span_thread, &threads[n]);
}
threads[0].extents.y1 = y;
threads[n].extents.y1 = y;
threads[n].extents.y2 = y += h;
- sna_threads_run(span_thread, &threads[n]);
+ sna_threads_run(n, span_thread, &threads[n]);
}
assert(y < threads[0].extents.y2);
threads[n].extents.y1 = y;
threads[n].extents.y2 = y += h;
- sna_threads_run(mask_thread, &threads[n]);
+ sna_threads_run(n, mask_thread, &threads[n]);
}
assert(y < threads[0].extents.y2);
threads[n].extents.y1 = y;
threads[n].extents.y2 = y += h;
- sna_threads_run(inplace_x8r8g8b8_thread, &threads[n]);
+ sna_threads_run(n, inplace_x8r8g8b8_thread, &threads[n]);
}
assert(y < threads[0].extents.y2);
threads[n].extents.y1 = y;
threads[n].extents.y2 = y += h;
- sna_threads_run(inplace_thread, &threads[n]);
+ sna_threads_run(n, inplace_thread, &threads[n]);
}
assert(y < threads[0].extents.y2);
threads[n].extents.y1 = y;
threads[n].extents.y2 = y += h;
- sna_threads_run(mask_thread, &threads[n]);
+ sna_threads_run(n, mask_thread, &threads[n]);
}
assert(y < threads[0].extents.y2);