Subject: (experiment) Use TclpMasterLock() in stead of a separate notifierInitMutex. One less mutex to be worried about.

From: "jan.nijtmans" <[email-masked]>
Date: Mon, 21 Mar 2016 14:22:52 +0000

---
 generic/tclInt.h    |  1 +
 unix/tclUnixNotfy.c | 21 ++++++++++-----------
 unix/tclUnixThrd.c  | 25 +++++++++++++++++++++++++
 win/tclWinNotify.c  | 26 ++++++++++++++++++--------
 4 files changed, 54 insertions(+), 19 deletions(-)

diff --git a/generic/tclInt.h b/generic/tclInt.h
index 42c13dd..da792aa 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -3059,6 +3059,7 @@ MODULE_SCOPE void	TclpInitUnlock(void);
 MODULE_SCOPE Tcl_Obj *	TclpObjListVolumes(void);
 MODULE_SCOPE void	TclpMasterLock(void);
 MODULE_SCOPE void	TclpMasterUnlock(void);
+MODULE_SCOPE void	TclpMasterReset(void);
 MODULE_SCOPE int	TclpMatchFiles(Tcl_Interp *interp, char *separators,
 			    Tcl_DString *dirPtr, char *pattern, char *tail);
 MODULE_SCOPE int	TclpObjNormalizePath(Tcl_Interp *interp,
diff --git a/unix/tclUnixNotfy.c b/unix/tclUnixNotfy.c
index 1457890..ca6a7ef 100644
--- a/unix/tclUnixNotfy.c
+++ b/unix/tclUnixNotfy.c
@@ -152,7 +152,6 @@ static int triggerPipe = -1;
  * The notifierMutex locks access to all of the global notifier state.
  */
 
-pthread_mutex_t notifierInitMutex = PTHREAD_MUTEX_INITIALIZER;
 pthread_mutex_t notifierMutex     = PTHREAD_MUTEX_INITIALIZER;
 /*
  * The following static indicates if the notifier thread is running.
@@ -281,7 +280,7 @@ static void
 StartNotifierThread(const char *proc)
 {
     if (!notifierThreadRunning) {
-	pthread_mutex_lock(&notifierInitMutex);
+	TclpMasterLock();
 	if (!notifierThreadRunning) {
 	    if (TclpThreadCreate(&notifierThread, NotifierThreadProc, NULL,
 		    TCL_THREAD_STACK_DEFAULT, TCL_THREAD_JOINABLE) != TCL_OK) {
@@ -300,7 +299,7 @@ StartNotifierThread(const char *proc)
 
 	    notifierThreadRunning = 1;
 	}
-	pthread_mutex_unlock(&notifierInitMutex);
+	TclpMasterUnlock();
     }
 }
 #endif /* TCL_THREADS */
@@ -362,7 +361,7 @@ Tcl_InitNotifier(void)
 	    tsdPtr->waitCVinitialized = 1;
 	}
 
-	pthread_mutex_lock(&notifierInitMutex);
+	TclpMasterLock();
 #if defined(HAVE_PTHREAD_ATFORK)
 	/*
 	 * Install pthread_atfork handlers to clean up the notifier in the
@@ -381,7 +380,7 @@ Tcl_InitNotifier(void)
 
 	notifierCount++;
 
-	pthread_mutex_unlock(&notifierInitMutex);
+	TclpMasterUnlock();
 
 #endif /* TCL_THREADS */
 	return tsdPtr;
@@ -417,7 +416,7 @@ Tcl_FinalizeNotifier(
 #ifdef TCL_THREADS
 	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
 
-	pthread_mutex_lock(&notifierInitMutex);
+	TclpMasterLock();
 	notifierCount--;
 
 	/*
@@ -462,7 +461,7 @@ Tcl_FinalizeNotifier(
 #endif /* __CYGWIN__ */
 	tsdPtr->waitCVinitialized = 0;
 
-	pthread_mutex_unlock(&notifierInitMutex);
+	TclpMasterUnlock();
 #endif /* TCL_THREADS */
     }
 }
@@ -1368,7 +1367,7 @@ static void
 AtForkPrepare(void)
 {
 #if RESET_ATFORK_MUTEX == 0
-    pthread_mutex_lock(&notifierInitMutex);
+    TclpMasterLock();
 #endif
 }
 
@@ -1392,7 +1391,7 @@ static void
 AtForkParent(void)
 {
 #if RESET_ATFORK_MUTEX == 0
-    pthread_mutex_unlock(&notifierInitMutex);
+    TclpMasterUnlock();
 #endif
 }
 
@@ -1419,9 +1418,9 @@ AtForkChild(void)
 	pthread_cond_destroy(&notifierCV);
     }
 #if RESET_ATFORK_MUTEX == 0
-    pthread_mutex_unlock(&notifierInitMutex);
+    TclpMasterUnlock();
 #else
-    pthread_mutex_init(&notifierInitMutex, NULL);
+    TclpMasterReset();
     pthread_mutex_init(&notifierMutex, NULL);
 #endif
     pthread_cond_init(&notifierCV, NULL);
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c
index 554a2dc..4130993 100644
--- a/unix/tclUnixThrd.c
+++ b/unix/tclUnixThrd.c
@@ -357,6 +357,31 @@ TclpMasterUnlock(void)
 /*
  *----------------------------------------------------------------------
  *
+ * TclpMasterReset
+ *
+ *	This procedure is used to reset a lock that serializes creation and
+ *	finalization of synchronization objects.
+ *
+ * Results:
+ *	None.
+ *
+ * Side effects:
+ *	Reset the master mutex.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TclpMasterReset(void)
+{
+#ifdef TCL_THREADS
+    pthread_mutex_init(&masterLock, NULL);
+#endif
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
  * Tcl_GetAllocMutex
  *
  *	This procedure returns a pointer to a statically initialized mutex for
diff --git a/win/tclWinNotify.c b/win/tclWinNotify.c
index 4543b02..985a769 100644
--- a/win/tclWinNotify.c
+++ b/win/tclWinNotify.c
@@ -51,7 +51,8 @@ static Tcl_ThreadDataKey dataKey;
 
 static int notifierCount = 0;
 static const TCHAR classname[] = TEXT("TclNotifier");
-TCL_DECLARE_MUTEX(notifierMutex)
+static int initialized = 0;
+static CRITICAL_SECTION notifierMutex;
 
 /*
  * Static routines defined in this file.
@@ -85,12 +86,19 @@ Tcl_InitNotifier(void)
 	ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
 	WNDCLASS class;
 
+	TclpMasterLock();
+	if (!initialized) {
+	    initialized = 1;
+	    InitializeCriticalSection(&notifierMutex);
+	}
+	TclpMasterUnlock();
+
 	/*
 	 * Register Notifier window class if this is the first thread to use
 	 * this module.
 	 */
 
-	Tcl_MutexLock(&notifierMutex);
+	EnterCriticalSection(&notifierMutex);
 	if (notifierCount == 0) {
 	    class.style = 0;
 	    class.cbClsExtra = 0;
@@ -108,7 +116,7 @@ Tcl_InitNotifier(void)
 	    }
 	}
 	notifierCount++;
-	Tcl_MutexUnlock(&notifierMutex);
+	LeaveCriticalSection(&notifierMutex);
 
 	tsdPtr->pending = 0;
 	tsdPtr->timerActive = 0;
@@ -183,12 +191,14 @@ Tcl_FinalizeNotifier(
 	 * notifier window class.
 	 */
 
-	Tcl_MutexLock(&notifierMutex);
-	notifierCount--;
-	if (notifierCount == 0) {
-	    UnregisterClass(classname, TclWinGetTclInstance());
+	EnterCriticalSection(&notifierMutex);
+	if (notifierCount) {
+	    notifierCount--;
+	    if (notifierCount == 0) {
+		UnregisterClass(classname, TclWinGetTclInstance());
+	    }
 	}
-	Tcl_MutexUnlock(&notifierMutex);
+	LeaveCriticalSection(&notifierMutex);
     }
 }
 
-- 
cgit v0.12