summaryrefslogtreecommitdiff
path: root/source/tools/mudraw.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2016-11-21 14:23:45 +0000
committerRobin Watts <robin.watts@artifex.com>2016-11-23 10:01:25 +0000
commitcb44c9ae591ae5cdfda932f04bf321932a0e1d0f (patch)
tree4fe8f3d70d6f951ee8cd50c96bc4dc732179a7f0 /source/tools/mudraw.c
parent30afe6fa458cef7a6f84020de5bd15d8ae164521 (diff)
downloadmupdf-cb44c9ae591ae5cdfda932f04bf321932a0e1d0f.tar.xz
Convert mudraw and muraster to use mu-threads.
Saves having the same threading code repeatedly.
Diffstat (limited to 'source/tools/mudraw.c')
-rw-r--r--source/tools/mudraw.c283
1 files changed, 83 insertions, 200 deletions
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index 0b091fee..20122563 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -5,18 +5,7 @@
#include "mupdf/fitz.h"
#include "mupdf/pdf.h" /* for pdf output */
-#ifdef _MSC_VER
-#include <winsock2.h>
-#include <windows.h>
-#define MUDRAW_THREADS 1
-#else
-#include <sys/time.h>
-#ifdef HAVE_PTHREADS
-#define MUDRAW_THREADS 2
-#include <pthread.h>
-#include <semaphore.h>
-#endif
-#endif
+#include "mupdf/helpers/mu-threads.h"
/* Enable for helpful threading debug */
/* #define DEBUG_THREADS(A) do { printf A; fflush(stdout); } while (0) */
@@ -131,144 +120,18 @@ static const format_cs_table_t format_cs_table[] =
a multi-threaded option. In the absence, of such, we degrade
nicely.
*/
-#ifdef MUDRAW_THREADS
-#if MUDRAW_THREADS == 1
-
-/* Windows threads */
-#define SEMAPHORE HANDLE
-#define SEMAPHORE_INIT(A) do { A = CreateSemaphore(NULL, 0, 1, NULL); } while (0)
-#define SEMAPHORE_FIN(A) do { CloseHandle(A); } while (0)
-#define SEMAPHORE_TRIGGER(A) do { (void)ReleaseSemaphore(A, 1, NULL); } while (0)
-#define SEMAPHORE_WAIT(A) do { (void)WaitForSingleObject(A, INFINITE); } while (0)
-#define THREAD HANDLE
-#define THREAD_INIT(A,B,C) do { A = CreateThread(NULL, 0, B, C, 0, NULL); } while (0)
-#define THREAD_FIN(A) do { CloseHandle(A); } while (0)
-#define THREAD_RETURN_TYPE DWORD WINAPI
-#define THREAD_RETURN() return 0
-#define MUTEX CRITICAL_SECTION
-#define MUTEX_INIT(A) do { InitializeCriticalSection(&A); } while (0)
-#define MUTEX_FIN(A) do { DeleteCriticalSection(&A); } while (0)
-#define MUTEX_LOCK(A) do { EnterCriticalSection(&A); } while (0)
-#define MUTEX_UNLOCK(A) do { LeaveCriticalSection(&A); } while (0)
-
-#elif MUDRAW_THREADS == 2
-
-/*
- PThreads - without working unnamed semaphores.
-
- Neither ios nor OSX supports unnamed semaphores.
- Named semaphores are a pain to use, so we implement
- our own semaphores using condition variables and
- mutexes.
-*/
+#ifndef DISABLE_MUTHREADS
-typedef struct
-{
- int count;
- pthread_mutex_t mutex;
- pthread_cond_t cond;
-} my_semaphore_t;
-
-int
-my_semaphore_open(my_semaphore_t *sem)
-{
- int scode;
-
- sem->count = 0;
- scode = pthread_mutex_init(&sem->mutex, NULL);
- if (scode == 0)
- {
- scode = pthread_cond_init(&sem->cond, NULL);
- if (scode)
- pthread_mutex_destroy(&sem->mutex);
- }
- if (scode)
- memset(sem, 0, sizeof(*sem));
- return scode;
-}
-
-int
-my_semaphore_close(my_semaphore_t *sem)
-{
- int scode, scode2;
-
- scode = pthread_cond_destroy(&sem->cond);
- scode2 = pthread_mutex_destroy(&sem->mutex);
- if (scode == 0)
- scode = scode2;
- return scode;
-}
-
-int
-my_semaphore_wait(my_semaphore_t *sem)
-{
- int scode, scode2;
-
- scode = pthread_mutex_lock(&sem->mutex);
- if (scode)
- return scode;
- while (sem->count == 0) {
- scode = pthread_cond_wait(&sem->cond, &sem->mutex);
- if (scode)
- break;
- }
- if (scode == 0)
- --sem->count;
- scode2 = pthread_mutex_unlock(&sem->mutex);
- if (scode == 0)
- scode = scode2;
- return scode;
-}
-
-int
-my_semaphore_signal(my_semaphore_t * sem)
-{
- int scode, scode2;
-
- scode = pthread_mutex_lock(&sem->mutex);
- if (scode)
- return scode;
- if (sem->count++ == 0)
- scode = pthread_cond_signal(&sem->cond);
- scode2 = pthread_mutex_unlock(&sem->mutex);
- if (scode == 0)
- scode = scode2;
- return scode;
-}
-
-#define SEMAPHORE my_semaphore_t
-#define SEMAPHORE_INIT(A) do { (void)my_semaphore_open(&A); } while (0)
-#define SEMAPHORE_FIN(A) do { (void)my_semaphore_close(&A); } while (0)
-#define SEMAPHORE_TRIGGER(A) do { (void)my_semaphore_signal(&A); } while (0)
-#define SEMAPHORE_WAIT(A) do { (void)my_semaphore_wait(&A); } while (0)
-#define THREAD pthread_t
-#define THREAD_INIT(A,B,C) do { (void)pthread_create(&A, NULL, B, C); } while (0)
-#define THREAD_FIN(A) do { void *res; (void)pthread_join(A, &res); } while (0)
-#define THREAD_RETURN_TYPE void *
-#define THREAD_RETURN() return NULL
-#define MUTEX pthread_mutex_t
-#define MUTEX_INIT(A) do { (void)pthread_mutex_init(&A, NULL); } while (0)
-#define MUTEX_FIN(A) do { (void)pthread_mutex_destroy(&A); } while (0)
-#define MUTEX_LOCK(A) do { (void)pthread_mutex_lock(&A); } while (0)
-#define MUTEX_UNLOCK(A) do { (void)pthread_mutex_unlock(&A); } while (0)
-
-#else
-#error Unknown MUDRAW_THREADS setting
-#endif
-
-#define LOCKS_INIT() init_mudraw_locks()
-#define LOCKS_FIN() fin_mudraw_locks()
-
-static MUTEX mutexes[FZ_LOCK_MAX];
+static mu_mutex mutexes[FZ_LOCK_MAX];
static void mudraw_lock(void *user, int lock)
{
- MUTEX_LOCK(mutexes[lock]);
+ mu_lock_mutex(&mutexes[lock]);
}
static void mudraw_unlock(void *user, int lock)
{
- MUTEX_UNLOCK(mutexes[lock]);
+ mu_unlock_mutex(&mutexes[lock]);
}
static fz_locks_context mudraw_locks =
@@ -276,37 +139,30 @@ static fz_locks_context mudraw_locks =
NULL, mudraw_lock, mudraw_unlock
};
-static fz_locks_context *init_mudraw_locks(void)
+static void fin_mudraw_locks(void)
{
int i;
for (i = 0; i < FZ_LOCK_MAX; i++)
- MUTEX_INIT(mutexes[i]);
-
- return &mudraw_locks;
+ mu_destroy_mutex(&mutexes[i]);
}
-static void fin_mudraw_locks(void)
+static fz_locks_context *init_mudraw_locks(void)
{
int i;
+ int failed = 0;
for (i = 0; i < FZ_LOCK_MAX; i++)
- MUTEX_FIN(mutexes[i]);
-}
+ failed |= mu_create_mutex(&mutexes[i]);
-#else
+ if (failed)
+ {
+ fin_mudraw_locks();
+ return NULL;
+ }
-/* Null Threads implementation */
-#define SEMAPHORE int
-#define THREAD int
-#define SEMAPHORE_INIT(A) do { A = 0; } while (0)
-#define SEMAPHORE_FIN(A) do { A = 0; } while (0)
-#define SEMAPHORE_TRIGGER(A) do { A = 0; } while (0)
-#define SEMAPHORE_WAIT(A) do { A = 0; } while (0)
-#define THREAD_INIT(A,B,C) do { A = 0; (void)C; } while (0)
-#define THREAD_FIN(A) do { A = 0; } while (0)
-#define LOCKS_INIT() NULL
-#define LOCKS_FIN() do { } while (0)
+ return &mudraw_locks;
+}
#endif
@@ -320,9 +176,9 @@ typedef struct worker_t {
fz_pixmap *pix;
fz_bitmap *bit;
fz_cookie cookie;
- SEMAPHORE start;
- SEMAPHORE stop;
- THREAD thread;
+ mu_semaphore start;
+ mu_semaphore stop;
+ mu_thread thread;
} worker_t;
static char *output = NULL;
@@ -385,9 +241,9 @@ static struct {
int active;
int started;
fz_context *ctx;
- THREAD thread;
- SEMAPHORE start;
- SEMAPHORE stop;
+ mu_thread thread;
+ mu_semaphore start;
+ mu_semaphore stop;
int pagenum;
char *filename;
fz_display_list *list;
@@ -865,7 +721,7 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
workers[band].pix = fz_new_pixmap_with_bbox(ctx, colorspace, &band_ibounds, alpha);
fz_set_pixmap_resolution(ctx, workers[band].pix, resolution, resolution);
DEBUG_THREADS(("Worker %d, Pre-triggering band %d\n", band, band));
- SEMAPHORE_TRIGGER(workers[band].start);
+ mu_trigger_semaphore(&workers[band].start);
ctm.f -= drawheight;
}
pix = workers[0].pix;
@@ -908,7 +764,7 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
{
worker_t *w = &workers[band % num_workers];
DEBUG_THREADS(("Waiting for worker %d to complete band %d\n", w->num, band));
- SEMAPHORE_WAIT(w->stop);
+ mu_wait_semaphore(&w->stop);
pix = w->pix;
bit = w->bit;
w->bit = NULL;
@@ -937,7 +793,7 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
w->tbounds = tbounds;
memset(&w->cookie, 0, sizeof(fz_cookie));
DEBUG_THREADS(("Triggering worker %d for band %d\n", w->num, w->band));
- SEMAPHORE_TRIGGER(w->start);
+ mu_trigger_semaphore(&w->start);
}
ctm.f -= drawheight;
}
@@ -1059,7 +915,7 @@ static void bgprint_flush(void)
if (!bgprint.active || !bgprint.started)
return;
- SEMAPHORE_WAIT(bgprint.stop);
+ mu_wait_semaphore(&bgprint.stop);
bgprint.started = 0;
}
@@ -1165,7 +1021,7 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
bgprint.filename = filename;
bgprint.pagenum = pagenum;
bgprint.interptime = start;
- SEMAPHORE_TRIGGER(bgprint.start);
+ mu_trigger_semaphore(&bgprint.start);
}
else
{
@@ -1267,26 +1123,25 @@ trace_realloc(void *arg, void *p_, size_t size)
return &p[1];
}
-#ifdef MUDRAW_THREADS
-static THREAD_RETURN_TYPE worker_thread(void *arg)
+#ifndef DISABLE_MUTHREADS
+static void worker_thread(void *arg)
{
worker_t *me = (worker_t *)arg;
do
{
DEBUG_THREADS(("Worker %d waiting\n", me->num));
- SEMAPHORE_WAIT(me->start);
+ mu_wait_semaphore(&me->start);
DEBUG_THREADS(("Worker %d woken for band %d\n", me->num, me->band));
if (me->band >= 0)
drawband(me->ctx, NULL, me->list, &me->ctm, &me->tbounds, &me->cookie, me->band * band_height, me->pix, &me->bit);
DEBUG_THREADS(("Worker %d completed band %d\n", me->num, me->band));
- SEMAPHORE_TRIGGER(me->stop);
+ mu_trigger_semaphore(&me->stop);
}
while (me->band >= 0);
- THREAD_RETURN();
}
-static THREAD_RETURN_TYPE bgprint_worker(void *arg)
+static void bgprint_worker(void *arg)
{
fz_cookie cookie = { 0 };
int pagenum;
@@ -1296,7 +1151,7 @@ static THREAD_RETURN_TYPE bgprint_worker(void *arg)
do
{
DEBUG_THREADS(("BGPrint waiting\n"));
- SEMAPHORE_WAIT(bgprint.start);
+ mu_wait_semaphore(&bgprint.start);
pagenum = bgprint.pagenum;
DEBUG_THREADS(("BGPrint woken for pagenum %d\n", pagenum));
if (pagenum >= 0)
@@ -1306,10 +1161,9 @@ static THREAD_RETURN_TYPE bgprint_worker(void *arg)
dodrawpage(bgprint.ctx, bgprint.page, bgprint.list, pagenum, &cookie, start, bgprint.interptime, bgprint.filename, 1);
}
DEBUG_THREADS(("BGPrint completed page %d\n", pagenum));
- SEMAPHORE_TRIGGER(bgprint.stop);
+ mu_trigger_semaphore(&bgprint.stop);
}
while (pagenum >= 0);
- THREAD_RETURN();
}
#endif
@@ -1426,6 +1280,7 @@ int mudraw_main(int argc, char **argv)
int c, i;
fz_context *ctx;
fz_alloc_context alloc_ctx = { NULL, trace_malloc, trace_realloc, trace_free };
+ fz_locks_context *locks = NULL;
fz_var(doc);
@@ -1479,7 +1334,7 @@ int mudraw_main(int argc, char **argv)
case 'i': ignore_errors = 1; break;
case 'T':
-#ifdef MUDRAW_THREADS
+#ifndef DISABLE_MUTHREADS
num_workers = atoi(fz_optarg); break;
#else
fprintf(stderr, "Threads not enabled in this build\n");
@@ -1520,7 +1375,16 @@ int mudraw_main(int argc, char **argv)
}
}
- ctx = fz_new_context((showmemory == 0 ? NULL : &alloc_ctx), LOCKS_INIT(), (lowmemory ? 1 : FZ_STORE_DEFAULT));
+#ifndef DISABLE_MUTHREADS
+ locks = init_mudraw_locks();
+ if (locks == NULL)
+ {
+ fprintf(stderr, "mutex initialisation failed\n");
+ exit(1);
+ }
+#endif
+
+ ctx = fz_new_context((showmemory == 0 ? NULL : &alloc_ctx), locks, (lowmemory ? 1 : FZ_STORE_DEFAULT));
if (!ctx)
{
fprintf(stderr, "cannot initialise context\n");
@@ -1531,26 +1395,40 @@ int mudraw_main(int argc, char **argv)
fz_set_graphics_aa_level(ctx, alphabits_graphics);
fz_set_graphics_min_line_width(ctx, min_line_width);
+#ifndef DISABLE_MUTHREADS
if (bgprint.active)
{
+ int fail = 0;
bgprint.ctx = fz_clone_context(ctx);
- SEMAPHORE_INIT(bgprint.start);
- SEMAPHORE_INIT(bgprint.stop);
- THREAD_INIT(bgprint.thread, bgprint_worker, NULL);
+ fail |= mu_create_semaphore(&bgprint.start);
+ fail |= mu_create_semaphore(&bgprint.stop);
+ fail |= mu_create_thread(&bgprint.thread, bgprint_worker, NULL);
+ if (fail)
+ {
+ fprintf(stderr, "bgprint startup failed\n");
+ exit(1);
+ }
}
if (num_workers > 0)
{
+ int fail = 0;
workers = fz_calloc(ctx, num_workers, sizeof(*workers));
for (i = 0; i < num_workers; i++)
{
workers[i].ctx = fz_clone_context(ctx);
workers[i].num = i;
- SEMAPHORE_INIT(workers[i].start);
- SEMAPHORE_INIT(workers[i].stop);
- THREAD_INIT(workers[i].thread, worker_thread, &workers[i]);
+ fail |= mu_create_semaphore(&workers[i].start);
+ fail |= mu_create_semaphore(&workers[i].stop);
+ fail |= mu_create_thread(&workers[i].thread, worker_thread, &workers[i]);
+ }
+ if (fail)
+ {
+ fprintf(stderr, "worker startup failed\n");
+ exit(1);
}
}
+#endif /* DISABLE_MUTHREADS */
if (layout_css)
{
@@ -1813,16 +1691,17 @@ int mudraw_main(int argc, char **argv)
}
}
+#ifndef DISABLE_MUTHREADS
if (num_workers > 0)
{
for (i = 0; i < num_workers; i++)
{
workers[i].band = -1;
- SEMAPHORE_TRIGGER(workers[i].start);
- SEMAPHORE_WAIT(workers[i].stop);
- SEMAPHORE_FIN(workers[i].start);
- SEMAPHORE_FIN(workers[i].stop);
- THREAD_FIN(workers[i].thread);
+ mu_trigger_semaphore(&workers[i].start);
+ mu_wait_semaphore(&workers[i].stop);
+ mu_destroy_semaphore(&workers[i].start);
+ mu_destroy_semaphore(&workers[i].stop);
+ mu_destroy_thread(&workers[i].thread);
fz_drop_context(workers[i].ctx);
}
fz_free(ctx, workers);
@@ -1831,16 +1710,20 @@ int mudraw_main(int argc, char **argv)
if (bgprint.active)
{
bgprint.pagenum = -1;
- SEMAPHORE_TRIGGER(bgprint.start);
- SEMAPHORE_WAIT(bgprint.stop);
- SEMAPHORE_FIN(bgprint.start);
- SEMAPHORE_FIN(bgprint.stop);
- THREAD_FIN(bgprint.thread);
+ mu_trigger_semaphore(&bgprint.start);
+ mu_wait_semaphore(&bgprint.stop);
+ mu_destroy_semaphore(&bgprint.start);
+ mu_destroy_semaphore(&bgprint.stop);
+ mu_destroy_thread(&bgprint.thread);
fz_drop_context(bgprint.ctx);
}
+#endif /* DISABLE_MUTHREADS */
fz_drop_context(ctx);
- LOCKS_FIN();
+
+#ifndef DISABLE_MUTHREADS
+ fin_mudraw_locks();
+#endif /* DISABLE_MUTHREADS */
if (showmemory)
{