converted appconfig rwlock to the more efficient mutex, since it uses it only for write locking
Costa Tsaousis committed
May 13, 2016 at 22:00 UTC
2377959d99ccda5e7f6ccf02536276ff1e615ad4
1 file changed
+13
-34
src/appconfig.c
+13
-34
@@ -4,15 +4,6 @@
4
*
5
* 1. Re-write this using DICTIONARY
6
*
7
- * FIXME
8
- * The way it is now, concurrency locking is incomplete!
9
- * It makes sure that only one writes to the structures
10
- * but at the same time there may be unlimited readers.
11
- * This can cause crashes.
12
- *
13
- * Of course, rewriting this to use DICTIONARY instead of
14
- * directly accessing AVL structures, will solve the problem.
15
- *
7
*/
8
9
#ifdef HAVE_CONFIG_H
@@ -29,7 +20,7 @@
20
21
#define CONFIG_FILE_LINE_MAX ((CONFIG_MAX_NAME + CONFIG_MAX_VALUE + 1024) * 2)
22
32
-pthread_rwlock_t config_rwlock = PTHREAD_RWLOCK_INITIALIZER;
23
+pthread_mutex_t config_mutex = PTHREAD_MUTEX_INITIALIZER;
24
25
// ----------------------------------------------------------------------------
26
// definitions
@@ -42,15 +33,14 @@ pthread_rwlock_t config_rwlock = PTHREAD_RWLOCK_INITIALIZER;
33
struct config_value {
34
avl avl; // the index - this has to be first!
35
36
+ uint8_t flags;
37
uint32_t hash; // a simple hash to speed up searching
38
// we first compare hashes, and only if the hashes are equal we do string comparisons
39
40
char *name;
41
char *value;
42
51
- uint8_t flags;
52
-
53
- struct config_value *next;
43
+ struct config_value *next; // config->mutex protects just this
44
};
45
46
struct config {
@@ -61,40 +51,33 @@ struct config {
51
52
char *name;
53
54
+ struct config *next; // gloabl config_mutex protects just this
55
+
56
struct config_value *values;
57
avl_tree_lock values_index;
58
67
- struct config *next;
68
-
69
- pthread_rwlock_t rwlock;
59
+ pthread_mutex_t mutex; // this locks only the writers, to ensure atomic updates
60
+ // readers are protected using the rwlock in avl_tree_lock
61
} *config_root = NULL;
62
63
64
// ----------------------------------------------------------------------------
65
// locking
66
76
-static inline void config_global_read_lock(void) {
77
- pthread_rwlock_rdlock(&config_rwlock);
78
-}
79
-
67
static inline void config_global_write_lock(void) {
81
- pthread_rwlock_wrlock(&config_rwlock);
68
+ pthread_mutex_lock(&config_mutex);
69
}
70
71
static inline void config_global_unlock(void) {
85
- pthread_rwlock_unlock(&config_rwlock);
86
-}
87
-
88
-static inline void config_section_read_lock(struct config *co) {
89
- pthread_rwlock_rdlock(&co->rwlock);
72
+ pthread_mutex_unlock(&config_mutex);
73
}
74
75
static inline void config_section_write_lock(struct config *co) {
93
- pthread_rwlock_wrlock(&co->rwlock);
76
+ pthread_mutex_lock(&co->mutex);
77
}
78
79
static inline void config_section_unlock(struct config *co) {
97
- pthread_rwlock_unlock(&co->rwlock);
80
+ pthread_mutex_unlock(&co->mutex);
81
}
82
83
@@ -171,17 +154,15 @@ static inline struct config *config_section_create(const char *section)
154
155
avl_init_lock(&co->values_index, config_value_compare);
156
174
- config_global_write_lock();
175
-
157
config_index_add(co);
158
159
+ config_global_write_lock();
160
struct config *co2 = config_root;
161
if(co2) {
162
while (co2->next) co2 = co2->next;
163
co2->next = co;
164
}
165
else config_root = co;
184
-
166
config_global_unlock();
167
168
return co;
@@ -205,17 +186,15 @@ static inline struct config_value *config_value_create(struct config *co, const
186
cv->value = strdup(value);
187
if(!cv->value) fatal("Cannot allocate config.value");
188
208
- config_section_write_lock(co);
209
-
189
config_value_index_add(co, cv);
190
191
+ config_section_write_lock(co);
192
struct config_value *cv2 = co->values;
193
if(cv2) {
194
while (cv2->next) cv2 = cv2->next;
195
cv2->next = cv;
196
}
197
else co->values = cv;
218
-
198
config_section_unlock(co);
199
200
return cv;