#include <time.h>
 
 
#include "shm.h"
 
struct rte_keepalive_shm *rte_keepalive_shm_create(void)
{
    int fd;
    int idx_core;
    struct rte_keepalive_shm *ka_shm;
 
    
    if (shm_unlink(RTE_KEEPALIVE_SHM_NAME) == -1 && errno != ENOENT)
            "Warning: Error unlinking stale %s (%s)\n",
            RTE_KEEPALIVE_SHM_NAME, strerror(errno));
 
    fd = shm_open(RTE_KEEPALIVE_SHM_NAME,
        O_CREAT | O_TRUNC | O_RDWR, 0666);
    if (fd < 0)
        RTE_LOG(ERR, L2FWD, 
"Failed to open %s as SHM (%s)\n",
 
            RTE_KEEPALIVE_SHM_NAME, strerror(errno));
    else if (ftruncate(fd, sizeof(struct rte_keepalive_shm)) != 0)
        RTE_LOG(ERR, L2FWD, 
"Failed to resize SHM (%s)\n", strerror(errno));
 
    else {
        ka_shm = (struct rte_keepalive_shm *) mmap(
            0, sizeof(struct rte_keepalive_shm),
            PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        close(fd);
        if (ka_shm == MAP_FAILED)
            RTE_LOG(ERR, L2FWD, 
"Failed to mmap SHM (%s)\n", strerror(errno));
 
        else {
            memset(ka_shm, 0, sizeof(struct rte_keepalive_shm));
 
            
            if (sem_init(&ka_shm->core_died, 1, 0) != 0) {
                RTE_LOG(ERR, L2FWD, 
"Failed to setup SHM semaphore (%s)\n",
 
                    strerror(errno));
                munmap(ka_shm,
                    sizeof(struct rte_keepalive_shm));
                return NULL;
            }
 
            
            for (idx_core = 0;
                    idx_core++) {
                ka_shm->core_state[idx_core] =
                    RTE_KA_STATE_UNUSED;
                ka_shm->core_last_seen_times[idx_core] = 0;
            }
 
            return ka_shm;
        }
    }
return NULL;
}
 
void rte_keepalive_relayed_state(struct rte_keepalive_shm *shm,
    const int id_core, const enum rte_keepalive_state core_state,
{
    int count;
 
    shm->core_state[id_core] = core_state;
    shm->core_last_seen_times[id_core] = last_alive;
 
    if (core_state == RTE_KEEPALIVE_SHM_DEAD) {
        
        if (sem_getvalue(&shm->core_died, &count) == -1) {
            RTE_LOG(ERR, L2FWD, 
"Semaphore check failed(%s)\n",
 
                strerror(errno));
            return;
        }
        if (count > 1)
            return;
 
        if (sem_post(&shm->core_died) != 0)
            RTE_LOG(ERR, L2FWD, 
"Failed to increment semaphore (%s)\n",
 
                strerror(errno));
    }
}
 
void rte_keepalive_shm_cleanup(struct rte_keepalive_shm *ka_shm)
{
    if (shm_unlink(RTE_KEEPALIVE_SHM_NAME) == -1 && errno != ENOENT)
        RTE_LOG(NOTICE, L2FWD, 
"Warning: Error unlinking  %s (%s)\n",
 
            RTE_KEEPALIVE_SHM_NAME, strerror(errno));
 
    if (ka_shm && munmap(ka_shm, sizeof(struct rte_keepalive_shm)) != 0)
        RTE_LOG(ERR, L2FWD, 
"Warning: munmap() failed: %s\n",
 
            strerror(errno));
}
#define RTE_KEEPALIVE_MAXCORES
 
#define RTE_LOG(l, t,...)