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