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