zebra: do not load/store wider-than-ptr atomics

Most 32-bit architectures cannot do atomic loads and stores of data
wider than their pointer size, i.e. 32 bit.  Funnily enough they
generally *can* do a CAS2, i.e., 64-bit compare-and-swap, but while a
CAS can emulate atomic add/bitops, loads and stores aren't available.

Replace with a mutex;  since this is 99% used from the zserv thread, the
mutex should take the local-to-thread fast path anyway.  And while one
atomic might be faster than a mutex lock/unlock, we're doing several
here, and at some point a mutex wins on speed anyway.

This fixes build on armel, mipsel, m68k, powerpc, and sh4.

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
This commit is contained in:
David Lamparter 2023-01-06 16:55:38 +01:00
parent b15826e81b
commit ccac11096c
2 changed files with 43 additions and 40 deletions

View File

@ -232,14 +232,16 @@ static void zserv_write(struct thread *thread)
struct stream *msg;
uint32_t wcmd = 0;
struct stream_fifo *cache;
uint64_t time_now = monotime(NULL);
/* If we have any data pending, try to flush it first */
switch (buffer_flush_all(client->wb, client->sock)) {
case BUFFER_ERROR:
goto zwrite_fail;
case BUFFER_PENDING:
atomic_store_explicit(&client->last_write_time, monotime(NULL),
memory_order_relaxed);
frr_with_mutex (&client->stats_mtx) {
client->last_write_time = time_now;
}
zserv_client_event(client, ZSERV_CLIENT_WRITE);
return;
case BUFFER_EMPTY:
@ -273,20 +275,19 @@ static void zserv_write(struct thread *thread)
case BUFFER_ERROR:
goto zwrite_fail;
case BUFFER_PENDING:
atomic_store_explicit(&client->last_write_time, monotime(NULL),
memory_order_relaxed);
frr_with_mutex (&client->stats_mtx) {
client->last_write_time = time_now;
}
zserv_client_event(client, ZSERV_CLIENT_WRITE);
return;
case BUFFER_EMPTY:
break;
}
atomic_store_explicit(&client->last_write_cmd, wcmd,
memory_order_relaxed);
atomic_store_explicit(&client->last_write_time, monotime(NULL),
memory_order_relaxed);
frr_with_mutex (&client->stats_mtx) {
client->last_write_cmd = wcmd;
client->last_write_time = time_now;
}
return;
zwrite_fail:
@ -433,11 +434,13 @@ static void zserv_read(struct thread *thread)
}
if (p2p < p2p_orig) {
uint64_t time_now = monotime(NULL);
/* update session statistics */
atomic_store_explicit(&client->last_read_time, monotime(NULL),
memory_order_relaxed);
atomic_store_explicit(&client->last_read_cmd, hdr.command,
memory_order_relaxed);
frr_with_mutex (&client->stats_mtx) {
client->last_read_time = time_now;
client->last_read_cmd = hdr.command;
}
/* publish read packets on client's input queue */
frr_with_mutex (&client->ibuf_mtx) {
@ -631,6 +634,7 @@ static void zserv_client_free(struct zserv *client)
buffer_free(client->wb);
/* Free buffer mutexes */
pthread_mutex_destroy(&client->stats_mtx);
pthread_mutex_destroy(&client->obuf_mtx);
pthread_mutex_destroy(&client->ibuf_mtx);
@ -751,14 +755,13 @@ static struct zserv *zserv_client_create(int sock)
client->obuf_fifo = stream_fifo_new();
client->ibuf_work = stream_new(stream_size);
client->obuf_work = stream_new(stream_size);
client->connect_time = monotime(NULL);
pthread_mutex_init(&client->ibuf_mtx, NULL);
pthread_mutex_init(&client->obuf_mtx, NULL);
pthread_mutex_init(&client->stats_mtx, NULL);
client->wb = buffer_new(0);
TAILQ_INIT(&(client->gr_info_queue));
atomic_store_explicit(&client->connect_time, monotime(NULL),
memory_order_relaxed);
/* Initialize flags */
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
@ -1019,8 +1022,14 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
vty_out(vty, "------------------------ \n");
vty_out(vty, "FD: %d \n", client->sock);
connect_time = (time_t) atomic_load_explicit(&client->connect_time,
memory_order_relaxed);
frr_with_mutex (&client->stats_mtx) {
connect_time = client->connect_time;
last_read_time = client->last_read_time;
last_write_time = client->last_write_time;
last_read_cmd = client->last_read_cmd;
last_write_cmd = client->last_write_cmd;
}
vty_out(vty, "Connect Time: %s \n",
zserv_time_buf(&connect_time, cbuf, ZEBRA_TIME_BUF));
@ -1041,16 +1050,6 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
"Client will %sbe notified about the status of its routes.\n",
client->notify_owner ? "" : "Not ");
last_read_time = (time_t)atomic_load_explicit(&client->last_read_time,
memory_order_relaxed);
last_write_time = (time_t)atomic_load_explicit(&client->last_write_time,
memory_order_relaxed);
last_read_cmd = atomic_load_explicit(&client->last_read_cmd,
memory_order_relaxed);
last_write_cmd = atomic_load_explicit(&client->last_write_cmd,
memory_order_relaxed);
vty_out(vty, "Last Msg Rx Time: %s \n",
zserv_time_buf(&last_read_time, rbuf, ZEBRA_TIME_BUF));
vty_out(vty, "Last Msg Tx Time: %s \n",
@ -1184,12 +1183,11 @@ static void zebra_show_client_brief(struct vty *vty, struct zserv *client)
char wbuf[ZEBRA_TIME_BUF];
time_t connect_time, last_read_time, last_write_time;
connect_time = (time_t)atomic_load_explicit(&client->connect_time,
memory_order_relaxed);
last_read_time = (time_t)atomic_load_explicit(&client->last_read_time,
memory_order_relaxed);
last_write_time = (time_t)atomic_load_explicit(&client->last_write_time,
memory_order_relaxed);
frr_with_mutex (&client->stats_mtx) {
connect_time = client->connect_time;
last_read_time = client->last_read_time;
last_write_time = client->last_write_time;
}
if (client->instance || client->session_id)
snprintfrr(client_string, sizeof(client_string), "%s[%u:%u]",

View File

@ -215,16 +215,21 @@ struct zserv {
* relative to last_read_time.
*/
pthread_mutex_t stats_mtx;
/* BEGIN covered by stats_mtx */
/* monotime of client creation */
_Atomic uint64_t connect_time;
uint64_t connect_time;
/* monotime of last message received */
_Atomic uint64_t last_read_time;
uint64_t last_read_time;
/* monotime of last message sent */
_Atomic uint64_t last_write_time;
uint64_t last_write_time;
/* command code of last message read */
_Atomic uint64_t last_read_cmd;
uint64_t last_read_cmd;
/* command code of last message written */
_Atomic uint64_t last_write_cmd;
uint64_t last_write_cmd;
/* END covered by stats_mtx */
/*
* Number of instances configured with