1
+ #include "TSRM.h"
2
+ #include <stdio.h>
3
+
4
+ typedef struct _tsrm_tls_entry tsrm_tls_entry ;
5
+
6
+ struct _tsrm_tls_entry {
7
+ void * * storage ;
8
+ int count ;
9
+ THREAD_T thread_id ;
10
+ tsrm_tls_entry * next ;
11
+ };
12
+
13
+
14
+ typedef struct {
15
+ size_t size ;
16
+ void (* ctor )(void * resource );
17
+ void (* dtor )(void * resource );
18
+ } tsrm_resource_type ;
19
+
20
+
21
+ /* The memory manager table */
22
+ static tsrm_tls_entry * * tsrm_tls_table ;
23
+ static int tsrm_tls_table_size ;
24
+ static ts_rsrc_id id_count ;
25
+
26
+ /* The resource sizes table */
27
+ static tsrm_resource_type * resource_types_table ;
28
+ static int resource_types_table_size ;
29
+
30
+
31
+ static MUTEX_T tsmm_mutex ; /* thread-safe memory manager mutex */
32
+
33
+ /* Debug support */
34
+ static int tsrm_debug (const char * format , ...);
35
+ static int tsrm_debug_status ;
36
+
37
+
38
+ /* Startup TSRM (call once for the entire process) */
39
+ int tsrm_startup (int expected_threads , int expected_resources , int debug_status )
40
+ {
41
+ tsrm_tls_table_size = expected_threads ;
42
+ tsrm_tls_table = (tsrm_tls_entry * * ) calloc (tsrm_tls_table_size , sizeof (tsrm_tls_entry * ));
43
+ if (!tsrm_tls_table ) {
44
+ return 0 ;
45
+ }
46
+ id_count = 0 ;
47
+
48
+ resource_types_table_size = expected_resources ;
49
+ resource_types_table = (tsrm_resource_type * ) calloc (resource_types_table_size , sizeof (tsrm_resource_type ));
50
+ if (!resource_types_table ) {
51
+ free (tsrm_tls_table );
52
+ return 0 ;
53
+ }
54
+
55
+ tsmm_mutex = tsrm_mutex_alloc ();
56
+
57
+ tsrm_debug_status = debug_status ;
58
+
59
+ tsrm_debug ("Started up TSRM, %d expected threads, %d expected resources\n" , expected_threads , expected_resources );
60
+ return 1 ;
61
+ }
62
+
63
+
64
+ /* Shutdown TSRM (call once for the entire process) */
65
+ void tsrm_shutdown ()
66
+ {
67
+ int i ;
68
+
69
+ if (tsrm_tls_table ) {
70
+ for (i = 0 ; i < tsrm_tls_table_size ; i ++ ) {
71
+ tsrm_tls_entry * p = tsrm_tls_table [i ], * next_p ;
72
+
73
+ while (p ) {
74
+ int j ;
75
+
76
+ next_p = p -> next ;
77
+ for (j = 0 ; j < id_count ; j ++ ) {
78
+ free (p -> storage [j ]);
79
+ }
80
+ free (p -> storage );
81
+ free (p );
82
+ p = next_p ;
83
+ }
84
+ }
85
+ free (tsrm_tls_table );
86
+ }
87
+ if (resource_types_table ) {
88
+ free (resource_types_table );
89
+ }
90
+ tsrm_mutex_free (tsmm_mutex );
91
+ tsrm_debug ("Shutdown TSRM\n" );
92
+ }
93
+
94
+
95
+ /* allocates a new thread-safe-resource id */
96
+ TSRM_FUNC ts_rsrc_id ts_allocate_id (size_t size , void (* ctor )(void * resource ), void (* dtor )(void * resource ))
97
+ {
98
+ ts_rsrc_id new_id ;
99
+ int i ;
100
+
101
+ tsrm_debug ("Obtaining a new resource id, %d bytes\n" , size );
102
+
103
+ tsrm_mutex_lock (tsmm_mutex );
104
+
105
+ /* obtain a resource id */
106
+ new_id = id_count ++ ;
107
+ tsrm_debug ("Obtained resource id %d\n" , new_id );
108
+
109
+ /* store the new resource type in the resource sizes table */
110
+ if (resource_types_table_size < id_count ) {
111
+ resource_types_table = (tsrm_resource_type * ) realloc (resource_types_table , sizeof (tsrm_resource_type )* id_count );
112
+ if (!resource_types_table ) {
113
+ return -1 ;
114
+ }
115
+ resource_types_table_size = id_count ;
116
+ }
117
+ resource_types_table [new_id ].size = size ;
118
+ resource_types_table [new_id ].ctor = ctor ;
119
+ resource_types_table [new_id ].dtor = dtor ;
120
+
121
+ /* enlarge the arrays for the already active threads */
122
+ for (i = 0 ; i < tsrm_tls_table_size ; i ++ ) {
123
+ tsrm_tls_entry * p = tsrm_tls_table [i ];
124
+
125
+ while (p ) {
126
+ if (p -> count < id_count ) {
127
+ int j ;
128
+
129
+ p -> storage = realloc (p -> storage , sizeof (void * )* id_count );
130
+ for (j = p -> count ; j < id_count ; j ++ ) {
131
+ p -> storage [j ] = (void * ) malloc (resource_types_table [j ].size );
132
+ }
133
+ p -> count = id_count ;
134
+ }
135
+ p = p -> next ;
136
+ }
137
+ }
138
+ tsrm_mutex_unlock (tsmm_mutex );
139
+
140
+ tsrm_debug ("Successfully allocated new resource id %d\n" , new_id );
141
+ return new_id ;
142
+ }
143
+
144
+
145
+ static void allocate_new_resource (tsrm_tls_entry * * thread_resources_ptr , THREAD_T thread_id )
146
+ {
147
+ int i ;
148
+
149
+ (* thread_resources_ptr ) = (tsrm_tls_entry * ) malloc (sizeof (tsrm_tls_entry ));
150
+ (* thread_resources_ptr )-> storage = (void * * ) malloc (sizeof (void * )* id_count );
151
+ (* thread_resources_ptr )-> count = id_count ;
152
+ (* thread_resources_ptr )-> thread_id = thread_id ;
153
+ (* thread_resources_ptr )-> next = NULL ;
154
+ for (i = 0 ; i < id_count ; i ++ ) {
155
+ (* thread_resources_ptr )-> storage [i ] = (void * ) malloc (resource_types_table [i ].size );
156
+ resource_types_table [i ].ctor ((* thread_resources_ptr )-> storage [i ]);
157
+ }
158
+ }
159
+
160
+
161
+ /* fetches the requested resource for the current thread */
162
+ void * ts_resource (ts_rsrc_id id )
163
+ {
164
+ THREAD_T thread_id = tsrm_thread_id ();
165
+ int hash_value ;
166
+ tsrm_tls_entry * thread_resources ;
167
+ void * resource ;
168
+
169
+ tsrm_debug ("Fetching resource id %d for thread %ld\n" , id , (long ) thread_id );
170
+ tsrm_mutex_lock (tsmm_mutex );
171
+
172
+ hash_value = THREAD_HASH_OF (thread_id , tsrm_tls_table_size );
173
+ thread_resources = tsrm_tls_table [hash_value ];
174
+
175
+ if (!thread_resources ) {
176
+ allocate_new_resource (& tsrm_tls_table [hash_value ], thread_id );
177
+ thread_resources = tsrm_tls_table [hash_value ];
178
+ } else {
179
+ do {
180
+ if (thread_resources -> thread_id == thread_id ) {
181
+ break ;
182
+ }
183
+ if (thread_resources -> next ) {
184
+ thread_resources = thread_resources -> next ;
185
+ } else {
186
+ allocate_new_resource (& thread_resources -> next , thread_id );
187
+ thread_resources = thread_resources -> next ;
188
+ break ;
189
+ }
190
+ } while (thread_resources );
191
+ }
192
+
193
+ resource = thread_resources -> storage [id ];
194
+
195
+ tsrm_mutex_unlock (tsmm_mutex );
196
+
197
+ tsrm_debug ("Successfully fetched resource id %d for thread id %ld - %x\n" , id , (long ) thread_id , (long ) resource );
198
+ return resource ;
199
+ }
200
+
201
+
202
+ /* frees all resources allocated for the current thread */
203
+ void ts_free_thread ()
204
+ {
205
+ THREAD_T thread_id = tsrm_thread_id ();
206
+ int hash_value ;
207
+ tsrm_tls_entry * thread_resources ;
208
+ tsrm_tls_entry * last = NULL ;
209
+
210
+ tsrm_mutex_lock (tsmm_mutex );
211
+ hash_value = THREAD_HASH_OF (thread_id , tsrm_tls_table_size );
212
+ thread_resources = tsrm_tls_table [hash_value ];
213
+
214
+ while (thread_resources ) {
215
+ if (thread_resources -> thread_id == thread_id ) {
216
+ int i ;
217
+
218
+ for (i = 0 ; i < thread_resources -> count ; i ++ ) {
219
+ resource_types_table [i ].dtor (thread_resources -> storage [i ]);
220
+ free (thread_resources -> storage [i ]);
221
+ }
222
+ free (thread_resources -> storage );
223
+ if (last ) {
224
+ last -> next = thread_resources -> next ;
225
+ } else {
226
+ tsrm_tls_table [hash_value ]= NULL ;
227
+ }
228
+ free (thread_resources );
229
+ break ;
230
+ }
231
+ if (thread_resources -> next ) {
232
+ last = thread_resources ;
233
+ thread_resources = thread_resources -> next ;
234
+ }
235
+ }
236
+ tsrm_mutex_unlock (tsmm_mutex );
237
+ }
238
+
239
+
240
+ /* deallocates all occurrences of a given id */
241
+ void ts_free_id (ts_rsrc_id id )
242
+ {
243
+ }
244
+
245
+
246
+
247
+
248
+ /*
249
+ * Utility Functions
250
+ */
251
+
252
+ /* Obtain the current thread id */
253
+ TSRM_FUNC THREAD_T tsrm_thread_id (void )
254
+ {
255
+ #ifdef WIN32
256
+ return GetCurrentThreadId ();
257
+ #elif defined(PTHREADS )
258
+ return pthread_self ();
259
+ #elif defined(NSAPI )
260
+ return systhread_current ();
261
+ #elif defined(PI3WEB )
262
+ return PIThread_getCurrent ();
263
+ #endif
264
+ }
265
+
266
+
267
+ /* Allocate a mutex */
268
+ TSRM_FUNC MUTEX_T tsrm_mutex_alloc ( void )
269
+ {
270
+ MUTEX_T mutexp ;
271
+
272
+ #ifdef WIN32
273
+ mutexp = CreateMutex (NULL ,FALSE,NULL );
274
+ #elif defined(PTHREADS )
275
+ mutexp = (pthread_mutex_t * )malloc (sizeof (pthread_mutex_t ));
276
+ pthread_mutex_init (mutexp ,NULL );
277
+ #elif defined(NSAPI )
278
+ mutexp = crit_init ();
279
+ #elif defined(PI3WEB )
280
+ mutexp = PIPlatform_allocLocalMutex ();
281
+ #endif
282
+ #ifdef THR_DEBUG
283
+ printf ("Mutex created thread: %d\n" ,mythreadid ());
284
+ #endif
285
+ return ( mutexp );
286
+ }
287
+
288
+
289
+ /* Free a mutex */
290
+ TSRM_FUNC void tsrm_mutex_free ( MUTEX_T mutexp )
291
+ {
292
+ if (mutexp ) {
293
+ #ifdef WIN32
294
+ CloseHandle (mutexp );
295
+ #elif defined(PTHREADS )
296
+ free (mutexp );
297
+ #elif defined(NSAPI )
298
+ crit_terminate (mutexp );
299
+ #elif defined(PI3WEB )
300
+ PISync_delete (mutexp )
301
+ #endif
302
+ }
303
+ #ifdef THR_DEBUG
304
+ printf ("Mutex freed thread: %d\n" ,mythreadid ());
305
+ #endif
306
+ }
307
+
308
+
309
+ /* Lock a mutex */
310
+ TSRM_FUNC int tsrm_mutex_lock ( MUTEX_T mutexp )
311
+ {
312
+ //tsrm_debug("Mutex locked thread: %ld\n",tsrm_thread_id());
313
+ #ifdef WIN32
314
+ return WaitForSingleObject (mutexp ,1000 );
315
+ #elif defined(PTHREADS )
316
+ return pthread_mutex_lock (mutexp );
317
+ #elif defined(NSAPI )
318
+ return crit_enter (mutexp );
319
+ #elif defined(PI3WEB )
320
+ return PISync_lock (mutexp );
321
+ #endif
322
+ }
323
+
324
+
325
+ /* Unlock a mutex */
326
+ TSRM_FUNC int tsrm_mutex_unlock ( MUTEX_T mutexp )
327
+ {
328
+ //tsrm_debug("Mutex unlocked thread: %ld\n",tsrm_thread_id());
329
+ #ifdef WIN32
330
+ return ReleaseMutex (mutexp );
331
+ #elif defined(PTHREADS )
332
+ return pthread_mutex_unlock (mutexp );
333
+ #elif defined(NSAPI )
334
+ return crit_exit (mutexp );
335
+ #elif defined(PI3WEB )
336
+ return PISync_unlock (mutexp );
337
+ #endif
338
+ }
339
+
340
+
341
+ /*
342
+ * Debug support
343
+ */
344
+
345
+ static int tsrm_debug (const char * format , ...)
346
+ {
347
+ if (tsrm_debug_status ) {
348
+ va_list args ;
349
+ int size ;
350
+
351
+ va_start (args , format );
352
+ size = vprintf (format , args );
353
+ va_end (args );
354
+ return size ;
355
+ } else {
356
+ return 0 ;
357
+ }
358
+ }
359
+
360
+
361
+ void tsrm_debug_set (int status )
362
+ {
363
+ tsrm_debug_status = status ;
364
+ }
0 commit comments