auth/credentials: don't ignore "client use kerberos" and --use-kerberos for machine...
[Samba.git] / lib / util / smb_threads.c
blob421dac9109a0b16a4c9f5c5322f00fbb60474cb9
1 /*
2 Unix SMB/CIFS implementation.
3 SMB client library implementation (thread interface functions).
4 Copyright (C) Jeremy Allison, 2009.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * This code is based in the ideas in openssl
22 * but somewhat simpler and expended to include
23 * thread local storage.
26 #include "replace.h"
27 #include "smb_threads.h"
28 #include "smb_threads_internal.h"
29 #include "lib/util/debug.h"
30 #include "lib/util/fault.h"
31 #include "lib/util/memory.h"
33 /*********************************************************
34 Functions to vector the locking primitives used internally
35 by libsmbclient.
36 *********************************************************/
38 const struct smb_thread_functions *global_tfp;
40 /*********************************************************
41 Dynamic lock array.
42 *********************************************************/
44 void **global_lock_array;
46 /*********************************************************
47 Mutex used for our internal "once" function
48 *********************************************************/
50 static void *once_mutex = NULL;
53 /*********************************************************
54 Function to set the locking primitives used by libsmbclient.
55 *********************************************************/
57 int smb_thread_set_functions(const struct smb_thread_functions *tf)
59 int i;
61 global_tfp = tf;
63 #if defined(PARANOID_MALLOC_CHECKER)
64 #ifdef malloc
65 #undef malloc
66 #endif
67 #endif
69 /* Here we initialize any static locks we're using. */
70 global_lock_array = (void **)malloc(sizeof(void *) *NUM_GLOBAL_LOCKS);
72 #if defined(PARANOID_MALLOC_CHECKER)
73 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
74 #endif
76 if (global_lock_array == NULL) {
77 return ENOMEM;
80 for (i = 0; i < NUM_GLOBAL_LOCKS; i++) {
81 char *name = NULL;
82 if (asprintf(&name, "global_lock_%d", i) == -1) {
83 SAFE_FREE(global_lock_array);
84 return ENOMEM;
86 if (global_tfp->create_mutex(name,
87 &global_lock_array[i],
88 __location__)) {
89 smb_panic("smb_thread_set_functions: create mutexes failed");
91 SAFE_FREE(name);
94 /* Create the mutex we'll use for our "once" function */
95 if (SMB_THREAD_CREATE_MUTEX("smb_once", once_mutex) != 0) {
96 smb_panic("smb_thread_set_functions: failed to create 'once' mutex");
99 return 0;
102 /*******************************************************************
103 Call a function only once. We implement this ourselves
104 using our own mutex rather than using the thread implementation's
105 *_once() function because each implementation has its own
106 type for the variable which keeps track of whether the function
107 has been called, and there's no easy way to allocate the correct
108 size variable in code internal to Samba without knowing the
109 implementation's "once" type.
110 ********************************************************************/
112 int smb_thread_once(smb_thread_once_t *ponce,
113 void (*init_fn)(void *pdata),
114 void *pdata)
116 int ret;
118 /* Lock our "once" mutex in order to test and initialize ponce */
119 if (SMB_THREAD_LOCK(once_mutex) != 0) {
120 smb_panic("error locking 'once'");
123 /* Keep track of whether we ran their init function */
124 ret = ! *ponce;
127 * See if another thread got here after we tested it initially but
128 * before we got our lock.
130 if (! *ponce) {
131 /* Nope, we need to run the initialization function */
132 (*init_fn)(pdata);
134 /* Now we can indicate that the function has been run */
135 *ponce = true;
138 /* Unlock the mutex */
139 if (SMB_THREAD_UNLOCK(once_mutex) != 0) {
140 smb_panic("error unlocking 'once'");
144 * Tell 'em whether we ran their init function. If they passed a data
145 * pointer to the init function and the init function could change
146 * something in the pointed-to data, this will tell them whether that
147 * data is valid or not.
149 return ret;
153 #if 0
154 /* Test. - pthread implementations. */
155 #include <pthread.h>
157 #ifdef malloc
158 #undef malloc
159 #endif
161 SMB_THREADS_DEF_PTHREAD_IMPLEMENTATION(tf);
163 static smb_thread_once_t ot = SMB_THREAD_ONCE_INIT;
164 void *pkey = NULL;
166 static void init_fn(void)
168 int ret;
170 if (!global_tfp) {
171 /* Non-thread safe init case. */
172 if (ot) {
173 return;
175 ot = true;
178 if ((ret = SMB_THREAD_CREATE_TLS("test_tls", pkey)) != 0) {
179 printf("Create tls once error: %d\n", ret);
183 /* Test function. */
184 int test_threads(void)
186 int ret;
187 void *plock = NULL;
188 smb_thread_set_functions(&tf);
190 SMB_THREAD_ONCE(&ot, init_fn);
192 if ((ret = SMB_THREAD_CREATE_MUTEX("test", plock)) != 0) {
193 printf("Create lock error: %d\n", ret);
195 if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_LOCK)) != 0) {
196 printf("lock error: %d\n", ret);
198 if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_UNLOCK)) != 0) {
199 printf("unlock error: %d\n", ret);
201 SMB_THREAD_DESTROY_MUTEX(plock);
202 SMB_THREAD_DESTROY_TLS(pkey);
204 return 0;
206 #endif