Annotation of embedaddon/php/TSRM/TSRM.c, revision 1.1.1.1
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | Thread Safe Resource Manager |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1999-2011, Andi Gutmans, Sascha Schumann, Zeev Suraski |
6: | This source file is subject to the TSRM license, that is bundled |
7: | with this package in the file LICENSE |
8: +----------------------------------------------------------------------+
9: | Authors: Zeev Suraski <zeev@zend.com> |
10: +----------------------------------------------------------------------+
11: */
12:
13: #include "TSRM.h"
14:
15: #ifdef ZTS
16:
17: #include <stdio.h>
18:
19: #if HAVE_STDARG_H
20: #include <stdarg.h>
21: #endif
22:
23: typedef struct _tsrm_tls_entry tsrm_tls_entry;
24:
25: struct _tsrm_tls_entry {
26: void **storage;
27: int count;
28: THREAD_T thread_id;
29: tsrm_tls_entry *next;
30: };
31:
32:
33: typedef struct {
34: size_t size;
35: ts_allocate_ctor ctor;
36: ts_allocate_dtor dtor;
37: int done;
38: } tsrm_resource_type;
39:
40:
41: /* The memory manager table */
42: static tsrm_tls_entry **tsrm_tls_table=NULL;
43: static int tsrm_tls_table_size;
44: static ts_rsrc_id id_count;
45:
46: /* The resource sizes table */
47: static tsrm_resource_type *resource_types_table=NULL;
48: static int resource_types_table_size;
49:
50:
51: static MUTEX_T tsmm_mutex; /* thread-safe memory manager mutex */
52:
53: /* New thread handlers */
54: static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler;
55: static tsrm_thread_end_func_t tsrm_new_thread_end_handler;
56:
57: /* Debug support */
58: int tsrm_error(int level, const char *format, ...);
59:
60: /* Read a resource from a thread's resource storage */
61: static int tsrm_error_level;
62: static FILE *tsrm_error_file;
63:
64: #if TSRM_DEBUG
65: #define TSRM_ERROR(args) tsrm_error args
66: #define TSRM_SAFE_RETURN_RSRC(array, offset, range) \
67: { \
68: int unshuffled_offset = TSRM_UNSHUFFLE_RSRC_ID(offset); \
69: \
70: if (offset==0) { \
71: return &array; \
72: } else if ((unshuffled_offset)>=0 && (unshuffled_offset)<(range)) { \
73: TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Successfully fetched resource id %d for thread id %ld - 0x%0.8X", \
74: unshuffled_offset, (long) thread_resources->thread_id, array[unshuffled_offset])); \
75: return array[unshuffled_offset]; \
76: } else { \
77: TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Resource id %d is out of range (%d..%d)", \
78: unshuffled_offset, TSRM_SHUFFLE_RSRC_ID(0), TSRM_SHUFFLE_RSRC_ID(thread_resources->count-1))); \
79: return NULL; \
80: } \
81: }
82: #else
83: #define TSRM_ERROR(args)
84: #define TSRM_SAFE_RETURN_RSRC(array, offset, range) \
85: if (offset==0) { \
86: return &array; \
87: } else { \
88: return array[TSRM_UNSHUFFLE_RSRC_ID(offset)]; \
89: }
90: #endif
91:
92: #if defined(PTHREADS)
93: /* Thread local storage */
94: static pthread_key_t tls_key;
95: # define tsrm_tls_set(what) pthread_setspecific(tls_key, (void*)(what))
96: # define tsrm_tls_get() pthread_getspecific(tls_key)
97:
98: #elif defined(TSRM_ST)
99: static int tls_key;
100: # define tsrm_tls_set(what) st_thread_setspecific(tls_key, (void*)(what))
101: # define tsrm_tls_get() st_thread_getspecific(tls_key)
102:
103: #elif defined(TSRM_WIN32)
104: static DWORD tls_key;
105: # define tsrm_tls_set(what) TlsSetValue(tls_key, (void*)(what))
106: # define tsrm_tls_get() TlsGetValue(tls_key)
107:
108: #elif defined(BETHREADS)
109: static int32 tls_key;
110: # define tsrm_tls_set(what) tls_set(tls_key, (void*)(what))
111: # define tsrm_tls_get() (tsrm_tls_entry*)tls_get(tls_key)
112:
113: #else
114: # define tsrm_tls_set(what)
115: # define tsrm_tls_get() NULL
116: # warning tsrm_set_interpreter_context is probably broken on this platform
117: #endif
118:
119: /* Startup TSRM (call once for the entire process) */
120: TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename)
121: {
122: #if defined(GNUPTH)
123: pth_init();
124: #elif defined(PTHREADS)
125: pthread_key_create( &tls_key, 0 );
126: #elif defined(TSRM_ST)
127: st_init();
128: st_key_create(&tls_key, 0);
129: #elif defined(TSRM_WIN32)
130: tls_key = TlsAlloc();
131: #elif defined(BETHREADS)
132: tls_key = tls_allocate();
133: #endif
134:
135: tsrm_error_file = stderr;
136: tsrm_error_set(debug_level, debug_filename);
137: tsrm_tls_table_size = expected_threads;
138:
139: tsrm_tls_table = (tsrm_tls_entry **) calloc(tsrm_tls_table_size, sizeof(tsrm_tls_entry *));
140: if (!tsrm_tls_table) {
141: TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate TLS table"));
142: return 0;
143: }
144: id_count=0;
145:
146: resource_types_table_size = expected_resources;
147: resource_types_table = (tsrm_resource_type *) calloc(resource_types_table_size, sizeof(tsrm_resource_type));
148: if (!resource_types_table) {
149: TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate resource types table"));
150: free(tsrm_tls_table);
151: tsrm_tls_table = NULL;
152: return 0;
153: }
154:
155: tsmm_mutex = tsrm_mutex_alloc();
156:
157: tsrm_new_thread_begin_handler = tsrm_new_thread_end_handler = NULL;
158:
159: TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Started up TSRM, %d expected threads, %d expected resources", expected_threads, expected_resources));
160: return 1;
161: }
162:
163:
164: /* Shutdown TSRM (call once for the entire process) */
165: TSRM_API void tsrm_shutdown(void)
166: {
167: int i;
168:
169: if (tsrm_tls_table) {
170: for (i=0; i<tsrm_tls_table_size; i++) {
171: tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
172:
173: while (p) {
174: int j;
175:
176: next_p = p->next;
177: for (j=0; j<p->count; j++) {
178: if (p->storage[j]) {
179: if (resource_types_table && !resource_types_table[j].done && resource_types_table[j].dtor) {
180: resource_types_table[j].dtor(p->storage[j], &p->storage);
181: }
182: free(p->storage[j]);
183: }
184: }
185: free(p->storage);
186: free(p);
187: p = next_p;
188: }
189: }
190: free(tsrm_tls_table);
191: tsrm_tls_table = NULL;
192: }
193: if (resource_types_table) {
194: free(resource_types_table);
195: resource_types_table=NULL;
196: }
197: tsrm_mutex_free(tsmm_mutex);
198: tsmm_mutex = NULL;
199: TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Shutdown TSRM"));
200: if (tsrm_error_file!=stderr) {
201: fclose(tsrm_error_file);
202: }
203: #if defined(GNUPTH)
204: pth_kill();
205: #elif defined(PTHREADS)
206: pthread_setspecific(tls_key, 0);
207: pthread_key_delete(tls_key);
208: #elif defined(TSRM_WIN32)
209: TlsFree(tls_key);
210: #endif
211: }
212:
213:
214: /* allocates a new thread-safe-resource id */
215: TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
216: {
217: int i;
218:
219: TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new resource id, %d bytes", size));
220:
221: tsrm_mutex_lock(tsmm_mutex);
222:
223: /* obtain a resource id */
224: *rsrc_id = TSRM_SHUFFLE_RSRC_ID(id_count++);
225: TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtained resource id %d", *rsrc_id));
226:
227: /* store the new resource type in the resource sizes table */
228: if (resource_types_table_size < id_count) {
229: resource_types_table = (tsrm_resource_type *) realloc(resource_types_table, sizeof(tsrm_resource_type)*id_count);
230: if (!resource_types_table) {
231: tsrm_mutex_unlock(tsmm_mutex);
232: TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource"));
233: *rsrc_id = 0;
234: return 0;
235: }
236: resource_types_table_size = id_count;
237: }
238: resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].size = size;
239: resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
240: resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
241: resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0;
242:
243: /* enlarge the arrays for the already active threads */
244: for (i=0; i<tsrm_tls_table_size; i++) {
245: tsrm_tls_entry *p = tsrm_tls_table[i];
246:
247: while (p) {
248: if (p->count < id_count) {
249: int j;
250:
251: p->storage = (void *) realloc(p->storage, sizeof(void *)*id_count);
252: for (j=p->count; j<id_count; j++) {
253: p->storage[j] = (void *) malloc(resource_types_table[j].size);
254: if (resource_types_table[j].ctor) {
255: resource_types_table[j].ctor(p->storage[j], &p->storage);
256: }
257: }
258: p->count = id_count;
259: }
260: p = p->next;
261: }
262: }
263: tsrm_mutex_unlock(tsmm_mutex);
264:
265: TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id));
266: return *rsrc_id;
267: }
268:
269:
270: static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_T thread_id)
271: {
272: int i;
273:
274: TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Creating data structures for thread %x", thread_id));
275: (*thread_resources_ptr) = (tsrm_tls_entry *) malloc(sizeof(tsrm_tls_entry));
276: (*thread_resources_ptr)->storage = (void **) malloc(sizeof(void *)*id_count);
277: (*thread_resources_ptr)->count = id_count;
278: (*thread_resources_ptr)->thread_id = thread_id;
279: (*thread_resources_ptr)->next = NULL;
280:
281: /* Set thread local storage to this new thread resources structure */
282: tsrm_tls_set(*thread_resources_ptr);
283:
284: if (tsrm_new_thread_begin_handler) {
285: tsrm_new_thread_begin_handler(thread_id, &((*thread_resources_ptr)->storage));
286: }
287: for (i=0; i<id_count; i++) {
288: if (resource_types_table[i].done) {
289: (*thread_resources_ptr)->storage[i] = NULL;
290: } else
291: {
292: (*thread_resources_ptr)->storage[i] = (void *) malloc(resource_types_table[i].size);
293: if (resource_types_table[i].ctor) {
294: resource_types_table[i].ctor((*thread_resources_ptr)->storage[i], &(*thread_resources_ptr)->storage);
295: }
296: }
297: }
298:
299: if (tsrm_new_thread_end_handler) {
300: tsrm_new_thread_end_handler(thread_id, &((*thread_resources_ptr)->storage));
301: }
302:
303: tsrm_mutex_unlock(tsmm_mutex);
304: }
305:
306:
307: /* fetches the requested resource for the current thread */
308: TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id)
309: {
310: THREAD_T thread_id;
311: int hash_value;
312: tsrm_tls_entry *thread_resources;
313:
314: #ifdef NETWARE
315: /* The below if loop is added for NetWare to fix an abend while unloading PHP
316: * when an Apache unload command is issued on the system console.
317: * While exiting from PHP, at the end for some reason, this function is called
318: * with tsrm_tls_table = NULL. When this happened, the server abends when
319: * tsrm_tls_table is accessed since it is NULL.
320: */
321: if(tsrm_tls_table) {
322: #endif
323: if (!th_id) {
324: /* Fast path for looking up the resources for the current
325: * thread. Its used by just about every call to
326: * ts_resource_ex(). This avoids the need for a mutex lock
327: * and our hashtable lookup.
328: */
329: thread_resources = tsrm_tls_get();
330:
331: if (thread_resources) {
332: TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for current thread %d", id, (long) thread_resources->thread_id));
333: /* Read a specific resource from the thread's resources.
334: * This is called outside of a mutex, so have to be aware about external
335: * changes to the structure as we read it.
336: */
337: TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
338: }
339: thread_id = tsrm_thread_id();
340: } else {
341: thread_id = *th_id;
342: }
343:
344: TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for thread %ld", id, (long) thread_id));
345: tsrm_mutex_lock(tsmm_mutex);
346:
347: hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
348: thread_resources = tsrm_tls_table[hash_value];
349:
350: if (!thread_resources) {
351: allocate_new_resource(&tsrm_tls_table[hash_value], thread_id);
352: return ts_resource_ex(id, &thread_id);
353: } else {
354: do {
355: if (thread_resources->thread_id == thread_id) {
356: break;
357: }
358: if (thread_resources->next) {
359: thread_resources = thread_resources->next;
360: } else {
361: allocate_new_resource(&thread_resources->next, thread_id);
362: return ts_resource_ex(id, &thread_id);
363: /*
364: * thread_resources = thread_resources->next;
365: * break;
366: */
367: }
368: } while (thread_resources);
369: }
370: tsrm_mutex_unlock(tsmm_mutex);
371: /* Read a specific resource from the thread's resources.
372: * This is called outside of a mutex, so have to be aware about external
373: * changes to the structure as we read it.
374: */
375: TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
376: #ifdef NETWARE
377: } /* if(tsrm_tls_table) */
378: #endif
379: }
380:
381: /* frees an interpreter context. You are responsible for making sure that
382: * it is not linked into the TSRM hash, and not marked as the current interpreter */
383: void tsrm_free_interpreter_context(void *context)
384: {
385: tsrm_tls_entry *next, *thread_resources = (tsrm_tls_entry*)context;
386: int i;
387:
388: while (thread_resources) {
389: next = thread_resources->next;
390:
391: for (i=0; i<thread_resources->count; i++) {
392: if (resource_types_table[i].dtor) {
393: resource_types_table[i].dtor(thread_resources->storage[i], &thread_resources->storage);
394: }
395: }
396: for (i=0; i<thread_resources->count; i++) {
397: free(thread_resources->storage[i]);
398: }
399: free(thread_resources->storage);
400: free(thread_resources);
401: thread_resources = next;
402: }
403: }
404:
405: void *tsrm_set_interpreter_context(void *new_ctx)
406: {
407: tsrm_tls_entry *current;
408:
409: current = tsrm_tls_get();
410:
411: /* TODO: unlink current from the global linked list, and replace it
412: * it with the new context, protected by mutex where/if appropriate */
413:
414: /* Set thread local storage to this new thread resources structure */
415: tsrm_tls_set(new_ctx);
416:
417: /* return old context, so caller can restore it when they're done */
418: return current;
419: }
420:
421:
422: /* allocates a new interpreter context */
423: void *tsrm_new_interpreter_context(void)
424: {
425: tsrm_tls_entry *new_ctx, *current;
426: THREAD_T thread_id;
427:
428: thread_id = tsrm_thread_id();
429: tsrm_mutex_lock(tsmm_mutex);
430:
431: current = tsrm_tls_get();
432:
433: allocate_new_resource(&new_ctx, thread_id);
434:
435: /* switch back to the context that was in use prior to our creation
436: * of the new one */
437: return tsrm_set_interpreter_context(current);
438: }
439:
440:
441: /* frees all resources allocated for the current thread */
442: void ts_free_thread(void)
443: {
444: tsrm_tls_entry *thread_resources;
445: int i;
446: THREAD_T thread_id = tsrm_thread_id();
447: int hash_value;
448: tsrm_tls_entry *last=NULL;
449:
450: tsrm_mutex_lock(tsmm_mutex);
451: hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
452: thread_resources = tsrm_tls_table[hash_value];
453:
454: while (thread_resources) {
455: if (thread_resources->thread_id == thread_id) {
456: for (i=0; i<thread_resources->count; i++) {
457: if (resource_types_table[i].dtor) {
458: resource_types_table[i].dtor(thread_resources->storage[i], &thread_resources->storage);
459: }
460: }
461: for (i=0; i<thread_resources->count; i++) {
462: free(thread_resources->storage[i]);
463: }
464: free(thread_resources->storage);
465: if (last) {
466: last->next = thread_resources->next;
467: } else {
468: tsrm_tls_table[hash_value] = thread_resources->next;
469: }
470: tsrm_tls_set(0);
471: free(thread_resources);
472: break;
473: }
474: if (thread_resources->next) {
475: last = thread_resources;
476: }
477: thread_resources = thread_resources->next;
478: }
479: tsrm_mutex_unlock(tsmm_mutex);
480: }
481:
482:
483: /* frees all resources allocated for all threads except current */
484: void ts_free_worker_threads(void)
485: {
486: tsrm_tls_entry *thread_resources;
487: int i;
488: THREAD_T thread_id = tsrm_thread_id();
489: int hash_value;
490: tsrm_tls_entry *last=NULL;
491:
492: tsrm_mutex_lock(tsmm_mutex);
493: hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
494: thread_resources = tsrm_tls_table[hash_value];
495:
496: while (thread_resources) {
497: if (thread_resources->thread_id != thread_id) {
498: for (i=0; i<thread_resources->count; i++) {
499: if (resource_types_table[i].dtor) {
500: resource_types_table[i].dtor(thread_resources->storage[i], &thread_resources->storage);
501: }
502: }
503: for (i=0; i<thread_resources->count; i++) {
504: free(thread_resources->storage[i]);
505: }
506: free(thread_resources->storage);
507: if (last) {
508: last->next = thread_resources->next;
509: } else {
510: tsrm_tls_table[hash_value] = thread_resources->next;
511: }
512: free(thread_resources);
513: if (last) {
514: thread_resources = last->next;
515: } else {
516: thread_resources = tsrm_tls_table[hash_value];
517: }
518: } else {
519: if (thread_resources->next) {
520: last = thread_resources;
521: }
522: thread_resources = thread_resources->next;
523: }
524: }
525: tsrm_mutex_unlock(tsmm_mutex);
526: }
527:
528:
529: /* deallocates all occurrences of a given id */
530: void ts_free_id(ts_rsrc_id id)
531: {
532: int i;
533: int j = TSRM_UNSHUFFLE_RSRC_ID(id);
534:
535: tsrm_mutex_lock(tsmm_mutex);
536:
537: TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Freeing resource id %d", id));
538:
539: if (tsrm_tls_table) {
540: for (i=0; i<tsrm_tls_table_size; i++) {
541: tsrm_tls_entry *p = tsrm_tls_table[i];
542:
543: while (p) {
544: if (p->count > j && p->storage[j]) {
545: if (resource_types_table && resource_types_table[j].dtor) {
546: resource_types_table[j].dtor(p->storage[j], &p->storage);
547: }
548: free(p->storage[j]);
549: p->storage[j] = NULL;
550: }
551: p = p->next;
552: }
553: }
554: }
555: resource_types_table[j].done = 1;
556:
557: tsrm_mutex_unlock(tsmm_mutex);
558:
559: TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully freed resource id %d", id));
560: }
561:
562:
563:
564:
565: /*
566: * Utility Functions
567: */
568:
569: /* Obtain the current thread id */
570: TSRM_API THREAD_T tsrm_thread_id(void)
571: {
572: #ifdef TSRM_WIN32
573: return GetCurrentThreadId();
574: #elif defined(GNUPTH)
575: return pth_self();
576: #elif defined(PTHREADS)
577: return pthread_self();
578: #elif defined(NSAPI)
579: return systhread_current();
580: #elif defined(PI3WEB)
581: return PIThread_getCurrent();
582: #elif defined(TSRM_ST)
583: return st_thread_self();
584: #elif defined(BETHREADS)
585: return find_thread(NULL);
586: #endif
587: }
588:
589:
590: /* Allocate a mutex */
591: TSRM_API MUTEX_T tsrm_mutex_alloc(void)
592: {
593: MUTEX_T mutexp;
594: #ifdef TSRM_WIN32
595: mutexp = malloc(sizeof(CRITICAL_SECTION));
596: InitializeCriticalSection(mutexp);
597: #elif defined(GNUPTH)
598: mutexp = (MUTEX_T) malloc(sizeof(*mutexp));
599: pth_mutex_init(mutexp);
600: #elif defined(PTHREADS)
601: mutexp = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
602: pthread_mutex_init(mutexp,NULL);
603: #elif defined(NSAPI)
604: mutexp = crit_init();
605: #elif defined(PI3WEB)
606: mutexp = PIPlatform_allocLocalMutex();
607: #elif defined(TSRM_ST)
608: mutexp = st_mutex_new();
609: #elif defined(BETHREADS)
610: mutexp = (beos_ben*)malloc(sizeof(beos_ben));
611: mutexp->ben = 0;
612: mutexp->sem = create_sem(1, "PHP sempahore");
613: #endif
614: #ifdef THR_DEBUG
615: printf("Mutex created thread: %d\n",mythreadid());
616: #endif
617: return( mutexp );
618: }
619:
620:
621: /* Free a mutex */
622: TSRM_API void tsrm_mutex_free(MUTEX_T mutexp)
623: {
624: if (mutexp) {
625: #ifdef TSRM_WIN32
626: DeleteCriticalSection(mutexp);
627: free(mutexp);
628: #elif defined(GNUPTH)
629: free(mutexp);
630: #elif defined(PTHREADS)
631: pthread_mutex_destroy(mutexp);
632: free(mutexp);
633: #elif defined(NSAPI)
634: crit_terminate(mutexp);
635: #elif defined(PI3WEB)
636: PISync_delete(mutexp);
637: #elif defined(TSRM_ST)
638: st_mutex_destroy(mutexp);
639: #elif defined(BETHREADS)
640: delete_sem(mutexp->sem);
641: free(mutexp);
642: #endif
643: }
644: #ifdef THR_DEBUG
645: printf("Mutex freed thread: %d\n",mythreadid());
646: #endif
647: }
648:
649:
650: /*
651: Lock a mutex.
652: A return value of 0 indicates success
653: */
654: TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
655: {
656: TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex locked thread: %ld", tsrm_thread_id()));
657: #ifdef TSRM_WIN32
658: EnterCriticalSection(mutexp);
659: return 0;
660: #elif defined(GNUPTH)
661: if (pth_mutex_acquire(mutexp, 0, NULL)) {
662: return 0;
663: }
664: return -1;
665: #elif defined(PTHREADS)
666: return pthread_mutex_lock(mutexp);
667: #elif defined(NSAPI)
668: crit_enter(mutexp);
669: return 0;
670: #elif defined(PI3WEB)
671: return PISync_lock(mutexp);
672: #elif defined(TSRM_ST)
673: return st_mutex_lock(mutexp);
674: #elif defined(BETHREADS)
675: if (atomic_add(&mutexp->ben, 1) != 0)
676: return acquire_sem(mutexp->sem);
677: return 0;
678: #endif
679: }
680:
681:
682: /*
683: Unlock a mutex.
684: A return value of 0 indicates success
685: */
686: TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
687: {
688: TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex unlocked thread: %ld", tsrm_thread_id()));
689: #ifdef TSRM_WIN32
690: LeaveCriticalSection(mutexp);
691: return 0;
692: #elif defined(GNUPTH)
693: if (pth_mutex_release(mutexp)) {
694: return 0;
695: }
696: return -1;
697: #elif defined(PTHREADS)
698: return pthread_mutex_unlock(mutexp);
699: #elif defined(NSAPI)
700: crit_exit(mutexp);
701: return 0;
702: #elif defined(PI3WEB)
703: return PISync_unlock(mutexp);
704: #elif defined(TSRM_ST)
705: return st_mutex_unlock(mutexp);
706: #elif defined(BETHREADS)
707: if (atomic_add(&mutexp->ben, -1) != 1)
708: return release_sem(mutexp->sem);
709: return 0;
710: #endif
711: }
712:
713:
714: TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler)
715: {
716: void *retval = (void *) tsrm_new_thread_begin_handler;
717:
718: tsrm_new_thread_begin_handler = new_thread_begin_handler;
719: return retval;
720: }
721:
722:
723: TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler)
724: {
725: void *retval = (void *) tsrm_new_thread_end_handler;
726:
727: tsrm_new_thread_end_handler = new_thread_end_handler;
728: return retval;
729: }
730:
731:
732:
733: /*
734: * Debug support
735: */
736:
737: #if TSRM_DEBUG
738: int tsrm_error(int level, const char *format, ...)
739: {
740: if (level<=tsrm_error_level) {
741: va_list args;
742: int size;
743:
744: fprintf(tsrm_error_file, "TSRM: ");
745: va_start(args, format);
746: size = vfprintf(tsrm_error_file, format, args);
747: va_end(args);
748: fprintf(tsrm_error_file, "\n");
749: fflush(tsrm_error_file);
750: return size;
751: } else {
752: return 0;
753: }
754: }
755: #endif
756:
757:
758: void tsrm_error_set(int level, char *debug_filename)
759: {
760: tsrm_error_level = level;
761:
762: #if TSRM_DEBUG
763: if (tsrm_error_file!=stderr) { /* close files opened earlier */
764: fclose(tsrm_error_file);
765: }
766:
767: if (debug_filename) {
768: tsrm_error_file = fopen(debug_filename, "w");
769: if (!tsrm_error_file) {
770: tsrm_error_file = stderr;
771: }
772: } else {
773: tsrm_error_file = stderr;
774: }
775: #endif
776: }
777:
778: #endif /* ZTS */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>