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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
From c80892f17e44331206c8318d53b63bb6a99554d0 Mon Sep 17 00:00:00 2001
From: Alexander Kanavin <alex.kanavin@gmail.com>
Date: Tue, 30 May 2017 13:58:30 +0300
Subject: [PATCH 3/4] rpmstrpool.c: make operations over string pools
thread-safe
Otherwise multithreaded rpm building explodes in various ways due
to data races.
Upstream-Status: Submitted [https://github.com/rpm-software-management/rpm/pull/226]
Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com>
---
rpmio/rpmstrpool.c | 56 +++++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 47 insertions(+), 9 deletions(-)
diff --git a/rpmio/rpmstrpool.c b/rpmio/rpmstrpool.c
index 30a57eb10..58ba95a02 100644
--- a/rpmio/rpmstrpool.c
+++ b/rpmio/rpmstrpool.c
@@ -113,6 +113,8 @@ static poolHash poolHashCreate(int numBuckets)
return ht;
}
+static const char * rpmstrPoolStrNoLock(rpmstrPool pool, rpmsid sid);
+
static void poolHashResize(rpmstrPool pool, int numBuckets)
{
poolHash ht = pool->hash;
@@ -120,7 +122,7 @@ static void poolHashResize(rpmstrPool pool, int numBuckets)
for (int i=0; i<ht->numBuckets; i++) {
if (!ht->buckets[i].keyid) continue;
- unsigned int keyHash = rstrhash(rpmstrPoolStr(pool, ht->buckets[i].keyid));
+ unsigned int keyHash = rstrhash(rpmstrPoolStrNoLock(pool, ht->buckets[i].keyid));
for (unsigned int j=0;;j++) {
unsigned int hash = hashbucket(keyHash, j) % numBuckets;
if (!buckets[hash].keyid) {
@@ -149,7 +151,7 @@ static void poolHashAddHEntry(rpmstrPool pool, const char * key, unsigned int ke
ht->buckets[hash].keyid = keyid;
ht->keyCount++;
break;
- } else if (!strcmp(rpmstrPoolStr(pool, ht->buckets[hash].keyid), key)) {
+ } else if (!strcmp(rpmstrPoolStrNoLock(pool, ht->buckets[hash].keyid), key)) {
return;
}
}
@@ -191,7 +193,7 @@ static void poolHashPrintStats(rpmstrPool pool)
int maxcollisions = 0;
for (i=0; i<ht->numBuckets; i++) {
- unsigned int keyHash = rstrhash(rpmstrPoolStr(pool, ht->buckets[i].keyid));
+ unsigned int keyHash = rstrhash(rpmstrPoolStrNoLock(pool, ht->buckets[i].keyid));
for (unsigned int j=0;;j++) {
unsigned int hash = hashbucket(keyHash, i) % ht->numBuckets;
if (hash==i) {
@@ -221,7 +223,7 @@ static void rpmstrPoolRehash(rpmstrPool pool)
pool->hash = poolHashCreate(sizehint);
for (int i = 1; i <= pool->offs_size; i++)
- poolHashAddEntry(pool, rpmstrPoolStr(pool, i), i);
+ poolHashAddEntry(pool, rpmstrPoolStrNoLock(pool, i), i);
}
rpmstrPool rpmstrPoolCreate(void)
@@ -245,6 +247,8 @@ rpmstrPool rpmstrPoolCreate(void)
rpmstrPool rpmstrPoolFree(rpmstrPool pool)
{
+ #pragma omp critical(rpmstrpool)
+ {
if (pool) {
if (pool->nrefs > 1) {
pool->nrefs--;
@@ -260,18 +264,24 @@ rpmstrPool rpmstrPoolFree(rpmstrPool pool)
free(pool);
}
}
+ }
return NULL;
}
rpmstrPool rpmstrPoolLink(rpmstrPool pool)
{
+ #pragma omp critical(rpmstrpool)
+ {
if (pool)
pool->nrefs++;
+ }
return pool;
}
void rpmstrPoolFreeze(rpmstrPool pool, int keephash)
{
+ #pragma omp critical(rpmstrpool)
+ {
if (pool && !pool->frozen) {
if (!keephash) {
pool->hash = poolHashFree(pool->hash);
@@ -281,16 +291,20 @@ void rpmstrPoolFreeze(rpmstrPool pool, int keephash)
pool->offs_alloced * sizeof(*pool->offs));
pool->frozen = 1;
}
+ }
}
void rpmstrPoolUnfreeze(rpmstrPool pool)
{
+ #pragma omp critical(rpmstrpool)
+ {
if (pool) {
if (pool->hash == NULL) {
rpmstrPoolRehash(pool);
}
pool->frozen = 0;
}
+ }
}
static rpmsid rpmstrPoolPut(rpmstrPool pool, const char *s, size_t slen, unsigned int hash)
@@ -350,7 +364,7 @@ static rpmsid rpmstrPoolGet(rpmstrPool pool, const char * key, size_t keylen,
return 0;
}
- s = rpmstrPoolStr(pool, ht->buckets[hash].keyid);
+ s = rpmstrPoolStrNoLock(pool, ht->buckets[hash].keyid);
/* pool string could be longer than keylen, require exact matche */
if (strncmp(s, key, keylen) == 0 && s[keylen] == '\0')
return ht->buckets[hash].keyid;
@@ -373,27 +387,31 @@ static inline rpmsid strn2id(rpmstrPool pool, const char *s, size_t slen,
rpmsid rpmstrPoolIdn(rpmstrPool pool, const char *s, size_t slen, int create)
{
rpmsid sid = 0;
-
+ #pragma omp critical(rpmstrpool)
+ {
if (s != NULL) {
unsigned int hash = rstrnhash(s, slen);
sid = strn2id(pool, s, slen, hash, create);
}
+ }
return sid;
}
rpmsid rpmstrPoolId(rpmstrPool pool, const char *s, int create)
{
rpmsid sid = 0;
-
+ #pragma omp critical(rpmstrpool)
+ {
if (s != NULL) {
size_t slen;
unsigned int hash = rstrlenhash(s, &slen);
sid = strn2id(pool, s, slen, hash, create);
}
+ }
return sid;
}
-const char * rpmstrPoolStr(rpmstrPool pool, rpmsid sid)
+static const char * rpmstrPoolStrNoLock(rpmstrPool pool, rpmsid sid)
{
const char *s = NULL;
if (pool && sid > 0 && sid <= pool->offs_size)
@@ -401,12 +419,25 @@ const char * rpmstrPoolStr(rpmstrPool pool, rpmsid sid)
return s;
}
+const char * rpmstrPoolStr(rpmstrPool pool, rpmsid sid)
+{
+ const char *s = NULL;
+ #pragma omp critical(rpmstrpool)
+ {
+ s = rpmstrPoolStrNoLock(pool, sid);
+ }
+ return s;
+}
+
size_t rpmstrPoolStrlen(rpmstrPool pool, rpmsid sid)
{
size_t slen = 0;
+ #pragma omp critical(rpmstrpool)
+ {
if (pool && sid > 0 && sid <= pool->offs_size) {
slen = strlen(pool->offs[sid]);
}
+ }
return slen;
}
@@ -421,5 +452,12 @@ int rpmstrPoolStreq(rpmstrPool poolA, rpmsid sidA,
rpmsid rpmstrPoolNumStr(rpmstrPool pool)
{
- return (pool != NULL) ? pool->offs_size : 0;
+ rpmsid id = 0;
+ #pragma omp critical(rpmstrpool)
+ {
+ if (pool) {
+ id = pool->offs_size;
+ }
+ }
+ return id;
}
--
2.11.0
|