Commit 3e6005c5 authored by Daniel Salzman's avatar Daniel Salzman

stats: replace __sync_* fallbacks with simple implementations to improve portability

The fallback is important for 32-bit systems with an old compiler. In this
case, just one udp and tcp workers should be configured. In general not
a serious problem.
parent 7cccac52
...@@ -59,19 +59,21 @@ const stats_item_t server_stats[] = { ...@@ -59,19 +59,21 @@ const stats_item_t server_stats[] = {
static void dump_counters(FILE *fd, int level, mod_ctr_t *ctr) static void dump_counters(FILE *fd, int level, mod_ctr_t *ctr)
{ {
for (uint32_t j = 0; j < ctr->count; j++) { for (uint32_t j = 0; j < ctr->count; j++) {
uint64_t counter = ATOMIC_GET(ctr->counters[j]);
// Skip empty counters. // Skip empty counters.
if (ctr->counters[j] == 0) { if (counter == 0) {
continue; continue;
} }
if (ctr->idx_to_str != NULL) { if (ctr->idx_to_str != NULL) {
char *str = ctr->idx_to_str(j, ctr->count); char *str = ctr->idx_to_str(j, ctr->count);
if (str != NULL) { if (str != NULL) {
DUMP_CTR(fd, level, "%s", str, ctr->counters[j]); DUMP_CTR(fd, level, "%s", str, counter);
free(str); free(str);
} }
} else { } else {
DUMP_CTR(fd, level, "%u", j, ctr->counters[j]); DUMP_CTR(fd, level, "%u", j, counter);
} }
} }
} }
...@@ -114,7 +116,8 @@ static void dump_modules(dump_ctx_t *ctx) ...@@ -114,7 +116,8 @@ static void dump_modules(dump_ctx_t *ctx)
} }
if (ctr->count == 1) { if (ctr->count == 1) {
// Simple counter. // Simple counter.
DUMP_CTR(ctx->fd, level + 1, "%s", ctr->name, ctr->counter); DUMP_CTR(ctx->fd, level + 1, "%s", ctr->name,
ATOMIC_GET(ctr->counter));
} else { } else {
// Array of counters. // Array of counters.
DUMP_STR(ctx->fd, level + 1, "%s", ctr->name, ""); DUMP_STR(ctx->fd, level + 1, "%s", ctr->name, "");
......
...@@ -1038,7 +1038,8 @@ static int send_stats_ctr(mod_ctr_t *ctr, ctl_args_t *args, knot_ctl_data_t *dat ...@@ -1038,7 +1038,8 @@ static int send_stats_ctr(mod_ctr_t *ctr, ctl_args_t *args, knot_ctl_data_t *dat
char value[32]; char value[32];
if (ctr->count == 1) { if (ctr->count == 1) {
int ret = snprintf(value, sizeof(value), "%"PRIu64, ctr->counter); int ret = snprintf(value, sizeof(value), "%"PRIu64,
ATOMIC_GET(ctr->counter));
if (ret <= 0 || ret >= sizeof(value)) { if (ret <= 0 || ret >= sizeof(value)) {
return KNOT_ESPACE; return KNOT_ESPACE;
} }
...@@ -1055,8 +1056,10 @@ static int send_stats_ctr(mod_ctr_t *ctr, ctl_args_t *args, knot_ctl_data_t *dat ...@@ -1055,8 +1056,10 @@ static int send_stats_ctr(mod_ctr_t *ctr, ctl_args_t *args, knot_ctl_data_t *dat
CTL_FLAG_FORCE); CTL_FLAG_FORCE);
for (uint32_t i = 0; i < ctr->count; i++) { for (uint32_t i = 0; i < ctr->count; i++) {
uint64_t counter = ATOMIC_GET(ctr->counters[i]);
// Skip empty counters. // Skip empty counters.
if (ctr->counters[i] == 0 && !force) { if (counter == 0 && !force) {
continue; continue;
} }
...@@ -1075,8 +1078,7 @@ static int send_stats_ctr(mod_ctr_t *ctr, ctl_args_t *args, knot_ctl_data_t *dat ...@@ -1075,8 +1078,7 @@ static int send_stats_ctr(mod_ctr_t *ctr, ctl_args_t *args, knot_ctl_data_t *dat
return KNOT_ESPACE; return KNOT_ESPACE;
} }
ret = snprintf(value, sizeof(value), "%"PRIu64, ret = snprintf(value, sizeof(value), "%"PRIu64, counter);
ctr->counters[i]);
if (ret <= 0 || ret >= sizeof(value)) { if (ret <= 0 || ret >= sizeof(value)) {
return KNOT_ESPACE; return KNOT_ESPACE;
} }
......
...@@ -29,13 +29,14 @@ ...@@ -29,13 +29,14 @@
#include "contrib/mempattern.h" #include "contrib/mempattern.h"
#ifdef HAVE_ATOMIC #ifdef HAVE_ATOMIC
#define ATOMIC_ADD(dst, val) __atomic_add_fetch(dst, val, __ATOMIC_RELAXED); #define ATOMIC_ADD(dst, val) __atomic_add_fetch(&(dst), (val), __ATOMIC_RELAXED)
#define ATOMIC_SUB(dst, val) __atomic_sub_fetch(dst, val, __ATOMIC_RELAXED); #define ATOMIC_SUB(dst, val) __atomic_sub_fetch(&(dst), (val), __ATOMIC_RELAXED)
#define ATOMIC_SET(dst, val) __atomic_store_n(dst, val, __ATOMIC_RELAXED); #define ATOMIC_SET(dst, val) __atomic_store_n(&(dst), (val), __ATOMIC_RELAXED)
#else #else
#define ATOMIC_ADD(dst, val) __sync_fetch_and_add(dst, val); #warning "Statistics data can be inaccurate if configured with multiple udp/tcp workers"
#define ATOMIC_SUB(dst, val) __sync_fetch_and_sub(dst, val); #define ATOMIC_ADD(dst, val) ((dst) += (val))
#define ATOMIC_SET(dst, val) // TODO: No __sync_* variant. #define ATOMIC_SUB(dst, val) ((dst) -= (val))
#define ATOMIC_SET(dst, val) ((dst) = (val))
#endif #endif
_public_ _public_
...@@ -289,10 +290,10 @@ void knotd_mod_stats_free(knotd_mod_t *mod) ...@@ -289,10 +290,10 @@ void knotd_mod_stats_free(knotd_mod_t *mod)
mod_ctr_t *ctr = mod->stats + ctr_id; \ mod_ctr_t *ctr = mod->stats + ctr_id; \
if (ctr->count == 1) { \ if (ctr->count == 1) { \
assert(idx == 0); \ assert(idx == 0); \
OPERATION(&ctr->counter, val); \ OPERATION(ctr->counter, val); \
} else { \ } else { \
assert(idx < ctr->count); \ assert(idx < ctr->count); \
OPERATION(&ctr->counters[idx], val); \ OPERATION(ctr->counters[idx], val); \
} \ } \
} }
......
...@@ -21,6 +21,12 @@ ...@@ -21,6 +21,12 @@
#include "knot/include/module.h" #include "knot/include/module.h"
#include "contrib/ucw/lists.h" #include "contrib/ucw/lists.h"
#ifdef HAVE_ATOMIC
#define ATOMIC_GET(src) __atomic_load_n(&(src), __ATOMIC_RELAXED)
#else
#define ATOMIC_GET(src) (src)
#endif
#define KNOTD_STAGES (KNOTD_STAGE_END + 1) #define KNOTD_STAGES (KNOTD_STAGE_END + 1)
typedef unsigned (*query_step_process_f) typedef unsigned (*query_step_process_f)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment