#include #include #include "libucd_int.h" #ifdef HAVE_PTHREAD_H # include #endif #include "gen/cache.c" #ifdef HAVE_PTHREAD_H static void lock_cache(struct cache_row *r) { pthread_mutex_lock(&r->mutex); } static void unlock_cache(struct cache_row *r) { pthread_mutex_unlock(&r->mutex); } #else /* Single-threaded execution only */ static void lock_cache(struct cache_row *r) { (void)r; } static void unlock_cache(struct cache_row *r) { (void)r; } #endif #if defined(HAVE_PTHREAD_H) && (defined(__i386__) || defined(__x86_64__)) /* Specially optimized versions for i386 and x86-64 */ const struct unicode_character_data * unicode_character_get(const struct unicode_character_data *ucd) { struct libucd_private *pvt = (struct libucd_private *)(ucd+1); asm volatile("lock ; incl %0" : "+m" (pvt->usage_ctr)); return ucd; } void unicode_character_put(const struct unicode_character_data *ucd) { struct libucd_private *pvt = (struct libucd_private *)(ucd+1); unsigned char zero; asm volatile("lock ; decl %0 ; setz %1" : "+m" (pvt->usage_ctr), "=r" (zero)); if ( zero ) free((void *)ucd); } #else # ifdef HAVE_PTHREAD_H static void lock(struct libucd_private *pvt) { pthread_mutex_lock(&pvt->mutex); } static void unlock(struct libucd_private *pvt) { pthread_mutex_unlock(&pvt->mutex); } # else static void lock(struct libucd_private *pvt) { } static void unlock(struct libucd_private *pvt) { } # endif const struct unicode_character_data * unicode_character_get(const struct unicode_character_data *ucd) { struct libucd_private *pvt = (struct libucd_private *)(ucd+1); lock(pvt); pvt->usage_ctr++; unlock(pvt); return ucd; } void unicode_character_put(const struct unicode_character_data *ucd) { struct libucd_private *pvt = (struct libucd_private *)(ucd+1); unsigned int cnt; lock(pvt); cnt = --pvt->usage_ctr; unlock(pvt); if ( !cnt ) free(ucd); } #endif const struct unicode_character_data * unicode_character_data(int32_t ucs) { const struct unicode_character_data *ucd; struct cache_row *row; if ( unlikely((uint32_t)ucs > UCS_MAX) ) { errno = EINVAL; return NULL; } row = &libucd_cache[(uint32_t)ucs % CACHE_ROWS]; RETURN_ENTRY(ucs, row); }