Commit 5116833f authored by Adam Wujek's avatar Adam Wujek 💬

Merge branch 'adam-shmem'

Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parents d8a817b8 77d598e4
......@@ -32,7 +32,8 @@ struct wrs_shm_head {
int pid; /* The current pid owning the area */
unsigned pidsequence; /* Each new pid must increments this */
unsigned sequence; /* If we need consistency, this is it */
unsigned sequence; /* If we need consistency, this is it. LSB bit
* informs whether shmem is locked already */
unsigned version; /* Version of the data structure */
unsigned data_size; /* Size of it (for binary dumps) */
};
......@@ -42,6 +43,14 @@ struct wrs_shm_head {
#define WRS_SHM_WRITE 0x0001
#define WRS_SHM_LOCKED 0x0002 /* at init time: writers locks, readers wait */
#define WRS_SHM_LOCK_MASK 0x0001
/* return values of wrs_shm_get_and_check */
#define WRS_SHM_OPEN_OK 0x0001
#define WRS_SHM_OPEN_FAILED 0x0001
#define WRS_SHM_WRONG_VERSION 0x0002
#define WRS_SHM_INCONSISTENT_DATA 0x0003
/* Set custom path for shmem */
void wrs_shm_set_path(char *new_path);
......@@ -52,33 +61,40 @@ void wrs_shm_set_path(char *new_path);
void wrs_shm_ignore_flag_locked(int ignore_flag);
/* get vs. put, like in the kernel. Errors are in errno (see source) */
void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags);
int wrs_shm_put(void *headptr);
struct wrs_shm_head *wrs_shm_get(enum wrs_shm_name name_id, char *name,
unsigned long flags);
int wrs_shm_put(struct wrs_shm_head *head);
/* A reader may wait for the writer (polling on version field) */
void wrs_shm_wait(void *headptr, int msec_step, int retries, FILE *msg);
void wrs_shm_wait(struct wrs_shm_head *head, int msec_step, int retries,
FILE *msg);
int wrs_shm_get_and_check(enum wrs_shm_name shm_name,
struct wrs_shm_head **head);
/* The writer can allocate structures that live in the area itself */
void *wrs_shm_alloc(void *headptr, size_t size);
void *wrs_shm_alloc(struct wrs_shm_head *head, size_t size);
/* The reader can track writer's pointers, if they are in the area */
void *wrs_shm_follow(void *headptr, void *ptr);
void *wrs_shm_follow(struct wrs_shm_head *head, void *ptr);
/* Before and after writing a chunk of data, act on sequence and stamp */
#define WRS_SHM_WRITE_BEGIN 1
#define WRS_SHM_WRITE_END 0
extern void wrs_shm_write(void *headptr, int flags);
/* A helper to pass the name of caller function */
#define wrs_shm_write(headptr, flags) wrs_shm_write_caller(headptr, flags, \
__func__)
extern void wrs_shm_write_caller(struct wrs_shm_head *head, int flags,
const char *caller);
/* A reader can rely on the sequence number (in the <linux/seqlock.h> way) */
extern unsigned wrs_shm_seqbegin(void *headptr);
extern int wrs_shm_seqretry(void *headptr, unsigned start);
extern unsigned wrs_shm_seqbegin(struct wrs_shm_head *head);
extern int wrs_shm_seqretry(struct wrs_shm_head *head, unsigned start);
/* A reader can check wether information is current enough */
extern int wrs_shm_age(void *headptr);
extern int wrs_shm_age(struct wrs_shm_head *head);
/* A reader can get the information pointer, for a specific version, or NULL */
extern void *wrs_shm_data(void *headptr, unsigned version);
extern void *wrs_shm_data(struct wrs_shm_head *head, unsigned version);
#endif /* __WRS_SHM_H__ */
......@@ -12,6 +12,7 @@
#include <libwr/shmem.h>
#include <libwr/util.h>
#include <libwr/wrs-msg.h>
#define SHM_LOCK_TIMEOUT_MS 50 /* in ms */
......@@ -38,7 +39,8 @@ void wrs_shm_ignore_flag_locked(int ignore_flag)
/* Get wrs shared memory */
/* return NULL and set errno on error */
void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags)
struct wrs_shm_head *wrs_shm_get(enum wrs_shm_name name_id, char *name,
unsigned long flags)
{
struct wrs_shm_head *head;
struct stat stbuf;
......@@ -119,20 +121,19 @@ void *wrs_shm_get(enum wrs_shm_name name_id, char *name, unsigned long flags)
head->pidsequence++;
/* version and size are up to the user (or to allocation) */
return map;
return (struct wrs_shm_head *) map;
}
/* Put wrs shared memory */
/* return 0 on success, !0 on error */
int wrs_shm_put(void *headptr)
int wrs_shm_put(struct wrs_shm_head *head)
{
struct wrs_shm_head *head = headptr;
int err;
if (head->pid == getpid()) {
head->pid = 0; /* mark that we are not writers any more */
close(head->fd);
}
if ((err = munmap(headptr, WRS_SHM_MAX_SIZE)) < 0)
if ((err = munmap(head, WRS_SHM_MAX_SIZE)) < 0)
return err;
return 0;
}
......@@ -140,25 +141,33 @@ int wrs_shm_put(void *headptr)
/* Open shmem and check if data is available
* return 0 when ok, otherwise error
* 1 when openning shmem failed
* 2 when version is 0 */
* 2 when version is 0
* 3 when data in shmem is inconsistent, function shall be called again
*/
int wrs_shm_get_and_check(enum wrs_shm_name shm_name,
struct wrs_shm_head **head)
{
int ii;
int version;
int ret;
/* try to open shmem */
if (!(*head) && !(*head = wrs_shm_get(shm_name, "",
WRS_SHM_READ | WRS_SHM_LOCKED))) {
return 1;
return WRS_SHM_OPEN_FAILED;
}
ii = wrs_shm_seqbegin(*head);
/* read head version */
version = (*head)->version;
if (wrs_shm_seqretry(*head, ii) || !version) {
/* data in shmem available and version not zero */
return 2;
ret = wrs_shm_seqretry(*head, ii);
if (ret) {
/* inconsistent data in shmem */
return WRS_SHM_INCONSISTENT_DATA;
}
if (!version) {
/* data in shmem available and version is zero */
return WRS_SHM_WRONG_VERSION;
}
/* all ok */
......@@ -166,9 +175,9 @@ int wrs_shm_get_and_check(enum wrs_shm_name shm_name,
}
/* The writer can allocate structures that live in the area itself */
void *wrs_shm_alloc(void *headptr, size_t size)
void *wrs_shm_alloc(struct wrs_shm_head *head, size_t size)
{
struct wrs_shm_head *head = headptr;
void *headptr = (void *) head;
void *nextptr;
if (head->pid != getpid())
......@@ -187,59 +196,77 @@ void *wrs_shm_alloc(void *headptr, size_t size)
}
/* The reader can track writer's pointers, if they are in the area */
void *wrs_shm_follow(void *headptr, void *ptr)
void *wrs_shm_follow(struct wrs_shm_head *head, void *ptr)
{
struct wrs_shm_head *head = headptr;
void *headptr = (void *) head;
if (ptr < head->mapbase || ptr > head->mapbase + WRS_SHM_MAX_SIZE)
return NULL; /* not in the area */
return headptr + (ptr - head->mapbase);
}
/* Before and after writing a chunk of data, act on sequence and stamp */
void wrs_shm_write(void *headptr, int flags)
void wrs_shm_write_caller(struct wrs_shm_head *head, int flags,
const char *caller)
{
struct wrs_shm_head *head = headptr;
char *msg = "Wrong parameter";
if (flags == WRS_SHM_WRITE_BEGIN) {
msg = "write begin";
}
if (flags == WRS_SHM_WRITE_END) {
msg = "write end";
}
pr_debug("caller of a function wrs_shm_write is %s, called for \"%s\" "
"with the flag \"%s\"\n", caller, head->name, msg);
head->sequence += 2;
if (flags == WRS_SHM_WRITE_BEGIN) {
if (head->sequence & WRS_SHM_LOCK_MASK)
pr_error("Trying to lock already locked shmem on the "
"write end! Sequence number is %d. The caller"
" of wrs_shm_write is %s\n",
head->sequence, caller);
head->sequence |= WRS_SHM_LOCK_MASK;
}
if (flags == WRS_SHM_WRITE_END) {
/* At end-of-writing update the timestamp too */
head->stamp = get_monotonic_sec();
if (!(head->sequence & WRS_SHM_LOCK_MASK))
pr_error("Trying to unlock already unlocked shmem on "
"the write begin! Sequence number is %d. The "
"caller of wrs_shm_write is %s\n",
head->sequence, caller);
head->sequence &= ~WRS_SHM_LOCK_MASK;
}
head->sequence++;
return;
}
/* A reader can rely on the sequence number (in the <linux/seqlock.h> way) */
unsigned wrs_shm_seqbegin(void *headptr)
unsigned wrs_shm_seqbegin(struct wrs_shm_head *head)
{
struct wrs_shm_head *head = headptr;
return head->sequence;
}
int wrs_shm_seqretry(void *headptr, unsigned start)
int wrs_shm_seqretry(struct wrs_shm_head *head, unsigned start)
{
struct wrs_shm_head *head = headptr;
if (start & 1)
if (start & WRS_SHM_LOCK_MASK)
return 1; /* it was odd: retry */
return head->sequence != start;
}
/* A reader can check wether information is current enough */
int wrs_shm_age(void *headptr)
int wrs_shm_age(struct wrs_shm_head *head)
{
struct wrs_shm_head *head = headptr;
return get_monotonic_sec() - head->stamp;
}
/* A reader can get the information pointer, for a specific version, or NULL */
void *wrs_shm_data(void *headptr, unsigned version)
void *wrs_shm_data(struct wrs_shm_head *head, unsigned version)
{
struct wrs_shm_head *head = headptr;
void *headptr = (void *) head;
if (head->version != version)
return NULL;
......
ppsi @ 96a78e15
Subproject commit ab7106d253d8d1a3651b8a5cb354a5dcd4ca1b63
Subproject commit 96a78e152aed8fda5cbcaa91b1b6bce4a685b958
......@@ -30,12 +30,16 @@ static int init_shm_hald(void)
n_wait++;
/* start printing error after 5 messages */
if (n_wait > 5) {
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
snmp_log(LOG_ERR, "Unable to open HAL's shmem!\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
snmp_log(LOG_ERR, "Unable to read HAL's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
snmp_log(LOG_ERR, "Unable to read consistent data from"
" HAL's shmem!\n");
}
}
if (ret) {
/* return if error while opening shmem */
......@@ -82,12 +86,16 @@ static int init_shm_ppsi(void)
/* start printing error after 5 messages */
if (n_wait > 5) {
/* timeout! */
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
snmp_log(LOG_ERR, "Unable to open shm for PPSI!\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
snmp_log(LOG_ERR, "Unable to read PPSI's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
snmp_log(LOG_ERR, "Unable to read consistent data from"
" PPSI's shmem!\n");
}
}
if (ret) {
/* return if error while opening shmem */
......@@ -128,12 +136,16 @@ static int init_shm_rtud(void)
n_wait++;
/* start printing error after 5 messages */
if (n_wait > 5) {
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
snmp_log(LOG_ERR, "Unable to open shm for RTUd!\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
snmp_log(LOG_ERR, "Unable to read RTUd's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
snmp_log(LOG_ERR, "Unable to read consistent data from"
" RTUd's shmem!\n");
}
}
if (ret) {
/* return if error while opening shmem */
......
......@@ -205,14 +205,18 @@ int get_nports_from_hal(void)
while ((ret = wrs_shm_get_and_check(wrs_shm_hal, &hal_head)) != 0) {
n_wait++;
if (n_wait > 10) {
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
fprintf(stderr, "rtu_stat: Unable to open "
"HAL's shm !\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
fprintf(stderr, "rtu_stat: Unable to read "
"HAL's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
fprintf(stderr, "rtu_stat: Unable to read "
"consistent data from HAL's shmem!\n");
}
exit(1);
}
sleep(1);
......@@ -329,14 +333,19 @@ int open_rtu_shm(void)
while ((ret = wrs_shm_get_and_check(wrs_shm_rtu, &rtu_port_shmem)) != 0) {
n_wait++;
if (n_wait > 10) {
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
fprintf(stderr, "rtu_stat: Unable to open "
"RTUd's shm !\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
fprintf(stderr, "rtu_stat: Unable to read "
"RTUd's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
fprintf(stderr, "rtu_stat: Unable to read "
"consistent data from RTUd's shmem!\n"
);
}
exit(1);
}
sleep(1);
......
......@@ -184,12 +184,16 @@ void init_shm(void)
int n_wait = 0;
while ((ret = wrs_shm_get_and_check(wrs_shm_hal, &hal_head)) != 0) {
n_wait++;
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
pr_error("Unable to open HAL's shm !\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
pr_error("Unable to read HAL's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
pr_error("Unable to read consistent data from HAL's "
"shmem!\n");
}
if (n_wait > 10) {
/* timeout! */
exit(-1);
......@@ -224,12 +228,16 @@ void init_shm(void)
n_wait = 0;
while ((ret = wrs_shm_get_and_check(wrs_shm_ptp, &ppsi_head)) != 0) {
n_wait++;
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
pr_error("Unable to open PPSI's shm !\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
pr_error("Unable to read PPSI's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
pr_error("Unable to read consistent data from PPSI's "
"shmem!\n");
}
if (n_wait > 10) {
/* timeout! */
exit(-1);
......
......@@ -65,14 +65,18 @@ int hal_shm_init(void)
while ((ret = wrs_shm_get_and_check(wrs_shm_hal, &hal_head)) != 0) {
n_wait++;
if (n_wait > 10) {
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
fprintf(stderr, "wr_phytool: Unable to open "
"HAL's shm !\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
fprintf(stderr, "wr_phytool: Unable to read "
"HAL's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
fprintf(stderr, "wr_phytool: Unable to read "
"consistent data from HAL's shmem!\n");
}
return(-1);
}
sleep(1);
......
......@@ -234,12 +234,16 @@ void hal_init_shm(void)
int n_wait = 0;
while ((ret = wrs_shm_get_and_check(wrs_shm_hal, &hal_head)) != 0) {
n_wait++;
if (ret == 1) {
pr_error("Unable to open HAL's shm !\n");
if (ret == WRS_SHM_OPEN_FAILED) {
pr_error("Unable to open HAL's shmem !\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
pr_error("Unable to read HAL's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
pr_error("Unable to read consistent data from HAL's "
"shmem!\n");
}
if (n_wait > 10) {
/* timeout! */
exit(1);
......
......@@ -192,12 +192,16 @@ int main(int argc, char *argv[])
while ((ret = wrs_shm_get_and_check(wrs_shm_rtu, &rtu_port_shmem)) != 0) {
n_wait++;
if (n_wait > 10) {
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
pr_error("Unable to open RTUd's shmem!\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
pr_error("Unable to read RTUd's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
pr_error("Unable to read consistent data from "
"RTUd's shmem!\n");
}
exit(1);
}
sleep(1);
......
......@@ -61,12 +61,16 @@ int get_nports_from_hal(void)
while ((ret = wrs_shm_get_and_check(wrs_shm_hal, &hal_head)) != 0) {
n_wait++;
if (n_wait > 10) {
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
pr_error("Unable to open HAL's shmem!\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
pr_error("Unable to read HAL's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
pr_error("Unable to read consistent data from "
"HAL's shmem!\n");
}
exit(1);
}
sleep(1);
......
......@@ -16,6 +16,7 @@
#include <libwr/shw_io.h>
#include <libwr/sfp_lib.h>
#include <libwr/config.h>
#include <libwr/shmem.h>
#include <libwr/hal_shmem.h>
#include <libwr/util.h>
......@@ -31,6 +32,7 @@ static char *logfilename;
static char *dotconfigname = "/wr/etc/dot-config";
struct hal_shmem_header *hal_shmem;
struct wrs_shm_head *hal_shmem_hdr;
/* Adds a function to be called during the HAL shutdown. */
int hal_add_cleanup_callback(hal_cleanup_callback_t cb)
......@@ -222,7 +224,7 @@ static void hal_parse_cmdline(int argc, char *argv[])
int main(int argc, char *argv[])
{
uint64_t t1, t2;
struct hal_temp_sensors temp_sensors; /* local copy of temperatures */
wrs_msg_init(argc, argv);
/* Print HAL's version */
......@@ -264,8 +266,13 @@ int main(int argc, char *argv[])
continue;
hal_port_update_all();
/* update fans and temperatures in shmem */
shw_update_fans(&hal_shmem->temp);
/* Update fans and get temperatures values. Don't write
* temperatures directly to the shmem to reduce the critical
* section of shmem */
shw_update_fans(&temp_sensors);
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_BEGIN);
memcpy(&hal_shmem->temp, &temp_sensors, sizeof(temp_sensors));
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_END);
t1 = t2;
}
......
......@@ -34,6 +34,7 @@
#define SFP_POLL_INTERVAL 1000 /* ms */
extern struct hal_shmem_header *hal_shmem;
extern struct wrs_shm_head *hal_shmem_hdr;
/* Port table: the only item which is not "hal_port_*", as it's much used */
static struct hal_port_state *ports;
......@@ -210,8 +211,6 @@ static int hal_port_init(int index)
int hal_port_init_shmem(char *logfilename)
{
int index;
struct wrs_shm_head *hal_shmem_hdr;
pr_info("Initializing switch ports...\n");
/* default timeouts */
......@@ -608,12 +607,18 @@ void hal_port_update_all()
{
int i;
/* poll_rts_state does not write to shmem */
poll_rts_state();
/* lock shmem */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_BEGIN);
hal_port_poll_sfp();
for (i = 0; i < HAL_MAX_PORTS; i++)
if (ports[i].in_use)
hal_port_fsm(&ports[i]);
/* unlock shmem */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_END);
}
int hal_port_enable_tracking(const char *port_name)
......@@ -641,8 +646,11 @@ int hal_port_start_lock(const char *port_name, int priority)
if (p->state != HAL_PORT_STATE_UP)
return -1;
/* lock shmem */
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_BEGIN);
/* fixme: check the main FSM state before */
p->state = HAL_PORT_STATE_LOCKING;
wrs_shm_write(hal_shmem_hdr, WRS_SHM_WRITE_END);
pr_info("Locking to port: %s\n", port_name);
......
......@@ -85,12 +85,16 @@ void init_shm(void)
/* print if waiting more than 10 seconds, some wait
* is expected since hal requires few seconds to start
*/
if (ret == 1) {
if (ret == WRS_SHM_OPEN_FAILED) {
pr_error("Unable to open HAL's shmem!\n");
}
if (ret == 2) {
if (ret == WRS_SHM_WRONG_VERSION) {
pr_error("Unable to read HAL's version!\n");
}
if (ret == WRS_SHM_INCONSISTENT_DATA) {
pr_error("Unable to read consistent data from "
"HAL's shmem!\n");
}
exit(1);
}
sleep(1);
......
......@@ -674,8 +674,6 @@ static void delete_htab_entry(struct rtu_addr addr)
{
int i, n_buckets = htab_count_buckets(addr);
wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_BEGIN);
pr_info("Deleted entry for MAC %s : hash %03x:%d.\n",
mac_to_string(rtu_htab[addr.hash][addr.bucket].mac), addr.hash,
addr.bucket);
......@@ -697,7 +695,6 @@ static void delete_htab_entry(struct rtu_addr addr)
&rtu_htab[a.hash][a.bucket],
(i == n_buckets - 1) ? 1 : 0);
}
wrs_shm_write(rtu_port_shmem, WRS_SHM_WRITE_END);
}
static void rtu_hw_commit(void)
......
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