Annotation of embedaddon/php/TSRM/TSRM.c, revision 1.1.1.2

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: 
1.1.1.2 ! misho     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: 
1.1       misho     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 */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>