Annotation of embedaddon/php/TSRM/TSRM.c, revision 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>