commit: r457 - in trunk: daemon libspread

[email protected] Tue, 10 Jan 2012 14:55:41 -0500
Newsgroups gmane.network.spread.cvs
Message-ID <[email protected]>
Author: jschultz
Date: 2012-01-10 14:55:41 -0500 (Tue, 10 Jan 2012)
New Revision: 457

Modified:
   trunk/daemon/Changelog
   trunk/daemon/mutex.h
   trunk/libspread/sp.c
Log:
Added Once_execute capabilities and changed the way client lib self initializes.



Modified: trunk/daemon/Changelog
===================================================================
--- trunk/daemon/Changelog	2012-01-10 17:40:40 UTC (rev 456)
+++ trunk/daemon/Changelog	2012-01-10 19:55:41 UTC (rev 457)
@@ -1,3 +1,12 @@
+Tue Jan 10 14:50:23 2012  John Schultz <[email protected]>
+
+	* mutex.h, sp.c: Changed mutex.h to add Once_execute capabilities.
+	mutex.h now requires Windows 2000 or later to work.  Changed sp.c
+	initialization to use Once_execute rather than messy static 
+	initialization and grabbing a lock once and holding it forever.
+	An important difference remains: on POSIX platforms Mutex's are
+	non-recursive while on Windows platforms they are recursive!
+
 Tue Jan 10 12:30:48 2012  John Schultz <[email protected]>
 
 	* session.c: Changed the way we "badger" client sessions that have 

Modified: trunk/daemon/mutex.h
===================================================================
--- trunk/daemon/mutex.h	2012-01-10 17:40:40 UTC (rev 456)
+++ trunk/daemon/mutex.h	2012-01-10 19:55:41 UTC (rev 457)
@@ -41,27 +41,31 @@
 #ifndef _REENTRANT
 
 #define MUTEX_STATIC_INIT 	0
+#define ONCE_STATIC_INIT        0
 
 #define mutex_type 		int
+#define once_type               int
 
 #define Mutex_init( mutex )    
 #define Mutex_lock( mutex )    
 #define Mutex_unlock( mutex ) 
 
-static	int	Trylock_firsttime = 0;
+#define Mutex_trylock( mutex )	-1
 
-#define Mutex_trylock( mutex )	 Trylock_firsttime; Trylock_firsttime = 1
-
 #define Mutex_atfork( prepare, parent, child )
 
+#define Once_execute( control, initializer ) do { if ( *(control) == 0 ) { *(control) = 1; (initializer)(); } } while (0)
+
 #else	/* _REENTRANT */
 
 #ifndef ARCH_PC_WIN95
 #include <pthread.h>
 
 #define MUTEX_STATIC_INIT 	PTHREAD_MUTEX_INITIALIZER
+#define ONCE_STATIC_INIT        PTHREAD_ONCE_INIT
 
 #define mutex_type 		pthread_mutex_t
+#define once_type               pthread_once_t
 
 #define Mutex_init( mutex )	pthread_mutex_init( (mutex), NULL )
 #define Mutex_lock( mutex )	pthread_mutex_lock( mutex )
@@ -69,30 +73,65 @@
 #define Mutex_trylock( mutex )	pthread_mutex_trylock( mutex )
 
 #ifdef  HAVE_PTHREAD_ATFORK
-#   define Mutex_atfork( prepare, parent, child )  pthread_atfork( prepare, parent, child )
+#   define Mutex_atfork( prepare, parent, child )  pthread_atfork( (prepare), (parent), (child) )
 #else
 #   define Mutex_atfork( prepare, parent, child )
 #endif
 
+#define Once_execute( control, initializer ) pthread_once( (control), (initializer) )
+
 #else	/* ARCH_PC_WIN95 */
 
-	/* ### Static init is implemented with a problem which cannot be solved */
 #include <process.h>
 
-#define MUTEX_STATIC_INIT 	0
+#define MUTEX_STATIC_INIT 	{ 0 }
+#define ONCE_STATIC_INIT        { 0, 0 }
 
 #define mutex_type 		CRITICAL_SECTION
+#define once_type               ONCE_CONTROL
 
+typedef struct 
+{
+  volatile int    initialized;
+  volatile HANDLE mutex;
+  
+} ONCE_CONTROL;
+
 #define Mutex_init( mutex )	InitializeCriticalSection( mutex )
 #define Mutex_lock( mutex )	EnterCriticalSection( mutex )
 #define Mutex_unlock( mutex )	LeaveCriticalSection( mutex )
+#define Mutex_trylock( mutex )	!TryEnterCriticalSection( mutex )
 
-static	int 	Trylock_firsttime = 0;
-#define Mutex_trylock( mutex )	Trylock_firsttime; Trylock_firsttime = 1
-
 /* Not needed? for Windows */
 #define Mutex_atfork( prepare, parent, child )
 
+#define Once_execute( control, initializer )\
+    if( !(control)->initialized )\
+    {\
+        HANDLE myMutex = CreateMutex( NULL, 0, NULL );\
+        if( myMutex == INVALID_HANDLE_VALUE )\
+        {\
+            int error = GetLastError();\
+            Alarm( EXIT, "Once_execute: Error creating mutex: %d\n", error );\
+        }\
+        if( InterlockedCompareExchangePointer( &(control)->mutex, myMutex, 0 ) )\
+        {\
+            CloseHandle( myMutex );\
+        }\
+        \
+        if( WaitForSingleObject( (control)->mutex, INFINITE ) == WAIT_FAILED )\
+        {\
+            int error = GetLastError();\
+            Alarm( EXIT, "Once_execute: Error locking mutex: %d\n", error );\
+        }\
+        if( !(control)->initialized )\
+        {\
+            (control)->initialized = 1;\
+            (initializer)();\
+        }\
+        ReleaseMutex( (control)->mutex );\
+    }
+
 #endif /* ARCH_PC_WIN95 */
 
 

Modified: trunk/libspread/sp.c
===================================================================
--- trunk/libspread/sp.c	2012-01-10 17:40:40 UTC (rev 456)
+++ trunk/libspread/sp.c	2012-01-10 19:55:41 UTC (rev 457)
@@ -37,7 +37,6 @@
 #include "arch.h"
 #include <string.h>
 #include <stdio.h>
-#include "mutex.h"
 
 #ifndef	ARCH_PC_WIN95
 
@@ -63,6 +62,7 @@
 
 #endif	/* ARCH_PC_WIN95 */
 
+#include "mutex.h"
 #include "sp_events.h"
 #include "spread_params.h"
 #include "sess_types.h"
@@ -122,13 +122,9 @@
 #define	MAX_MUTEX	256
 #define	MAX_MUTEX_MASK	0x000000ff
 
-#ifdef _REENTRANT
-#ifndef	ARCH_PC_WIN95
-static	mutex_type	Init_mutex = MUTEX_STATIC_INIT;
-#else	/* ARCH_PC_WIN95 */
-static	mutex_type	Init_mutex = {MUTEX_STATIC_INIT};
-#endif	/* ARCH_PC_WIN95 */
+static once_type Init_once = ONCE_STATIC_INIT;
 
+#ifdef _REENTRANT
 static	mutex_type	Struct_mutex;
 static	mutex_type	Mbox_mutex[MAX_MUTEX][2];
 
@@ -229,33 +225,27 @@
 #endif  /* HAVE_PTHREAD_ATFORK */
 #endif /* _REENTRANT */
 
-static  void    sp_initialize_locks(void)
+static  void    sp_initialize(void)
 {
-        int ret, i;
+        int i;
 
-	ret = Mutex_trylock( &Init_mutex );
-	if( ret == 0 )
+	Mutex_init( &Struct_mutex );
+	for( i=0; i < MAX_MUTEX; i++ )
 	{
-		/* 
-		 * we managed to lock the Init_mutex. This means we are the first thread
-		 * to get here.
-		 */
+	        Mutex_init( &Mbox_mutex[i][0] );
+		Mutex_init( &Mbox_mutex[i][1] );
+	}
 
-		Mutex_init( &Struct_mutex );
-		for( i=0; i < MAX_MUTEX; i++ )
-		{
-			Mutex_init( &Mbox_mutex[i][0] );
-			Mutex_init( &Mbox_mutex[i][1] );
-		}
+	Mutex_atfork( sp_atfork_prepare, sp_atfork_parent, sp_atfork_child );
 
-                Mutex_atfork( sp_atfork_prepare, sp_atfork_parent, sp_atfork_child );
 #ifdef ARCH_PC_WIN95
-
-		ret = WSAStartup( MAKEWORD(2,0), &WSAData );
+	{
+	        int ret = WSAStartup( MAKEWORD(2,0), &WSAData );
 		if( ret != 0 )
-			Alarm( EXIT, "sp_initialize_locks: winsock initialization error %d\n", ret );
-#endif	/* ARCH_PC_WIN95 */
+		  Alarm( EXIT, "sp_initialize_locks: winsock initialization error %d\n", ret );
 	}
+#endif	/* ARCH_PC_WIN95 */
+
         return;
 }
 /* This calls recv() with the additional features of ignoring syscall interruptions
@@ -474,7 +464,7 @@
  */
 int     SP_set_auth_method( const char *auth_name, int (*auth_function) (int, void *), void * auth_data)
 {
-        sp_initialize_locks();
+        Once_execute( &Init_once, sp_initialize );
 
         if (strlen(auth_name) >= MAX_AUTH_NAME)
         {
@@ -503,8 +493,9 @@
 int     SP_set_auth_methods( int num_methods, const char *auth_name[], int (*auth_function[]) (int, void *), void * auth_data[])
 {
         int i;
-        sp_initialize_locks();
 
+        Once_execute(&Init_once, sp_initialize );
+
         if (num_methods < 0 || num_methods > MAX_AUTH_METHODS)
         {
             Alarm( SESSION, "SP_set_auth_methods: Too many methods trying to be registered\n");
@@ -597,7 +588,7 @@
         Alarm_set_priority(SPLOG_DEBUG);
 #endif
 
-        sp_initialize_locks();
+        Once_execute( &Init_once, sp_initialize );
 
 	/* 
 	 * There are 3 possibilities for a name: