blob: a617ffe6cdc5db4dab7692f99dfb3baed5718a81 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
#include <stdlib.h>
#include <errno.h>
#include "libucd_int.h"
#ifdef HAVE_PTHREAD_H
# include <pthread.h>
#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);
}
|