[gs-cvs] rev 8715 - trunk/gs/src
ray at ghostscript.com
ray at ghostscript.com
Thu May 8 12:10:40 PDT 2008
Author: ray
Date: 2008-05-08 12:10:40 -0700 (Thu, 08 May 2008)
New Revision: 8715
Modified:
trunk/gs/src/gp_psync.c
Log:
Add support for recursive mutex on posix. Multiple threads that perform
'locking' before calling an object's finalize need this to prevent
deadlock if the finalize calls 'free'. This protection is standard on
Windows, but PTHREAD_MUTEX_RECURSIVE attribute is not available on
many systems.
The method, using pthread_self and pthread_equal, was extracted from
a web information page and tested on linux.
NB: The multi-threaded clist rendering no longer needs this since
the 'chunk' memory wrapper calls the 'finalize' function without
locking, so the deadlock no longer occurs.
Modified: trunk/gs/src/gp_psync.c
===================================================================
--- trunk/gs/src/gp_psync.c 2008-05-08 18:56:10 UTC (rev 8714)
+++ trunk/gs/src/gp_psync.c 2008-05-08 19:10:40 UTC (rev 8715)
@@ -127,20 +127,31 @@
/* Monitor supports enter/leave semantics */
+/*
+ * We need PTHREAD_MUTEX_RECURSIVE behavior, but this isn't totally portable
+ * so we implement it in a more portable fashion, keeping track of the
+ * owner thread using 'pthread_self()'
+ */
+typedef struct gp_pthread_recursive_s {
+ pthread_mutex_t mutex; /* actual mutex */
+ pthread_t self_id; /* owner */
+} gp_pthread_recursive_t;
+
uint
gp_monitor_sizeof(void)
{
- return sizeof(pthread_mutex_t);
+ return sizeof(gp_pthread_recursive_t);
}
int
gp_monitor_open(gp_monitor * mona)
{
- pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
+ pthread_mutex_t * const mon = &((gp_pthread_recursive_t *)mona)->mutex;
int scode;
if (!mona)
return -1; /* monitors are not movable */
+ ((gp_pthread_recursive_t *)mona)->self_id = 0; /* Not valid unless mutex is locked */
scode = pthread_mutex_init(mon, NULL);
return SEM_ERROR_CODE(scode);
}
@@ -148,7 +159,7 @@
int
gp_monitor_close(gp_monitor * mona)
{
- pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
+ pthread_mutex_t * const mon = &((gp_pthread_recursive_t *)mona)->mutex;
int scode;
scode = pthread_mutex_destroy(mon);
@@ -161,8 +172,19 @@
pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
int scode;
- scode = pthread_mutex_lock(mon);
- return SEM_ERROR_CODE(scode);
+ if ((scode = pthread_mutex_trylock(mon)) == 0) {
+ ((gp_pthread_recursive_t *)mona)->self_id = pthread_self();
+ return SEM_ERROR_CODE(scode);
+ } else {
+ if (pthread_equal(pthread_self(),((gp_pthread_recursive_t *)mona)->self_id))
+ return 0;
+ else {
+ /* we were not the owner, wait */
+ scode = pthread_mutex_lock(mon);
+ ((gp_pthread_recursive_t *)mona)->self_id = pthread_self();
+ return SEM_ERROR_CODE(scode);
+ }
+ }
}
int
@@ -172,6 +194,7 @@
int scode;
scode = pthread_mutex_unlock(mon);
+ ((gp_pthread_recursive_t *)mona)->self_id = 0; /* Not valid unless mutex is locked */
return SEM_ERROR_CODE(scode);
}
More information about the gs-cvs
mailing list