summaryrefslogtreecommitdiff
path: root/lib/util/smb_threads.c
diff options
context:
space:
mode:
authorDerrell Lipman <derrell@dworkin.(none)>2009-05-10 21:55:23 -0400
committerDerrell Lipman <derrell@dworkin.(none)>2009-05-10 22:45:12 -0400
commitd3434477e6d42432a0acf426fcfbe39eb11b1fd0 (patch)
tree9108912416b0d73081a5af2204c0c74422162ba2 /lib/util/smb_threads.c
parent831b73ec82717c3c73ea1250f9c94228d251c1ec (diff)
downloadsamba-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.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/lib/util/smb_threads.c b/lib/util/smb_threads.c
index 1998211d404..8cddbf01762 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);