root/TSRM/TSRM.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tsrm_startup
  2. tsrm_shutdown
  3. ts_allocate_id
  4. allocate_new_resource
  5. ts_resource_ex
  6. tsrm_free_interpreter_context
  7. tsrm_set_interpreter_context
  8. tsrm_new_interpreter_context
  9. ts_free_thread
  10. ts_free_worker_threads
  11. ts_free_id
  12. tsrm_thread_id
  13. tsrm_mutex_alloc
  14. tsrm_mutex_free
  15. tsrm_mutex_lock
  16. tsrm_mutex_unlock
  17. tsrm_sigmask
  18. tsrm_set_new_thread_begin_handler
  19. tsrm_set_new_thread_end_handler
  20. tsrm_error
  21. tsrm_error_set

   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   Changes the signal mask of the calling thread
 715 */
 716 #ifdef HAVE_SIGPROCMASK
 717 TSRM_API int tsrm_sigmask(int how, const sigset_t *set, sigset_t *oldset)
 718 {
 719         TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Changed sigmask in thread: %ld", tsrm_thread_id()));
 720         /* TODO: add support for other APIs */
 721 #ifdef PTHREADS
 722         return pthread_sigmask(how, set, oldset);
 723 #else
 724         return sigprocmask(how, set, oldset);
 725 #endif
 726 }
 727 #endif
 728 
 729 
 730 TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler)
 731 {
 732         void *retval = (void *) tsrm_new_thread_begin_handler;
 733 
 734         tsrm_new_thread_begin_handler = new_thread_begin_handler;
 735         return retval;
 736 }
 737 
 738 
 739 TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler)
 740 {
 741         void *retval = (void *) tsrm_new_thread_end_handler;
 742 
 743         tsrm_new_thread_end_handler = new_thread_end_handler;
 744         return retval;
 745 }
 746 
 747 
 748 
 749 /*
 750  * Debug support
 751  */
 752 
 753 #if TSRM_DEBUG
 754 int tsrm_error(int level, const char *format, ...)
 755 {
 756         if (level<=tsrm_error_level) {
 757                 va_list args;
 758                 int size;
 759 
 760                 fprintf(tsrm_error_file, "TSRM:  ");
 761                 va_start(args, format);
 762                 size = vfprintf(tsrm_error_file, format, args);
 763                 va_end(args);
 764                 fprintf(tsrm_error_file, "\n");
 765                 fflush(tsrm_error_file);
 766                 return size;
 767         } else {
 768                 return 0;
 769         }
 770 }
 771 #endif
 772 
 773 
 774 void tsrm_error_set(int level, char *debug_filename)
 775 {
 776         tsrm_error_level = level;
 777 
 778 #if TSRM_DEBUG
 779         if (tsrm_error_file!=stderr) { /* close files opened earlier */
 780                 fclose(tsrm_error_file);
 781         }
 782 
 783         if (debug_filename) {
 784                 tsrm_error_file = fopen(debug_filename, "w");
 785                 if (!tsrm_error_file) {
 786                         tsrm_error_file = stderr;
 787                 }
 788         } else {
 789                 tsrm_error_file = stderr;
 790         }
 791 #endif
 792 }
 793 
 794 #endif /* ZTS */

/* [<][>][^][v][top][bottom][index][help] */