1998211d40467a8335e57731a9b370008fb696d4
[ira/wip.git] / lib / util / smb_threads.c
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
34 const struct smb_thread_functions *global_tfp;
35
36 /*********************************************************
37  Dynamic lock array.
38 *********************************************************/
39
40 void **global_lock_array;
41
42 /*********************************************************
43  Function to set the locking primitives used by libsmbclient.
44 *********************************************************/
45
46 int smb_thread_set_functions(const struct smb_thread_functions *tf)
47 {
48         int i;
49
50         global_tfp = tf;
51
52 #if defined(PARANOID_MALLOC_CHECKER)
53 #ifdef malloc
54 #undef malloc
55 #endif
56 #endif
57
58         /* Here we initialize any static locks we're using. */
59         global_lock_array = (void **)malloc(sizeof(void *) *NUM_GLOBAL_LOCKS);
60
61 #if defined(PARANOID_MALLOC_CHECKER)
62 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
63 #endif
64
65         if (global_lock_array == NULL) {
66                 return ENOMEM;
67         }
68
69         for (i = 0; i < NUM_GLOBAL_LOCKS; i++) {
70                 char *name = NULL;
71                 if (asprintf(&name, "global_lock_%d", i) == -1) {
72                         SAFE_FREE(global_lock_array);
73                         return ENOMEM;
74                 }
75                 if (global_tfp->create_mutex(name,
76                                 &global_lock_array[i],
77                                 __location__)) {
78                         smb_panic("smb_thread_set_functions: create mutexes failed");
79                 }
80                 SAFE_FREE(name);
81         }
82
83         return 0;
84 }
85
86 #if 0
87 /* Test. - pthread implementations. */
88 #include <pthread.h>
89
90 #ifdef malloc
91 #undef malloc
92 #endif
93
94 SMB_THREADS_DEF_PTHREAD_IMPLEMENTATION(tf);
95
96 static smb_thread_once_t ot = SMB_THREAD_ONCE_INIT;
97 void *pkey = NULL;
98
99 static void init_fn(void)
100 {
101         int ret;
102
103         if (!global_tfp) {
104                 /* Non-thread safe init case. */
105                 if (ot) {
106                         return;
107                 }
108                 ot = true;
109         }
110
111         if ((ret = SMB_THREAD_CREATE_TLS("test_tls", pkey)) != 0) {
112                 printf("Create tls once error: %d\n", ret);
113         }
114 }
115
116 /* Test function. */
117 int test_threads(void)
118 {
119         int ret;
120         void *plock = NULL;
121         smb_thread_set_functions(&tf);
122
123         SMB_THREAD_ONCE(&ot, init_fn);
124
125         if ((ret = SMB_THREAD_CREATE_MUTEX("test", plock)) != 0) {
126                 printf("Create lock error: %d\n", ret);
127         }
128         if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_LOCK)) != 0) {
129                 printf("lock error: %d\n", ret);
130         }
131         if ((SMB_THREAD_LOCK(plock, SMB_THREAD_UNLOCK)) != 0) {
132                 printf("unlock error: %d\n", ret);
133         }
134         SMB_THREAD_DESTROY_MUTEX(plock);
135         SMB_THREAD_DESTROY_TLS(pkey);
136
137         return 0;
138 }
139 #endif