Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(c) 2025 Ericsson AB 3 : : */ 4 : : 5 : : #include "test_atomic_common.h" 6 : : 7 : : static inline bool 8 : : test_done(struct test_order *const t) 9 : : { 10 : 0 : return t->err || t->result == EVT_TEST_SUCCESS; 11 : : } 12 : : 13 : : static inline int 14 : 0 : atomic_producer(void *arg) 15 : : { 16 : : struct prod_data *p = arg; 17 : 0 : struct test_order *t = p->t; 18 : 0 : struct evt_options *opt = t->opt; 19 : 0 : const uint8_t dev_id = p->dev_id; 20 : 0 : const uint8_t port = p->port_id; 21 : 0 : struct rte_mempool *pool = t->pool; 22 : 0 : const uint64_t nb_pkts = t->nb_pkts; 23 : 0 : uint32_t *producer_flow_seq = t->producer_flow_seq; 24 : 0 : const uint32_t nb_flows = t->nb_flows; 25 : : uint64_t count = 0; 26 : : struct rte_mbuf *m; 27 : : struct rte_event ev; 28 : : 29 : 0 : if (opt->verbose_level > 1) 30 : 0 : printf("%s(): lcore %d dev_id %d port=%d queue=%d\n", 31 : 0 : __func__, rte_lcore_id(), dev_id, port, p->queue_id); 32 : : 33 : 0 : ev = (struct rte_event) { 34 : : .op = RTE_EVENT_OP_NEW, 35 : 0 : .queue_id = p->queue_id, 36 : : .sched_type = RTE_SCHED_TYPE_ATOMIC, 37 : : .priority = RTE_EVENT_DEV_PRIORITY_NORMAL, 38 : : .event_type = RTE_EVENT_TYPE_CPU, 39 : : .sub_event_type = 0 40 : : }; 41 : : 42 : 0 : while (count < nb_pkts && t->err == false) { 43 : 0 : m = rte_pktmbuf_alloc(pool); 44 : 0 : if (m == NULL) 45 : 0 : continue; 46 : : 47 : : /* Maintain seq number per flow */ 48 : : 49 : 0 : const flow_id_t flow = rte_rand_max(nb_flows); 50 : : 51 : 0 : *order_mbuf_flow_id(t, m) = flow; 52 : 0 : *order_mbuf_seqn(t, m) = producer_flow_seq[flow]++; 53 : : 54 : 0 : ev.flow_id = flow; 55 : 0 : ev.mbuf = m; 56 : : 57 : 0 : while (rte_event_enqueue_burst(dev_id, port, &ev, 1) != 1) { 58 : 0 : if (t->err) 59 : : break; 60 : : rte_pause(); 61 : : } 62 : : 63 : 0 : count++; 64 : : } 65 : : 66 : 0 : if (!evt_is_maintenance_free(dev_id)) { 67 : 0 : while (!test_done(t)) { 68 : : rte_event_maintain(dev_id, port, RTE_EVENT_DEV_MAINT_OP_FLUSH); 69 : : rte_pause(); 70 : : } 71 : : } 72 : : 73 : 0 : return 0; 74 : : } 75 : : 76 : : int 77 : 0 : atomic_launch_lcores(struct evt_test *test, struct evt_options *opt, 78 : : int (*worker)(void *)) 79 : : { 80 : : int ret, lcore_id; 81 : : struct test_order *t = evt_test_priv(test); 82 : : 83 : : /* launch workers */ 84 : : 85 : : int wkr_idx = 0; 86 : 0 : RTE_LCORE_FOREACH_WORKER(lcore_id) { 87 : 0 : if (!(opt->wlcores[lcore_id])) 88 : 0 : continue; 89 : : 90 : 0 : ret = rte_eal_remote_launch(worker, &t->worker[wkr_idx], lcore_id); 91 : 0 : if (ret) { 92 : 0 : evt_err("failed to launch worker %d", lcore_id); 93 : 0 : return ret; 94 : : } 95 : 0 : wkr_idx++; 96 : : } 97 : : 98 : : /* launch producer */ 99 : 0 : int plcore = evt_get_first_active_lcore(opt->plcores); 100 : : 101 : 0 : ret = rte_eal_remote_launch(atomic_producer, &t->prod, plcore); 102 : 0 : if (ret) { 103 : 0 : evt_err("failed to launch order_producer %d", plcore); 104 : 0 : return ret; 105 : : } 106 : : 107 : : uint64_t prev_time = rte_get_timer_cycles(); 108 : : int64_t prev_outstanding_pkts = -1; 109 : : 110 : 0 : while (t->err == false) { 111 : : uint64_t current_time = rte_get_timer_cycles(); 112 : 0 : int64_t outstanding_pkts = rte_atomic_load_explicit( 113 : : &t->outstand_pkts, rte_memory_order_relaxed); 114 : : 115 : 0 : if (outstanding_pkts <= 0) { 116 : 0 : t->result = EVT_TEST_SUCCESS; 117 : 0 : break; 118 : : } 119 : : 120 : 0 : if (current_time - prev_time > rte_get_timer_hz() * IDLE_TIMEOUT) { 121 : : printf(CLGRN "\r%" PRId64 "" CLNRM, outstanding_pkts); 122 : 0 : fflush(stdout); 123 : 0 : if (prev_outstanding_pkts == outstanding_pkts) { 124 : 0 : rte_event_dev_dump(opt->dev_id, stdout); 125 : 0 : evt_err("No events processed during one period, deadlock"); 126 : 0 : t->err = true; 127 : 0 : break; 128 : : } 129 : : prev_outstanding_pkts = outstanding_pkts; 130 : : prev_time = current_time; 131 : : } 132 : : } 133 : : printf("\r"); 134 : : 135 : 0 : return 0; 136 : : }