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[] = {
static void dump_counters(FILE *fd, int level, mod_ctr_t *ctr)
{
for (uint32_t j = 0; j < ctr->count; j++) {
uint64_t counter = ATOMIC_GET(ctr->counters[j]);
// Skip empty counters.
if (ctr->counters[j] == 0) {
if (counter == 0) {
continue;
}
if (ctr->idx_to_str != NULL) {
char *str = ctr->idx_to_str(j, ctr->count);
if (str != NULL) {
DUMP_CTR(fd, level, "%s", str, ctr->counters[j]);
DUMP_CTR(fd, level, "%s", str, counter);
free(str);
}
} 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)
}
if (ctr->count == 1) {
// 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 {
// Array of counters.
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
char value[32];
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)) {
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
CTL_FLAG_FORCE);
for (uint32_t i = 0; i < ctr->count; i++) {
uint64_t counter = ATOMIC_GET(ctr->counters[i]);
// Skip empty counters.
if (ctr->counters[i] == 0 && !force) {
if (counter == 0 && !force) {
continue;
}
......@@ -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;
}
ret = snprintf(value, sizeof(value), "%"PRIu64,
ctr->counters[i]);
ret = snprintf(value, sizeof(value), "%"PRIu64, counter);
if (ret <= 0 || ret >= sizeof(value)) {
return KNOT_ESPACE;
}
......
......@@ -29,13 +29,14 @@
#include "contrib/mempattern.h"
#ifdef HAVE_ATOMIC
#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_SET(dst, val) __atomic_store_n(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_SET(dst, val) __atomic_store_n(&(dst), (val), __ATOMIC_RELAXED)
#else
#define ATOMIC_ADD(dst, val) __sync_fetch_and_add(dst, val);
#define ATOMIC_SUB(dst, val) __sync_fetch_and_sub(dst, val);
#define ATOMIC_SET(dst, val) // TODO: No __sync_* variant.
#warning "Statistics data can be inaccurate if configured with multiple udp/tcp workers"
#define ATOMIC_ADD(dst, val) ((dst) += (val))
#define ATOMIC_SUB(dst, val) ((dst) -= (val))
#define ATOMIC_SET(dst, val) ((dst) = (val))
#endif
_public_
......@@ -289,10 +290,10 @@ void knotd_mod_stats_free(knotd_mod_t *mod)
mod_ctr_t *ctr = mod->stats + ctr_id; \
if (ctr->count == 1) { \
assert(idx == 0); \
OPERATION(&ctr->counter, val); \
OPERATION(ctr->counter, val); \
} else { \
assert(idx < ctr->count); \
OPERATION(&ctr->counters[idx], val); \
OPERATION(ctr->counters[idx], val); \
} \
}
......
......@@ -21,6 +21,12 @@
#include "knot/include/module.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)
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