Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(c) 2015-2016 Intel Corporation 3 : : */ 4 : : 5 : : #include <inttypes.h> 6 : : #include <stdalign.h> 7 : : 8 : : #include <rte_common.h> 9 : : #include <rte_cycles.h> 10 : : #include <rte_lcore.h> 11 : : #include <rte_log.h> 12 : : #include <rte_keepalive.h> 13 : : #include <rte_malloc.h> 14 : : 15 : : #include "eal_private.h" 16 : : 17 : : struct rte_keepalive { 18 : : /** Core Liveness. */ 19 : : struct { 20 : : /* 21 : : * Each element must be cache aligned to prevent false sharing. 22 : : */ 23 : : alignas(RTE_CACHE_LINE_SIZE) enum rte_keepalive_state core_state; 24 : : } live_data[RTE_KEEPALIVE_MAXCORES]; 25 : : 26 : : /** Last-seen-alive timestamps */ 27 : : uint64_t last_alive[RTE_KEEPALIVE_MAXCORES]; 28 : : 29 : : /** 30 : : * Cores to check. 31 : : * Indexed by core id, non-zero if the core should be checked. 32 : : */ 33 : : uint8_t active_cores[RTE_KEEPALIVE_MAXCORES]; 34 : : 35 : : /** Dead core handler. */ 36 : : rte_keepalive_failure_callback_t callback; 37 : : 38 : : /** 39 : : * Dead core handler app data. 40 : : * Pointer is passed to dead core handler. 41 : : */ 42 : : void *callback_data; 43 : : uint64_t tsc_initial; 44 : : uint64_t tsc_mhz; 45 : : 46 : : /** Core state relay handler. */ 47 : : rte_keepalive_relay_callback_t relay_callback; 48 : : 49 : : /** 50 : : * Core state relay handler app data. 51 : : * Pointer is passed to live core handler. 52 : : */ 53 : : void *relay_callback_data; 54 : : }; 55 : : 56 : : static void 57 : 0 : print_trace(const char *msg, struct rte_keepalive *keepcfg, int idx_core) 58 : : { 59 : 0 : EAL_LOG(INFO, "%sLast seen %" PRId64 "ms ago.", 60 : : msg, 61 : : ((rte_rdtsc() - keepcfg->last_alive[idx_core])*1000) 62 : : / rte_get_tsc_hz() 63 : : ); 64 : 0 : } 65 : : 66 : : void 67 : 0 : rte_keepalive_dispatch_pings(__rte_unused void *ptr_timer, 68 : : void *ptr_data) 69 : : { 70 : : struct rte_keepalive *keepcfg = ptr_data; 71 : : int idx_core; 72 : : 73 [ # # ]: 0 : for (idx_core = 0; idx_core < RTE_KEEPALIVE_MAXCORES; idx_core++) { 74 [ # # ]: 0 : if (keepcfg->active_cores[idx_core] == 0) 75 : 0 : continue; 76 : : 77 [ # # # # : 0 : switch (keepcfg->live_data[idx_core].core_state) { # ] 78 : : case RTE_KA_STATE_UNUSED: 79 : : break; 80 : 0 : case RTE_KA_STATE_ALIVE: /* Alive */ 81 : 0 : keepcfg->live_data[idx_core].core_state = 82 : : RTE_KA_STATE_MISSING; 83 : 0 : keepcfg->last_alive[idx_core] = rte_rdtsc(); 84 : 0 : break; 85 : 0 : case RTE_KA_STATE_MISSING: /* MIA */ 86 : 0 : print_trace("Core MIA. ", keepcfg, idx_core); 87 : 0 : keepcfg->live_data[idx_core].core_state = 88 : : RTE_KA_STATE_DEAD; 89 : 0 : break; 90 : 0 : case RTE_KA_STATE_DEAD: /* Dead */ 91 : 0 : keepcfg->live_data[idx_core].core_state = 92 : : RTE_KA_STATE_GONE; 93 : 0 : print_trace("Core died. ", keepcfg, idx_core); 94 [ # # ]: 0 : if (keepcfg->callback) 95 : 0 : keepcfg->callback( 96 : : keepcfg->callback_data, 97 : : idx_core 98 : : ); 99 : : break; 100 : : case RTE_KA_STATE_GONE: /* Buried */ 101 : : break; 102 : 0 : case RTE_KA_STATE_DOZING: /* Core going idle */ 103 : 0 : keepcfg->live_data[idx_core].core_state = 104 : : RTE_KA_STATE_SLEEP; 105 : 0 : keepcfg->last_alive[idx_core] = rte_rdtsc(); 106 : 0 : break; 107 : : case RTE_KA_STATE_SLEEP: /* Idled core */ 108 : : break; 109 : : } 110 [ # # ]: 0 : if (keepcfg->relay_callback) 111 : 0 : keepcfg->relay_callback( 112 : : keepcfg->relay_callback_data, 113 : : idx_core, 114 : : keepcfg->live_data[idx_core].core_state, 115 : : keepcfg->last_alive[idx_core] 116 : : ); 117 : : } 118 : 0 : } 119 : : 120 : : struct rte_keepalive * 121 : 0 : rte_keepalive_create(rte_keepalive_failure_callback_t callback, 122 : : void *data) 123 : : { 124 : : struct rte_keepalive *keepcfg; 125 : : 126 : 0 : keepcfg = rte_zmalloc("RTE_EAL_KEEPALIVE", 127 : : sizeof(struct rte_keepalive), 128 : : RTE_CACHE_LINE_SIZE); 129 [ # # ]: 0 : if (keepcfg != NULL) { 130 : 0 : keepcfg->callback = callback; 131 : 0 : keepcfg->callback_data = data; 132 : 0 : keepcfg->tsc_initial = rte_rdtsc(); 133 : 0 : keepcfg->tsc_mhz = rte_get_tsc_hz() / 1000; 134 : : } 135 : 0 : return keepcfg; 136 : : } 137 : : 138 : 0 : void rte_keepalive_register_relay_callback(struct rte_keepalive *keepcfg, 139 : : rte_keepalive_relay_callback_t callback, 140 : : void *data) 141 : : { 142 : 0 : keepcfg->relay_callback = callback; 143 : 0 : keepcfg->relay_callback_data = data; 144 : 0 : } 145 : : 146 : : void 147 : 0 : rte_keepalive_register_core(struct rte_keepalive *keepcfg, const int id_core) 148 : : { 149 [ # # ]: 0 : if (id_core < RTE_KEEPALIVE_MAXCORES) { 150 : 0 : keepcfg->active_cores[id_core] = RTE_KA_STATE_ALIVE; 151 : 0 : keepcfg->last_alive[id_core] = rte_rdtsc(); 152 : : } 153 : 0 : } 154 : : 155 : : void 156 : 0 : rte_keepalive_mark_alive(struct rte_keepalive *keepcfg) 157 : : { 158 : 0 : keepcfg->live_data[rte_lcore_id()].core_state = RTE_KA_STATE_ALIVE; 159 : 0 : } 160 : : 161 : : void 162 : 0 : rte_keepalive_mark_sleep(struct rte_keepalive *keepcfg) 163 : : { 164 : 0 : keepcfg->live_data[rte_lcore_id()].core_state = RTE_KA_STATE_DOZING; 165 : 0 : }