Use atomics to protect libovni process state
Multiple threads may attempt to initialize or finalize the process, so we keep the state stored in an atomic integer to protect against bad usage.
This commit is contained in:
parent
ceaac3bcf0
commit
f6fc166a38
@ -5,6 +5,8 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -19,6 +21,13 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "utlist.h"
|
#include "utlist.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ST_UNINIT = 0,
|
||||||
|
ST_INIT,
|
||||||
|
ST_READY,
|
||||||
|
ST_GONE,
|
||||||
|
};
|
||||||
|
|
||||||
struct ovni_rcpu {
|
struct ovni_rcpu {
|
||||||
int index;
|
int index;
|
||||||
int phyid;
|
int phyid;
|
||||||
@ -73,8 +82,7 @@ struct ovni_rproc {
|
|||||||
int rank;
|
int rank;
|
||||||
int nranks;
|
int nranks;
|
||||||
|
|
||||||
int ready;
|
atomic_int st;
|
||||||
int finished;
|
|
||||||
|
|
||||||
JSON_Value *meta;
|
JSON_Value *meta;
|
||||||
};
|
};
|
||||||
@ -171,8 +179,8 @@ ovni_add_cpu(int index, int phyid)
|
|||||||
if (phyid < 0)
|
if (phyid < 0)
|
||||||
die("cannot use negative CPU id %d", phyid);
|
die("cannot use negative CPU id %d", phyid);
|
||||||
|
|
||||||
if (!rproc.ready)
|
if (rproc.st != ST_READY)
|
||||||
die("process not yet initialized");
|
die("process not ready");
|
||||||
|
|
||||||
if (!rthread.ready)
|
if (!rthread.ready)
|
||||||
die("thread not yet initialized");
|
die("thread not yet initialized");
|
||||||
@ -190,8 +198,8 @@ ovni_add_cpu(int index, int phyid)
|
|||||||
void
|
void
|
||||||
ovni_proc_set_rank(int rank, int nranks)
|
ovni_proc_set_rank(int rank, int nranks)
|
||||||
{
|
{
|
||||||
if (!rproc.ready)
|
if (rproc.st != ST_READY)
|
||||||
die("process not yet initialized");
|
die("process not ready");
|
||||||
|
|
||||||
rproc.rank_set = 1;
|
rproc.rank_set = 1;
|
||||||
rproc.rank = rank;
|
rproc.rank = rank;
|
||||||
@ -237,13 +245,19 @@ create_proc_dir(const char *loom, int pid)
|
|||||||
void
|
void
|
||||||
ovni_proc_init(int app, const char *loom, int pid)
|
ovni_proc_init(int app, const char *loom, int pid)
|
||||||
{
|
{
|
||||||
if (rproc.ready)
|
/* Protect against two threads calling at the same time */
|
||||||
|
int st = ST_UNINIT;
|
||||||
|
bool was_uninit = atomic_compare_exchange_strong(&rproc.st,
|
||||||
|
&st, ST_INIT);
|
||||||
|
|
||||||
|
if (!was_uninit) {
|
||||||
|
if (st == ST_INIT)
|
||||||
|
die("pid %d already being initialized", pid);
|
||||||
|
else if (st == ST_READY)
|
||||||
die("pid %d already initialized", pid);
|
die("pid %d already initialized", pid);
|
||||||
|
else if (st == ST_GONE)
|
||||||
if (rproc.finished)
|
|
||||||
die("pid %d has finished, cannot init again", pid);
|
die("pid %d has finished, cannot init again", pid);
|
||||||
|
}
|
||||||
memset(&rproc, 0, sizeof(rproc));
|
|
||||||
|
|
||||||
if (strlen(loom) >= OVNI_MAX_HOSTNAME)
|
if (strlen(loom) >= OVNI_MAX_HOSTNAME)
|
||||||
die("loom name too long: %s", loom);
|
die("loom name too long: %s", loom);
|
||||||
@ -255,7 +269,7 @@ ovni_proc_init(int app, const char *loom, int pid)
|
|||||||
|
|
||||||
create_proc_dir(loom, pid);
|
create_proc_dir(loom, pid);
|
||||||
|
|
||||||
rproc.ready = 1;
|
rproc.st = ST_READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -353,18 +367,19 @@ try_clean_dir(const char *dir)
|
|||||||
void
|
void
|
||||||
ovni_proc_fini(void)
|
ovni_proc_fini(void)
|
||||||
{
|
{
|
||||||
if (!rproc.ready)
|
/* Protect against two threads calling at the same time */
|
||||||
die("process not initialized");
|
int st = ST_READY;
|
||||||
|
bool was_ready = atomic_compare_exchange_strong(&rproc.st,
|
||||||
|
&st, ST_GONE);
|
||||||
|
|
||||||
|
if (!was_ready)
|
||||||
|
die("process not ready");
|
||||||
|
|
||||||
if (rproc.move_to_final) {
|
if (rproc.move_to_final) {
|
||||||
try_clean_dir(rproc.procdir);
|
try_clean_dir(rproc.procdir);
|
||||||
try_clean_dir(rproc.loomdir);
|
try_clean_dir(rproc.loomdir);
|
||||||
try_clean_dir(rproc.tmpdir);
|
try_clean_dir(rproc.tmpdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark the process no longer ready */
|
|
||||||
rproc.finished = 1;
|
|
||||||
rproc.ready = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -516,8 +531,8 @@ ovni_thread_init(pid_t tid)
|
|||||||
if (tid == 0)
|
if (tid == 0)
|
||||||
die("cannot use tid=%d", tid);
|
die("cannot use tid=%d", tid);
|
||||||
|
|
||||||
if (!rproc.ready)
|
if (rproc.st != ST_READY)
|
||||||
die("process not yet initialized");
|
die("process not ready");
|
||||||
|
|
||||||
memset(&rthread, 0, sizeof(rthread));
|
memset(&rthread, 0, sizeof(rthread));
|
||||||
|
|
||||||
@ -751,8 +766,8 @@ ovni_flush(void)
|
|||||||
if (!rthread.ready)
|
if (!rthread.ready)
|
||||||
die("thread is not initialized");
|
die("thread is not initialized");
|
||||||
|
|
||||||
if (!rproc.ready)
|
if (rproc.st != ST_READY)
|
||||||
die("process is not initialized");
|
die("process not ready");
|
||||||
|
|
||||||
ovni_ev_set_clock(&pre, ovni_clock_now());
|
ovni_ev_set_clock(&pre, ovni_clock_now());
|
||||||
ovni_ev_set_mcv(&pre, "OF[");
|
ovni_ev_set_mcv(&pre, "OF[");
|
||||||
|
Loading…
Reference in New Issue
Block a user