1 /*- 2 * BSD LICENSE 3 * 4 * Copyright(c) 2016 Intel Corporation. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <time.h> 35 36 #include <rte_common.h> 37 #include <rte_log.h> 38 #include <rte_keepalive.h> 39 40 #include "shm.h" 41 42 struct rte_keepalive_shm *rte_keepalive_shm_create(void) 43 { 44 int fd; 45 int idx_core; 46 struct rte_keepalive_shm *ka_shm; 47 48 /* If any existing object is not unlinked, it makes it all too easy 49 * for clients to end up with stale shared memory blocks when 50 * restarted. Unlinking makes sure subsequent shm_open by clients 51 * will get the new block mapped below. 52 */ 53 if (shm_unlink(RTE_KEEPALIVE_SHM_NAME) == -1 && errno != ENOENT) 54 printf("Warning: Error unlinking stale %s (%s)\n", 55 RTE_KEEPALIVE_SHM_NAME, strerror(errno)); 56 57 fd = shm_open(RTE_KEEPALIVE_SHM_NAME, 58 O_CREAT | O_TRUNC | O_RDWR, 0666); 59 if (fd < 0) 60 RTE_LOG(INFO, EAL, 61 "Failed to open %s as SHM (%s)\n", 62 RTE_KEEPALIVE_SHM_NAME, 63 strerror(errno)); 64 else if (ftruncate(fd, sizeof(struct rte_keepalive_shm)) != 0) 65 RTE_LOG(INFO, EAL, 66 "Failed to resize SHM (%s)\n", strerror(errno)); 67 else { 68 ka_shm = (struct rte_keepalive_shm *) mmap( 69 0, sizeof(struct rte_keepalive_shm), 70 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 71 close(fd); 72 if (ka_shm == MAP_FAILED) 73 RTE_LOG(INFO, EAL, 74 "Failed to mmap SHM (%s)\n", strerror(errno)); 75 else { 76 memset(ka_shm, 0, sizeof(struct rte_keepalive_shm)); 77 78 /* Initialize the semaphores for IPC/SHM use */ 79 if (sem_init(&ka_shm->core_died, 1, 0) != 0) { 80 RTE_LOG(INFO, EAL, 81 "Failed to setup SHM semaphore (%s)\n", 82 strerror(errno)); 83 munmap(ka_shm, 84 sizeof(struct rte_keepalive_shm)); 85 return NULL; 86 } 87 88 /* Set all cores to 'not present' */ 89 for (idx_core = 0; 90 idx_core < RTE_KEEPALIVE_MAXCORES; 91 idx_core++) { 92 ka_shm->core_state[idx_core] = 93 RTE_KA_STATE_UNUSED; 94 ka_shm->core_last_seen_times[idx_core] = 0; 95 } 96 97 return ka_shm; 98 } 99 } 100 return NULL; 101 } 102 103 void rte_keepalive_relayed_state(struct rte_keepalive_shm *shm, 104 const int id_core, const enum rte_keepalive_state core_state, 105 __rte_unused uint64_t last_alive) 106 { 107 int count; 108 109 shm->core_state[id_core] = core_state; 110 shm->core_last_seen_times[id_core] = last_alive; 111 112 if (core_state == RTE_KEEPALIVE_SHM_DEAD) { 113 /* Since core has died, also signal ka_agent. 114 * 115 * Limit number of times semaphore can be incremented, in case 116 * ka_agent is not active. 117 */ 118 if (sem_getvalue(&shm->core_died, &count) == -1) { 119 RTE_LOG(INFO, EAL, "Semaphore check failed(%s)\n", 120 strerror(errno)); 121 return; 122 } 123 if (count > 1) 124 return; 125 126 if (sem_post(&shm->core_died) != 0) 127 RTE_LOG(INFO, EAL, 128 "Failed to increment semaphore (%s)\n", 129 strerror(errno)); 130 } 131 } 132 133 void rte_keepalive_shm_cleanup(struct rte_keepalive_shm *ka_shm) 134 { 135 if (shm_unlink(RTE_KEEPALIVE_SHM_NAME) == -1 && errno != ENOENT) 136 printf("Warning: Error unlinking %s (%s)\n", 137 RTE_KEEPALIVE_SHM_NAME, strerror(errno)); 138 139 if (ka_shm && munmap(ka_shm, sizeof(struct rte_keepalive_shm)) != 0) 140 printf("Warning: munmap() failed\n"); 141 } 142