diff options
author | Derrell Lipman <derrell@dworkin.(none)> | 2009-05-10 21:55:23 -0400 |
---|---|---|
committer | Derrell Lipman <derrell@dworkin.(none)> | 2009-05-10 22:45:12 -0400 |
commit | d3434477e6d42432a0acf426fcfbe39eb11b1fd0 (patch) | |
tree | 9108912416b0d73081a5af2204c0c74422162ba2 /lib/util/smb_threads.c | |
parent | 831b73ec82717c3c73ea1250f9c94228d251c1ec (diff) | |
download | samba-d3434477e6d42432a0acf426fcfbe39eb11b1fd0.tar.gz |
Replace external thread "once" with an internal implementation
Jeremy, please check...
- I'm in the process of providing an interface in libsmbclient to the
recently-added threading capabilities. In the process, I discovered that
different thread implementations have varying types for the variable passed
to the thread_impl_once() function. pthreads, for example, uses type
pthread_once_t. Since Samba needs to internally declare these variables, it
would need to know the exact type required by each thread implementation's
function. After considering multiple methods of obtaining an appropriately
sized variable, I decided that for the basic "once" functionality required
by Samba, it would be much simpler to just implement our own "once"
functionality. We don't require cancellation points et all. This commit adds
an smb_thread_once() function that is implemented using an internal
mutex. The mutex itself uses the implementation's create_mutex
function. This eliminates the need for the user to provide a smb_thread_once
function pointer and the entire issue of that function's first parameter.
Derrell
Diffstat (limited to 'lib/util/smb_threads.c')
-rw-r--r-- | lib/util/smb_threads.c | 64 |
1 files changed, 63 insertions, 1 deletions
diff --git a/lib/util/smb_threads.c b/lib/util/smb_threads.c index 1998211d40..8cddbf0176 100644 --- a/lib/util/smb_threads.c +++ b/lib/util/smb_threads.c @@ -40,6 +40,13 @@ const struct smb_thread_functions *global_tfp; void **global_lock_array; /********************************************************* + Mutex used for our internal "once" function +*********************************************************/ + +void *once_mutex = NULL; + + +/********************************************************* Function to set the locking primitives used by libsmbclient. *********************************************************/ @@ -80,9 +87,64 @@ int smb_thread_set_functions(const struct smb_thread_functions *tf) SAFE_FREE(name); } + /* Create the mutex we'll use for our "once" function */ + if (SMB_THREAD_CREATE_MUTEX("smb_once", once_mutex) != 0) { + smb_panic("smb_thread_set_functions: failed to create 'once' mutex"); + } + return 0; } +/******************************************************************* + Call a function only once. We implement this ourselves + using our own mutex rather than using the thread implementation's + *_once() function because each implementation has its own + type for the variable which keeps track of whether the function + has been called, and there's no easy way to allocate the correct + size variable in code internal to Samba without knowing the + implementation's "once" type. +********************************************************************/ +void smb_thread_once(smb_thread_once_t *ponce, void (*init_fn)(void)) +{ + int ret; + int need_func_call; + + /* Lock our "once" mutex in order to test and initialize ponce */ + if ((ret = SMB_THREAD_LOCK(once_mutex, SMB_THREAD_LOCK)) != 0) { + DEBUG(0, ("error locking 'once': %d\n", ret)); + } + + /* Store whether we're going to need to issue the function call */ + need_func_call = ! *ponce; + + /* + * See if another thread got here after we tested it initially but + * before we got our lock. + */ + if (need_func_call) { + /* + * Nope, we still need to issue the call. Set the "once" + * variable to true now so we can unlock the mutex. (We don't + * want to leave it locked during the call to the + * initialization function in case there's yet another "once" + * function needed to be called from therein.) + */ + *ponce = true; + } + + /* Unlock the mutex */ + if ((ret = SMB_THREAD_LOCK(once_mutex, SMB_THREAD_UNLOCK)) != 0) { + DEBUG(0, ("error unlocking 'once': %d\n", ret)); + } + + /* Finally, if we need to call the user-provided function, ... */ + if (need_func_call) { + /* ... then do so now. */ + (*init_fn)(); + } +} + + #if 0 /* Test. - pthread implementations. */ #include <pthread.h> @@ -128,7 +190,7 @@ int test_threads(void) if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_LOCK)) != 0) { printf("lock error: %d\n", ret); } - if ((SMB_THREAD_LOCK(plock, SMB_THREAD_UNLOCK)) != 0) { + if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_UNLOCK)) != 0) { printf("unlock error: %d\n", ret); } SMB_THREAD_DESTROY_MUTEX(plock); |