source: vendor/current/lib/util/smb_threads.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 5.4 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 SMB client library implementation (thread interface functions).
4 Copyright (C) Jeremy Allison, 2009.
5
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.
10
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.
15
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/>.
18*/
19
20/*
21 * This code is based in the ideas in openssl
22 * but somewhat simpler and expended to include
23 * thread local storage.
24 */
25
26#include "includes.h"
27#include "smb_threads.h"
28
29/*********************************************************
30 Functions to vector the locking primitives used internally
31 by libsmbclient.
32*********************************************************/
33
34const struct smb_thread_functions *global_tfp;
35
36/*********************************************************
37 Dynamic lock array.
38*********************************************************/
39
40void **global_lock_array;
41
42/*********************************************************
43 Mutex used for our internal "once" function
44*********************************************************/
45
46static void *once_mutex = NULL;
47
48
49/*********************************************************
50 Function to set the locking primitives used by libsmbclient.
51*********************************************************/
52
53int smb_thread_set_functions(const struct smb_thread_functions *tf)
54{
55 int i;
56
57 global_tfp = tf;
58
59#if defined(PARANOID_MALLOC_CHECKER)
60#ifdef malloc
61#undef malloc
62#endif
63#endif
64
65 /* Here we initialize any static locks we're using. */
66 global_lock_array = (void **)malloc(sizeof(void *) *NUM_GLOBAL_LOCKS);
67
68#if defined(PARANOID_MALLOC_CHECKER)
69#define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
70#endif
71
72 if (global_lock_array == NULL) {
73 return ENOMEM;
74 }
75
76 for (i = 0; i < NUM_GLOBAL_LOCKS; i++) {
77 char *name = NULL;
78 if (asprintf(&name, "global_lock_%d", i) == -1) {
79 SAFE_FREE(global_lock_array);
80 return ENOMEM;
81 }
82 if (global_tfp->create_mutex(name,
83 &global_lock_array[i],
84 __location__)) {
85 smb_panic("smb_thread_set_functions: create mutexes failed");
86 }
87 SAFE_FREE(name);
88 }
89
90 /* Create the mutex we'll use for our "once" function */
91 if (SMB_THREAD_CREATE_MUTEX("smb_once", once_mutex) != 0) {
92 smb_panic("smb_thread_set_functions: failed to create 'once' mutex");
93 }
94
95 return 0;
96}
97
98/*******************************************************************
99 Call a function only once. We implement this ourselves
100 using our own mutex rather than using the thread implementation's
101 *_once() function because each implementation has its own
102 type for the variable which keeps track of whether the function
103 has been called, and there's no easy way to allocate the correct
104 size variable in code internal to Samba without knowing the
105 implementation's "once" type.
106********************************************************************/
107
108int smb_thread_once(smb_thread_once_t *ponce,
109 void (*init_fn)(void *pdata),
110 void *pdata)
111{
112 int ret;
113
114 /* Lock our "once" mutex in order to test and initialize ponce */
115 if (SMB_THREAD_LOCK(once_mutex) != 0) {
116 smb_panic("error locking 'once'");
117 }
118
119 /* Keep track of whether we ran their init function */
120 ret = ! *ponce;
121
122 /*
123 * See if another thread got here after we tested it initially but
124 * before we got our lock.
125 */
126 if (! *ponce) {
127 /* Nope, we need to run the initialization function */
128 (*init_fn)(pdata);
129
130 /* Now we can indicate that the function has been run */
131 *ponce = true;
132 }
133
134 /* Unlock the mutex */
135 if (SMB_THREAD_UNLOCK(once_mutex) != 0) {
136 smb_panic("error unlocking 'once'");
137 }
138
139 /*
140 * Tell 'em whether we ran their init function. If they passed a data
141 * pointer to the init function and the init function could change
142 * something in the pointed-to data, this will tell them whether that
143 * data is valid or not.
144 */
145 return ret;
146}
147
148
149#if 0
150/* Test. - pthread implementations. */
151#include <pthread.h>
152
153#ifdef malloc
154#undef malloc
155#endif
156
157SMB_THREADS_DEF_PTHREAD_IMPLEMENTATION(tf);
158
159static smb_thread_once_t ot = SMB_THREAD_ONCE_INIT;
160void *pkey = NULL;
161
162static void init_fn(void)
163{
164 int ret;
165
166 if (!global_tfp) {
167 /* Non-thread safe init case. */
168 if (ot) {
169 return;
170 }
171 ot = true;
172 }
173
174 if ((ret = SMB_THREAD_CREATE_TLS("test_tls", pkey)) != 0) {
175 printf("Create tls once error: %d\n", ret);
176 }
177}
178
179/* Test function. */
180int test_threads(void)
181{
182 int ret;
183 void *plock = NULL;
184 smb_thread_set_functions(&tf);
185
186 SMB_THREAD_ONCE(&ot, init_fn);
187
188 if ((ret = SMB_THREAD_CREATE_MUTEX("test", plock)) != 0) {
189 printf("Create lock error: %d\n", ret);
190 }
191 if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_LOCK)) != 0) {
192 printf("lock error: %d\n", ret);
193 }
194 if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_UNLOCK)) != 0) {
195 printf("unlock error: %d\n", ret);
196 }
197 SMB_THREAD_DESTROY_MUTEX(plock);
198 SMB_THREAD_DESTROY_TLS(pkey);
199
200 return 0;
201}
202#endif
Note: See TracBrowser for help on using the repository browser.