From: Alberto Leiva Popper Date: Thu, 16 May 2019 18:40:45 +0000 (-0500) Subject: Fix atomic reference counter TODO X-Git-Tag: v0.0.2~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=739e61c56e0a462cf4e75cb340bc6ce5677161a0;p=thirdparty%2FFORT-validator.git Fix atomic reference counter TODO I couldn't find a viable way to multithreadedly manage deltas without reference counters, and sig_atomic_t doesn't look portable to me. So I decided to use C11 atomic types. Upgrades the language standard from gnu99 to gnu11. --- diff --git a/src/Makefile.am b/src/Makefile.am index a41a1bfa..40a8d9b1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -96,7 +96,7 @@ fort_SOURCES += slurm/slurm_parser.c slurm/slurm_parser.h fort_CFLAGS = -Wall # Feel free to temporarily remove this one if you're not using gcc 7.3.0. #fort_CFLAGS += $(GCC_WARNS) -fort_CFLAGS += -std=gnu99 -O0 -g $(CFLAGS_DEBUG) +fort_CFLAGS += -std=gnu11 -O0 -g $(CFLAGS_DEBUG) fort_LDFLAGS = $(LDFLAGS_DEBUG) fort_LDADD = ${JANSSON_LIBS} diff --git a/src/abbreviations.txt b/src/abbreviations.txt index 92263bc1..6cab74cd 100644 --- a/src/abbreviations.txt +++ b/src/abbreviations.txt @@ -20,6 +20,8 @@ msg: message pdu: Protocol Data Unit (RFC 6810) pr: print ptr: pointer +refget: reference get (+1 to reference counter) +refput: reference put (-1 to reference counter) str: string tmp: temporal uint: unsigned int diff --git a/src/rtr/db/delta.c b/src/rtr/db/delta.c index 3bcc1c5d..7ffe0790 100644 --- a/src/rtr/db/delta.c +++ b/src/rtr/db/delta.c @@ -1,5 +1,6 @@ #include "rtr/db/delta.h" +#include #include "data_structure/array_list.h" struct delta_v4 { @@ -27,8 +28,7 @@ struct deltas { struct deltas_v6 removes; } v6; - /* TODO (now) atomic */ - unsigned int references; + atomic_uint references; }; int @@ -44,23 +44,26 @@ deltas_create(struct deltas **_result) deltas_v4_init(&result->v4.removes); deltas_v6_init(&result->v6.adds); deltas_v6_init(&result->v6.removes); - result->references = 1; + atomic_init(&result->references, 1); *_result = result; return 0; } void -deltas_get(struct deltas *deltas) +deltas_refget(struct deltas *deltas) { - deltas->references++; + atomic_fetch_add(&deltas->references, 1); } void -deltas_put(struct deltas *deltas) +deltas_refput(struct deltas *deltas) { - deltas->references--; - if (deltas->references == 0) { + /* + * Reminder: atomic_fetch_sub() returns the previous value, not the + * resulting one. + */ + if (atomic_fetch_sub(&deltas->references, 1) == 1) { deltas_v4_cleanup(&deltas->v4.adds, NULL); deltas_v4_cleanup(&deltas->v4.removes, NULL); deltas_v6_cleanup(&deltas->v6.adds, NULL); diff --git a/src/rtr/db/delta.h b/src/rtr/db/delta.h index 1d2a0701..a3d66ae6 100644 --- a/src/rtr/db/delta.h +++ b/src/rtr/db/delta.h @@ -7,8 +7,8 @@ struct deltas; int deltas_create(struct deltas **); -void deltas_get(struct deltas *); -void deltas_put(struct deltas *); +void deltas_refget(struct deltas *); +void deltas_refput(struct deltas *); int deltas_add_roa_v4(struct deltas *, uint32_t, struct v4_address *, int); int deltas_add_roa_v6(struct deltas *, uint32_t, struct v6_address *, int); diff --git a/src/rtr/db/roa_table.c b/src/rtr/db/roa_table.c index bf4c012d..5e7df96b 100644 --- a/src/rtr/db/roa_table.c +++ b/src/rtr/db/roa_table.c @@ -269,6 +269,6 @@ compute_deltas(struct roa_table *old, struct roa_table *new, return 0; fail: - deltas_put(deltas); + deltas_refput(deltas); return error; } diff --git a/src/rtr/db/vrps.c b/src/rtr/db/vrps.c index 7a290b62..b32296c2 100644 --- a/src/rtr/db/vrps.c +++ b/src/rtr/db/vrps.c @@ -48,7 +48,7 @@ static pthread_rwlock_t lock; void deltagroup_cleanup(struct delta_group *group) { - deltas_put(group->deltas); + deltas_refput(group->deltas); } int @@ -173,7 +173,7 @@ resize_deltas_db(struct deltas_db *db, struct delta_group *start) memcpy(tmp, start, db->len * sizeof(struct delta_group)); /* Release memory allocated */ for (ptr = db->array; ptr < start; ptr++) - deltas_put(ptr->deltas); + deltas_refput(ptr->deltas); free(db->array); db->array = tmp; } @@ -187,12 +187,12 @@ vrps_purge(void) min_serial = clients_get_min_serial(); - /** Assume is ordered by serial, so get the new initial pointer */ + /* Assume is ordered by serial, so get the new initial pointer */ ARRAYLIST_FOREACH(&state.deltas, group, i) if (group->serial >= min_serial) break; - /** Is the first element or reached end, nothing to purge */ + /* Is the first element or reached end, nothing to purge */ if (group == state.deltas.array || (group - state.deltas.array) == state.deltas.len) return; @@ -251,7 +251,7 @@ vrps_update(bool *changed) */ old_base = state.base; - /** Remove unnecessary deltas */ + /* Remove unnecessary deltas */ vrps_purge(); } else { @@ -287,7 +287,7 @@ vrps_update(bool *changed) return 0; revert_deltas: - deltas_put(deltas); + deltas_refput(deltas); revert_base: roa_table_destroy(new_base); return error; @@ -369,7 +369,7 @@ vrps_get_deltas_from(serial_t from, serial_t *to, struct deltas_db *result) return error; } - deltas_get(group->deltas); + deltas_refget(group->deltas); *to = group->serial; }