@cryptotaxi247 / netdata-1 / commits / 2377959d9

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;