[gs-cvs] rev 8638 - branches/mtrender/src

ray at ghostscript.com ray at ghostscript.com
Sun Apr 13 19:46:20 PDT 2008


Author: ray
Date: 2008-04-13 19:46:20 -0700 (Sun, 13 Apr 2008)
New Revision: 8638

Modified:
   branches/mtrender/src/gp_psync.c
Log:
Add protection for recursive locking of a mutex (monitor) by the same
thread. This is the default behavior on Windows (I guess Windoze coders
tend to be sloppier about mutex deadlock, primarily due to recursion).
This was detected with the multi-threaded render, on linux, when the
'finalize' procedure for a structure also tried to free (invoking a
deadlock since the same thread already "owned" the mutex).


Modified: branches/mtrender/src/gp_psync.c
===================================================================
--- branches/mtrender/src/gp_psync.c	2008-04-14 02:40:55 UTC (rev 8637)
+++ branches/mtrender/src/gp_psync.c	2008-04-14 02:46:20 UTC (rev 8638)
@@ -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