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: