/* * posix_partition.c */ #include #include #include #include #include "private.h" extern void sysheap_suppress_leak_detection(void); extern void sysheap_restore_leak_detection(void); typedef struct _key_data key_data_t; struct _key_data { lub_partition_t *partition; lub_heap_t *local_heap; }; /*-------------------------------------------------------- */ static void lub_posix_partition_destroy_key(void *arg) { key_data_t *key_data = arg; lub_partition_destroy_local_heap(key_data->partition,key_data->local_heap); lub_partition_global_realloc(key_data->partition,(char**)key_data,0,LUB_HEAP_ALIGN_NATIVE); } /*-------------------------------------------------------- */ lub_partition_t * lub_partition_create(const lub_partition_spec_t *spec) { lub_posix_partition_t *this; lub_partition_sysalloc_fn *alloc_fn = spec->sysalloc; if(!alloc_fn) { alloc_fn = malloc; } this = alloc_fn(sizeof(lub_posix_partition_t)); if(this) { lub_posix_partition_init(this,spec); } return &this->m_base; } /*-------------------------------------------------------- */ void lub_posix_partition_init(lub_posix_partition_t *this, const lub_partition_spec_t *spec) { memset(this,sizeof(*this),0); /* initialise the base class */ lub_partition_init(&this->m_base,spec); /* initialise the global mutex */ if(0 != pthread_mutex_init(&this->m_mutex,0)) { perror("pthread_mutex_init() failed!"); } /* initialise the local key */ if(0 != pthread_key_create(&this->m_key, lub_posix_partition_destroy_key)) { perror("pthread_key_create() failed!"); } } /*-------------------------------------------------------- */ void lub_partition_destroy(lub_partition_t *instance) { lub_posix_partition_t *this = (void*)instance; /* finalise the base class */ lub_partition_fini(&this->m_base); /* now clean up the global mutex */ if(0 != pthread_mutex_destroy(&this->m_mutex)) { perror("pthread_mutex_destroy() failed!"); } /* now clean up the local key */ if(0 != pthread_key_delete(this->m_key)) { perror("pthread_key_delete() failed!"); } free(this); } /*-------------------------------------------------------- */ lub_heap_t * lub_partition__get_local_heap(lub_partition_t *instance) { lub_heap_t *result = 0; lub_posix_partition_t *this = (void*)instance; key_data_t *key_data = pthread_getspecific(this->m_key); if(key_data) { result = key_data->local_heap; } return result; } /*-------------------------------------------------------- */ void lub_partition__set_local_heap(lub_partition_t *instance, lub_heap_t *heap) { lub_posix_partition_t *this = (void*)instance; key_data_t *key_data = 0; #if defined(__CYGWIN__) /* cygwin seems to leak key_data!!! so we ignore this for the time being... */ lub_heap_leak_suppress_detection(instance->m_global_heap); #endif /* __CYGWIN__*/ lub_partition_global_realloc(instance,(char**)&key_data,sizeof(key_data_t),LUB_HEAP_ALIGN_NATIVE); #if defined(__CYGWIN__) /* cygwin seems to leak key_data!!! so we ignore this for the time being... */ lub_heap_leak_restore_detection(instance->m_global_heap); #endif /* __CYGWIN__*/ assert(key_data); key_data->partition = instance; key_data->local_heap = heap; if(0 != pthread_getspecific(this->m_key)) { assert(NULL == "Local heap already exists!"); } if(0 != pthread_setspecific(this->m_key,key_data)) { perror("pthread_setspecific() failed!"); } } /*-------------------------------------------------------- */ void lub_partition_lock(lub_partition_t *instance) { lub_posix_partition_t *this = (void*)instance; if(0 != pthread_mutex_lock(&this->m_mutex)) { perror("pthread_mutex_lock() failed!"); } } /*-------------------------------------------------------- */ void lub_partition_unlock(lub_partition_t *instance) { lub_posix_partition_t *this = (void*)instance; if(0 != pthread_mutex_unlock(&this->m_mutex)) { perror("pthread_mutex_unlock() failed!"); } } /*-------------------------------------------------------- */