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
  22. tsrm_get_ls_cache

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

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