diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/tools/mudraw.c | 283 | ||||
-rw-r--r-- | source/tools/muraster.c | 364 |
2 files changed, 182 insertions, 465 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) { diff --git a/source/tools/muraster.c b/source/tools/muraster.c index a22ee0a8..d65074d5 100644 --- a/source/tools/muraster.c +++ b/source/tools/muraster.c @@ -16,6 +16,17 @@ /* CONFIGURATION SECTION + The first bit of configuration for this is actually in + how the muthreads helper library is built. If muthreads + does not know how to support threading on your system + then it will ensure that DISABLE_MUTHREADS is set. All + the muthreads entrypoints/types will still be defined + (as dummy types/functions), but attempting to use them + will return errors. + + Configuration options affecting threading should be + turned off if DISABLE_MUTHREADS is set. + Integrators can/should define the following MURASTER_CONFIG_ values. If not set, we'll attempt to set sensible defaults. @@ -122,32 +133,11 @@ /* #define MURASTER_CONFIG_GREY_FALLBACK 1 */ /* - MURASTER_CONFIG_THREAD_SYSTEM: - - 0 for no threading available. - - 1 for Windows (or leave undefined to autodetect) - - 2 for PThreads (or leave undefined and use HAVE_PTHREADS) - - 3 (or higher) for custom threading options. - Add your implementations further down the - file. -*/ -/* #undef MURASTER_CONFIG_THREAD_SYSTEM */ - -/* END OF CONFIGURATION SECTION */ #include "mupdf/fitz.h" - -#ifdef _MSC_VER -#include <winsock2.h> -#include <windows.h> -#else -#include <sys/time.h> -#endif +#include "mupdf/helpers/mu-threads.h" /* After this point, we convert the #defines set (or not set) @@ -155,21 +145,6 @@ these for configuration. */ -/* Detect threading */ -#ifdef MURASTER_CONFIG_THREAD_SYSTEM -#define MURASTER_THREADS MURASTER_CONFIG_THREAD_SYSTEM -#else -#ifdef _MSC_VER -#define MURASTER_THREADS 1 -#else -#ifdef HAVE_PTHREADS -#define MURASTER_THREADS 2 -#include <pthread.h> -#include <semaphore.h> -#endif -#endif -#endif - #ifdef MURASTER_CONFIG_X_RESOLUTION #define X_RESOLUTION MURASTER_CONFIG_X_RESOLUTION #else @@ -278,171 +253,16 @@ static const suffix_t suffix_table[] = #endif }; -/* - In the presence of pthreads or Windows threads, we can offer - a multi-threaded option. In the absence, of such, we degrade - nicely. -*/ -#ifdef MURASTER_THREADS -#if MURASTER_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 MURASTER_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 sempahores using condition variables and - mutexes. -*/ - -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) - -// ADD OTHER THREADING IMPLEMENTATIONS HERE. -// See the above implementations for what the different -// arguments mean. -// -//#elif MURASTER_THREADS == 3 -// -//#define SEMAPHORE /* type for a semaphore */ -//#define SEMAPHORE_INIT(A) /* init a semaphore */ -//#define SEMAPHORE_FIN(A) /* finalise a semaphore */ -//#define SEMAPHORE_TRIGGER(A) /* trigger a semaphore */ -//#define SEMAPHORE_WAIT(A) /* wait for a semaphore */ -//#define THREAD /* type for a thread */ -//#define THREAD_INIT(A,B,C) /* initialise a new thread */ -//#define THREAD_FIN(A) /* finalise a thread */ -//#define THREAD_RETURN_TYPE /* return type for the thread */ -//#define THREAD_RETURN() /* command to return from a thread */ -//#define MUTEX /* type for a mutex */ -//#define MUTEX_INIT(A) /* initialise a mutex */ -//#define MUTEX_FIN(A) /* finalise a mutex */ -//#define MUTEX_LOCK(A) /* lock a mutex */ -//#define MUTEX_UNLOCK(A) /* unlock a mutex */ - -#else -#error Unknown MURASTER_THREADS setting -#endif - -#define LOCKS_INIT() init_muraster_locks() -#define LOCKS_FIN() fin_muraster_locks() - -static MUTEX mutexes[FZ_LOCK_MAX]; +static mu_mutex mutexes[FZ_LOCK_MAX]; static void muraster_lock(void *user, int lock) { - MUTEX_LOCK(mutexes[lock]); + mu_lock_mutex(&mutexes[lock]); } static void muraster_unlock(void *user, int lock) { - MUTEX_UNLOCK(mutexes[lock]); + mu_unlock_mutex(&mutexes[lock]); } static fz_locks_context muraster_locks = @@ -450,52 +270,40 @@ static fz_locks_context muraster_locks = NULL, muraster_lock, muraster_unlock }; -static fz_locks_context *init_muraster_locks(void) +static void fin_muraster_locks(void) { int i; for (i = 0; i < FZ_LOCK_MAX; i++) - MUTEX_INIT(mutexes[i]); - - return &muraster_locks; + mu_destroy_mutex(&mutexes[i]); } -static void fin_muraster_locks(void) +static fz_locks_context *init_muraster_locks(void) { int i; + int failed = 0; for (i = 0; i < FZ_LOCK_MAX; i++) - MUTEX_FIN(mutexes[i]); -} - -#else + failed |= mu_create_mutex(&mutexes[i]); -/* 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) - -#undef MURASTER_THREADS -#define MURASTER_THREADS 0 + if (failed) + { + fin_muraster_locks(); + return NULL; + } -#endif + return &muraster_locks; +} #ifdef MURASTER_CONFIG_RENDER_THREADS #define NUM_RENDER_THREADS MURASTER_CONFIG_RENDER_THREADS -#elif MURASTER_THREADS == 0 +#elif defined(DISABLE_MUTHREADS) #define NUM_RENDER_THREADS 0 #else #define NUM_RENDER_THREADS 3 #endif -#if MURASTER_THREADS == 0 && NUM_RENDER_THREADS != 0 +#if defined(DISABLE_MUTHREADS) && NUM_RENDER_THREADS != 0 #error "Can't have MURASTER_CONFIG_RENDER_THREADS > 0 without having a threading library!" #endif @@ -507,7 +315,7 @@ static void fin_muraster_locks(void) #define BGPRINT 1 #endif -#if MURASTER_THREADS == 0 && BGPRINT != 0 +#if defined(DISABLE_MUTHREADS) && BGPRINT != 0 #error "Can't have MURASTER_CONFIG_BGPRINT > 0 without having a threading library!" #endif @@ -523,9 +331,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; @@ -625,9 +433,9 @@ static struct { int solo; int status; fz_context *ctx; - THREAD thread; - SEMAPHORE start; - SEMAPHORE stop; + mu_thread thread; + mu_semaphore start; + mu_semaphore stop; int pagenum; char *filename; render_details render; @@ -668,7 +476,7 @@ static void usage(void) "\t-f\tfit file to page if too large\n" "\t-B -\tminimum band height (e.g. 32)\n" "\t-M -\tmax bandmemory (e.g. 655360)\n" -#if MURASTER_THREADS != 0 +#ifndef DISABLE_MUTHREADS "\t-T -\tnumber of threads to use for rendering\n" "\t-P\tparallel interpretation/rendering\n" #endif @@ -780,7 +588,7 @@ static int dodrawpage(fz_context *ctx, int pagenum, fz_cookie *cookie, render_de fz_set_pixmap_resolution(ctx, w->pix, x_resolution, y_resolution); DEBUG_THREADS(("Worker %d, Pre-triggering band %d\n", band, band)); w->started = 1; - SEMAPHORE_TRIGGER(w->start); + mu_trigger_semaphore(&w->start); ctm.f -= band_height; } pix = workers[0].pix; @@ -805,7 +613,7 @@ static int dodrawpage(fz_context *ctx, int pagenum, fz_cookie *cookie, render_de { worker_t *w = &workers[band % render->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); w->started = 0; status = w->status; pix = w->pix; @@ -840,7 +648,7 @@ static int dodrawpage(fz_context *ctx, int pagenum, fz_cookie *cookie, render_de memset(&w->cookie, 0, sizeof(fz_cookie)); DEBUG_THREADS(("Triggering worker %d for band_start= %d\n", w->num, w->band_start)); w->started = 1; - SEMAPHORE_TRIGGER(w->start); + mu_trigger_semaphore(&w->start); } ctm.f -= draw_height; } @@ -858,7 +666,7 @@ static int dodrawpage(fz_context *ctx, int pagenum, fz_cookie *cookie, render_de w->cookie.abort = 1; if (w->started) { - SEMAPHORE_WAIT(w->stop); + mu_wait_semaphore(&w->stop); w->started = 0; } fz_drop_pixmap(ctx, w->pix); @@ -1011,7 +819,7 @@ static int wait_for_bgprint_to_finish(void) if (!bgprint.active || !bgprint.started) return 0; - SEMAPHORE_WAIT(bgprint.stop); + mu_wait_semaphore(&bgprint.stop); bgprint.started = 0; return bgprint.status; } @@ -1336,7 +1144,7 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum) } bgprint.started = 1; bgprint.solo = 1; - SEMAPHORE_TRIGGER(bgprint.start); + mu_trigger_semaphore(&bgprint.start); status = wait_for_bgprint_to_finish(); if (status != 0) { @@ -1359,7 +1167,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 { @@ -1396,7 +1204,7 @@ finish_bgprint(fz_context *ctx) } bgprint.started = 1; bgprint.solo = 1; - SEMAPHORE_TRIGGER(bgprint.start); + mu_trigger_semaphore(&bgprint.start); status = wait_for_bgprint_to_finish(); if (status != 0) { @@ -1484,27 +1292,26 @@ trace_realloc(void *arg, void *p_, size_t size) return &p[1]; } -#if MURASTER_THREADS != 0 -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_start %d\n", me->num, me->band_start)); me->status = RENDER_OK; if (me->band_start >= 0) me->status = drawband(me->ctx, NULL, me->list, &me->ctm, &me->tbounds, &me->cookie, me->band_start, me->pix, &me->bit); DEBUG_THREADS(("Worker %d completed band_start %d (status=%d)\n", me->num, me->band_start, me->status)); - SEMAPHORE_TRIGGER(me->stop); + mu_trigger_semaphore(&me->stop); } while (me->band_start >= 0); - THREAD_RETURN(); } -static THREAD_RETURN_TYPE bgprint_worker(void *arg) +static void bgprint_worker(void *arg) { fz_cookie cookie = { 0 }; int pagenum; @@ -1514,7 +1321,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) @@ -1524,10 +1331,9 @@ static THREAD_RETURN_TYPE bgprint_worker(void *arg) bgprint.status = try_render_page(bgprint.ctx, pagenum, &cookie, start, bgprint.interptime, bgprint.filename, 1, bgprint.solo, &bgprint.render); } DEBUG_THREADS(("BGPrint completed page %d\n", pagenum)); - SEMAPHORE_TRIGGER(bgprint.stop); + mu_trigger_semaphore(&bgprint.stop); } while (pagenum >= 0); - THREAD_RETURN(); } #endif @@ -1576,9 +1382,10 @@ int main(int argc, char **argv) { char *password = ""; fz_document *doc = NULL; - int c, i; + int i, c; fz_context *ctx; fz_alloc_context alloc_ctx = { NULL, trace_malloc, trace_realloc, trace_free }; + fz_locks_context *locks = NULL; fz_var(doc); @@ -1666,7 +1473,16 @@ int main(int argc, char **argv) exit(1); } - ctx = fz_new_context((showmemory == 0 ? NULL : &alloc_ctx), LOCKS_INIT(), FZ_STORE_DEFAULT); +#ifndef DISABLE_MUTHREADS + locks = init_muraster_locks(); + if (locks == NULL) + { + fprintf(stderr, "cannot initialise mutexes\n"); + exit(1); + } +#endif + + ctx = fz_new_context((showmemory == 0 ? NULL : &alloc_ctx), locks, FZ_STORE_DEFAULT); if (!ctx) { fprintf(stderr, "cannot initialise context\n"); @@ -1676,26 +1492,40 @@ int main(int argc, char **argv) fz_set_text_aa_level(ctx, alphabits_text); fz_set_graphics_aa_level(ctx, alphabits_graphics); +#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 (layoutput_css) { @@ -1830,16 +1660,17 @@ int main(int argc, char **argv) fprintf(stderr, "slowest page %d: %dms\n", timing.maxpage, timing.max); } +#ifndef DISABLE_MUTHREADS if (num_workers > 0) { for (i = 0; i < num_workers; i++) { workers[i].band_start = -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); @@ -1848,19 +1679,22 @@ int 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_output(ctx, out); out = NULL; fz_drop_context(ctx); - LOCKS_FIN(); +#ifndef DISABLE_MUTHREADS + fin_muraster_locks(); +#endif /* DISABLE_MUTHREADS */ if (showmemory) { |