static int chaos_thread(void *arg) { uint64_t i, wait; int rc; chaos_buf *cbuf; odp_event_t ev; odp_queue_t from; thread_args_t *args = (thread_args_t *)arg; test_globals_t *globals = args->globals; int me = odp_thread_id(); odp_time_t start_time, end_time, diff; if (CHAOS_DEBUG) printf("Chaos thread %d starting...\n", me); /* Wait for all threads to start */ odp_barrier_wait(&globals->barrier); start_time = odp_time_local(); /* Run the test */ wait = odp_schedule_wait_time(5 * ODP_TIME_MSEC_IN_NS); for (i = 0; i < CHAOS_NUM_ROUNDS; i++) { ev = odp_schedule(&from, wait); if (ev == ODP_EVENT_INVALID) continue; cbuf = odp_buffer_addr(odp_buffer_from_event(ev)); CU_ASSERT_FATAL(cbuf != NULL); if (CHAOS_DEBUG) printf("Thread %d received event %" PRIu64 " seq %" PRIu64 " from Q %s, sending to Q %s\n", me, cbuf->evno, cbuf->seqno, globals-> chaos_q [CHAOS_PTR_TO_NDX(odp_queue_context(from))].name, globals-> chaos_q[cbuf->seqno % CHAOS_NUM_QUEUES].name); rc = odp_queue_enq( globals-> chaos_q[cbuf->seqno++ % CHAOS_NUM_QUEUES].handle, ev); CU_ASSERT_FATAL(rc == 0); } if (CHAOS_DEBUG) printf("Thread %d completed %d rounds...terminating\n", odp_thread_id(), CHAOS_NUM_EVENTS); exit_schedule_loop(); end_time = odp_time_local(); diff = odp_time_diff(end_time, start_time); printf("Thread %d ends, elapsed time = %" PRIu64 "us\n", odp_thread_id(), odp_time_to_ns(diff) / 1000); return 0; }
static void spin_wait(uint64_t ns) { odp_time_t start, now, diff; start = odp_time_local(); do { now = odp_time_local(); diff = odp_time_diff(now, start); } while (odp_time_to_ns(diff) < ns); }
void scheduler_test_wait_time(void) { int i; odp_queue_t queue; uint64_t wait_time; odp_queue_param_t qp; odp_time_t lower_limit, upper_limit; odp_time_t start_time, end_time, diff; /* check on read */ wait_time = odp_schedule_wait_time(0); wait_time = odp_schedule_wait_time(1); /* check ODP_SCHED_NO_WAIT */ odp_queue_param_init(&qp); qp.type = ODP_QUEUE_TYPE_SCHED; qp.sched.sync = ODP_SCHED_SYNC_PARALLEL; qp.sched.prio = ODP_SCHED_PRIO_NORMAL; qp.sched.group = ODP_SCHED_GROUP_ALL; queue = odp_queue_create("dummy_queue", &qp); CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID); wait_time = odp_schedule_wait_time(ODP_TIME_SEC_IN_NS); start_time = odp_time_local(); odp_schedule(&queue, ODP_SCHED_NO_WAIT); end_time = odp_time_local(); diff = odp_time_diff(end_time, start_time); lower_limit = ODP_TIME_NULL; upper_limit = odp_time_local_from_ns(ODP_WAIT_TOLERANCE); CU_ASSERT(odp_time_cmp(diff, lower_limit) >= 0); CU_ASSERT(odp_time_cmp(diff, upper_limit) <= 0); /* check time correctness */ start_time = odp_time_local(); for (i = 1; i < 6; i++) { odp_schedule(&queue, wait_time); printf("%d..", i); } end_time = odp_time_local(); diff = odp_time_diff(end_time, start_time); lower_limit = odp_time_local_from_ns(5 * ODP_TIME_SEC_IN_NS - ODP_WAIT_TOLERANCE); upper_limit = odp_time_local_from_ns(5 * ODP_TIME_SEC_IN_NS + ODP_WAIT_TOLERANCE); CU_ASSERT(odp_time_cmp(diff, lower_limit) >= 0); CU_ASSERT(odp_time_cmp(diff, upper_limit) <= 0); CU_ASSERT_FATAL(odp_queue_destroy(queue) == 0); }
void scheduler_test_wait_time(void) { odp_queue_t queue; uint64_t wait_time; odp_queue_param_t qp; odp_time_t lower_limit, upper_limit; odp_time_t start_time, end_time, diff; /* check on read */ wait_time = odp_schedule_wait_time(0); wait_time = odp_schedule_wait_time(1); (void)wait_time; /* check ODP_SCHED_NO_WAIT */ odp_queue_param_init(&qp); queue = odp_queue_create("dummy_queue", ODP_QUEUE_TYPE_SCHED, &qp); CU_ASSERT_FATAL(queue != ODP_QUEUE_INVALID); wait_time = odp_schedule_wait_time(ODP_TIME_SEC_IN_NS); start_time = odp_time_local(); odp_schedule(&queue, ODP_SCHED_NO_WAIT); end_time = odp_time_local(); diff = odp_time_diff(end_time, start_time); lower_limit = ODP_TIME_NULL; upper_limit = odp_time_local_from_ns(ODP_WAIT_TOLERANCE); CU_ASSERT(odp_time_cmp(diff, lower_limit) >= 0); CU_ASSERT(odp_time_cmp(diff, upper_limit) <= 0); #ifndef MAGIC_SCALL int i; /* check time correctness */ start_time = odp_time_local(); for (i = 1; i < 6; i++) { odp_schedule(&queue, wait_time); /* printf("%d..", i); */ } end_time = odp_time_local(); diff = odp_time_diff(end_time, start_time); lower_limit = odp_time_local_from_ns(5 * ODP_TIME_SEC_IN_NS - ODP_WAIT_TOLERANCE); upper_limit = odp_time_local_from_ns(5 * ODP_TIME_SEC_IN_NS + ODP_WAIT_TOLERANCE); CU_ASSERT(odp_time_cmp(diff, lower_limit) >= 0); CU_ASSERT(odp_time_cmp(diff, upper_limit) <= 0); #endif CU_ASSERT_FATAL(odp_queue_destroy(queue) == 0); }
/** * printing verbose statistics * */ static void print_global_stats(int num_workers) { odp_time_t start, wait, diff; uint64_t pkts, pkts_prev = 0, pps, maximum_pps = 0; int verbose_interval = 20; odp_thrmask_t thrd_mask; while (odp_thrmask_worker(&thrd_mask) < num_workers) continue; wait = odp_time_local_from_ns(verbose_interval * ODP_TIME_SEC_IN_NS); start = odp_time_local(); while (odp_thrmask_worker(&thrd_mask) == num_workers) { if (args->appl.number != -1 && odp_atomic_load_u64(&counters.cnt) >= (unsigned int)args->appl.number) { break; } diff = odp_time_diff(odp_time_local(), start); if (odp_time_cmp(wait, diff) > 0) continue; start = odp_time_local(); if (args->appl.mode == APPL_MODE_RCV) { pkts = odp_atomic_load_u64(&counters.udp); printf(" total receive(UDP: %" PRIu64 ")\n", pkts); continue; } if (args->appl.mode == APPL_MODE_PING) { pkts = odp_atomic_load_u64(&counters.icmp); printf(" total receive(ICMP: %" PRIu64 ")\n", pkts); } pkts = odp_atomic_load_u64(&counters.seq); printf(" total sent: %" PRIu64 "\n", pkts); if (args->appl.mode == APPL_MODE_UDP) { pps = (pkts - pkts_prev) / verbose_interval; if (pps > maximum_pps) maximum_pps = pps; printf(" %" PRIu64 " pps, %" PRIu64 " max pps\n", pps, maximum_pps); pkts_prev = pkts; } } }
static odp_event_t queue_deq_wait_time(odp_queue_t queue, uint64_t ns) { odp_time_t wait, end; odp_event_t ev; wait = odp_time_local_from_ns(ns); end = odp_time_sum(odp_time_local(), wait); do { ev = odp_queue_deq(queue); if (ev != ODP_EVENT_INVALID) return ev; } while (odp_time_cmp(end, odp_time_local()) > 0); return ODP_EVENT_INVALID; }
static odp_packet_t wait_for_packet(pktio_info_t *pktio_rx, uint32_t seq, uint64_t ns) { odp_time_t wait_time, end; odp_event_t ev; odp_packet_t pkt; uint64_t wait; wait = odp_schedule_wait_time(ns); wait_time = odp_time_local_from_ns(ns); end = odp_time_sum(odp_time_local(), wait_time); do { pkt = ODP_PACKET_INVALID; if (pktio_rx->in_mode == ODP_PKTIN_MODE_RECV) { odp_pktio_recv(pktio_rx->id, &pkt, 1); } else { if (pktio_rx->in_mode == ODP_PKTIN_MODE_POLL) ev = queue_deq_wait_time(pktio_rx->inq, ns); else ev = odp_schedule(NULL, wait); if (ev != ODP_EVENT_INVALID) { if (odp_event_type(ev) == ODP_EVENT_PACKET) pkt = odp_packet_from_event(ev); else odp_event_free(ev); } } if (pkt != ODP_PACKET_INVALID) { if (pktio_pkt_seq(pkt) == seq) return pkt; odp_packet_free(pkt); } } while (odp_time_cmp(end, odp_time_local()) > 0); CU_FAIL("failed to receive transmitted packet"); return ODP_PACKET_INVALID; }
static int schedule_common_(void *arg) { thread_args_t *args = (thread_args_t *)arg; odp_schedule_sync_t sync; test_globals_t *globals; queue_context *qctx; buf_contents *bctx, *bctx_cpy; odp_pool_t pool; int locked; int num; odp_event_t ev; odp_buffer_t buf, buf_cpy; odp_queue_t from; globals = args->globals; sync = args->sync; pool = odp_pool_lookup(MSG_POOL_NAME); CU_ASSERT_FATAL(pool != ODP_POOL_INVALID); if (args->num_workers > 1) odp_barrier_wait(&globals->barrier); while (1) { from = ODP_QUEUE_INVALID; num = 0; odp_ticketlock_lock(&globals->lock); if (globals->buf_count == 0) { odp_ticketlock_unlock(&globals->lock); break; } odp_ticketlock_unlock(&globals->lock); if (args->enable_schd_multi) { odp_event_t events[BURST_BUF_SIZE], ev_cpy[BURST_BUF_SIZE]; odp_buffer_t buf_cpy[BURST_BUF_SIZE]; int j; num = odp_schedule_multi(&from, ODP_SCHED_NO_WAIT, events, BURST_BUF_SIZE); CU_ASSERT(num >= 0); CU_ASSERT(num <= BURST_BUF_SIZE); if (num == 0) continue; if (sync == ODP_SCHED_SYNC_ORDERED) { int ndx; int ndx_max; int rc; ndx_max = odp_queue_lock_count(from); CU_ASSERT_FATAL(ndx_max >= 0); qctx = odp_queue_context(from); for (j = 0; j < num; j++) { bctx = odp_buffer_addr( odp_buffer_from_event (events[j])); buf_cpy[j] = odp_buffer_alloc(pool); CU_ASSERT_FATAL(buf_cpy[j] != ODP_BUFFER_INVALID); bctx_cpy = odp_buffer_addr(buf_cpy[j]); memcpy(bctx_cpy, bctx, sizeof(buf_contents)); bctx_cpy->output_sequence = bctx_cpy->sequence; ev_cpy[j] = odp_buffer_to_event(buf_cpy[j]); } rc = odp_queue_enq_multi(qctx->pq_handle, ev_cpy, num); CU_ASSERT(rc == num); bctx = odp_buffer_addr( odp_buffer_from_event(events[0])); for (ndx = 0; ndx < ndx_max; ndx++) { odp_schedule_order_lock(ndx); CU_ASSERT(bctx->sequence == qctx->lock_sequence[ndx]); qctx->lock_sequence[ndx] += num; odp_schedule_order_unlock(ndx); } } for (j = 0; j < num; j++) odp_event_free(events[j]); } else { ev = odp_schedule(&from, ODP_SCHED_NO_WAIT); if (ev == ODP_EVENT_INVALID) continue; buf = odp_buffer_from_event(ev); num = 1; if (sync == ODP_SCHED_SYNC_ORDERED) { int ndx; int ndx_max; int rc; ndx_max = odp_queue_lock_count(from); CU_ASSERT_FATAL(ndx_max >= 0); qctx = odp_queue_context(from); bctx = odp_buffer_addr(buf); buf_cpy = odp_buffer_alloc(pool); CU_ASSERT_FATAL(buf_cpy != ODP_BUFFER_INVALID); bctx_cpy = odp_buffer_addr(buf_cpy); memcpy(bctx_cpy, bctx, sizeof(buf_contents)); bctx_cpy->output_sequence = bctx_cpy->sequence; rc = odp_queue_enq(qctx->pq_handle, odp_buffer_to_event (buf_cpy)); CU_ASSERT(rc == 0); for (ndx = 0; ndx < ndx_max; ndx++) { odp_schedule_order_lock(ndx); CU_ASSERT(bctx->sequence == qctx->lock_sequence[ndx]); qctx->lock_sequence[ndx] += num; odp_schedule_order_unlock(ndx); } } odp_buffer_free(buf); } if (args->enable_excl_atomic) { locked = odp_spinlock_trylock(&globals->atomic_lock); CU_ASSERT(locked != 0); CU_ASSERT(from != ODP_QUEUE_INVALID); if (locked) { int cnt; odp_time_t time = ODP_TIME_NULL; /* Do some work here to keep the thread busy */ for (cnt = 0; cnt < 1000; cnt++) time = odp_time_sum(time, odp_time_local()); odp_spinlock_unlock(&globals->atomic_lock); } } if (sync == ODP_SCHED_SYNC_ATOMIC) odp_schedule_release_atomic(); if (sync == ODP_SCHED_SYNC_ORDERED) odp_schedule_release_ordered(); odp_ticketlock_lock(&globals->lock); globals->buf_count -= num; if (globals->buf_count < 0) { odp_ticketlock_unlock(&globals->lock); CU_FAIL_FATAL("Buffer counting failed"); } odp_ticketlock_unlock(&globals->lock); } if (args->num_workers > 1) odp_barrier_wait(&globals->barrier); if (sync == ODP_SCHED_SYNC_ORDERED) locked = odp_ticketlock_trylock(&globals->lock); else locked = 0; if (locked && globals->buf_count_cpy > 0) { odp_event_t ev; odp_queue_t pq; uint64_t seq; uint64_t bcount = 0; int i, j; char name[32]; uint64_t num_bufs = args->num_bufs; uint64_t buf_count = globals->buf_count_cpy; for (i = 0; i < args->num_prio; i++) { for (j = 0; j < args->num_queues; j++) { snprintf(name, sizeof(name), "plain_%d_%d_o", i, j); pq = odp_queue_lookup(name); CU_ASSERT_FATAL(pq != ODP_QUEUE_INVALID); seq = 0; while (1) { ev = odp_queue_deq(pq); if (ev == ODP_EVENT_INVALID) { CU_ASSERT(seq == num_bufs); break; } bctx = odp_buffer_addr( odp_buffer_from_event(ev)); CU_ASSERT(bctx->sequence == seq); seq++; bcount++; odp_event_free(ev); } } } CU_ASSERT(bcount == buf_count); globals->buf_count_cpy = 0; } if (locked) odp_ticketlock_unlock(&globals->lock); /* Clear scheduler atomic / ordered context between tests */ num = exit_schedule_loop(); CU_ASSERT(num == 0); if (num) printf("\nDROPPED %i events\n\n", num); return 0; }
static int ipc_second_process(void) { odp_pktio_t ipc_pktio; odp_pool_param_t params; odp_pool_t pool; odp_packet_t pkt_tbl[MAX_PKT_BURST]; odp_packet_t alloc_pkt; int pkts; int ret; int i; odp_time_t start_cycle; odp_time_t cycle; odp_time_t diff; odp_time_t wait; uint64_t stat_pkts = 0; odp_pktin_queue_t pktin; /* Create packet pool */ memset(¶ms, 0, sizeof(params)); params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE; params.pkt.len = SHM_PKT_POOL_BUF_SIZE; params.pkt.num = SHM_PKT_POOL_SIZE; params.type = ODP_POOL_PACKET; pool = odp_pool_create("packet_pool2", ¶ms); if (pool == ODP_POOL_INVALID) { EXAMPLE_ERR("Error: packet pool create failed.\n"); exit(EXIT_FAILURE); } ipc_pktio = create_pktio(pool); wait = odp_time_local_from_ns(run_time_sec * ODP_TIME_SEC_IN_NS); start_cycle = odp_time_local(); if (odp_pktin_queue(ipc_pktio, &pktin, 1) != 1) { EXAMPLE_ERR("no input queue\n"); return -1; } /* start ipc pktio, i.e. wait until other process connects */ for (;;) { /* 1. exit loop if time specified */ if (run_time_sec) { cycle = odp_time_local(); diff = odp_time_diff(cycle, start_cycle); if (odp_time_cmp(wait, diff) < 0) { printf("timeout exit, run_time_sec %d\n", run_time_sec); goto not_started; } } ret = odp_pktio_start(ipc_pktio); if (!ret) break; } for (;;) { /* exit loop if time specified */ if (run_time_sec) { cycle = odp_time_local(); diff = odp_time_diff(cycle, start_cycle); if (odp_time_cmp(wait, diff) < 0) { EXAMPLE_DBG("exit after %d seconds\n", run_time_sec); break; } } /* recv some packets and change MAGIC to MAGIC_2 */ pkts = odp_pktin_recv(pktin, pkt_tbl, MAX_PKT_BURST); if (pkts <= 0) continue; for (i = 0; i < pkts; i++) { odp_packet_t pkt = pkt_tbl[i]; pkt_head_t head; size_t off; off = odp_packet_l4_offset(pkt); if (off == ODP_PACKET_OFFSET_INVALID) EXAMPLE_ABORT("invalid l4 offset\n"); off += ODPH_UDPHDR_LEN; ret = odp_packet_copy_to_mem(pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable copy out head data"); if (head.magic != TEST_SEQ_MAGIC) EXAMPLE_ABORT("Wrong head magic!"); /* Modify magic number in packet */ head.magic = TEST_SEQ_MAGIC_2; ret = odp_packet_copy_from_mem(pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable to copy in head data"); } /* send all packets back */ ret = ipc_odp_packet_send_or_free(ipc_pktio, pkt_tbl, pkts); if (ret < 0) EXAMPLE_ABORT("can not send packets\n"); stat_pkts += ret; /* alloc packet from local pool, set magic to ALLOC_MAGIC, * and send it.*/ alloc_pkt = odp_packet_alloc(pool, SHM_PKT_POOL_BUF_SIZE); if (alloc_pkt != ODP_PACKET_INVALID) { pkt_head_t head; size_t off; odp_packet_l4_offset_set(alloc_pkt, 30); head.magic = TEST_ALLOC_MAGIC; off = odp_packet_l4_offset(alloc_pkt); off += ODPH_UDPHDR_LEN; ret = odp_packet_copy_from_mem(alloc_pkt, off, sizeof(head), &head); if (ret) EXAMPLE_ABORT("unable to copy in head data"); pkt_tbl[0] = alloc_pkt; ret = ipc_odp_packet_send_or_free(ipc_pktio, pkt_tbl, 1); if (ret < 0) EXAMPLE_ABORT("can not send packets\n"); stat_pkts += 1; } } /* cleanup and exit */ ret = odp_pktio_stop(ipc_pktio); if (ret) { EXAMPLE_DBG("ipc2: odp_pktio_stop error %d\n", ret); return -1; } not_started: ret = odp_pktio_close(ipc_pktio); if (ret) { EXAMPLE_DBG("ipc2: odp_pktio_close error %d\n", ret); return -1; } ret = odp_pool_destroy(pool); if (ret) EXAMPLE_DBG("ipc2: pool_destroy error %d\n", ret); return stat_pkts > 1000 ? 0 : -1; }
/* * Main packet transmit routine. Transmit packets at a fixed rate for * specified length of time. */ static int run_thread_tx(void *arg) { test_globals_t *globals; int thr_id; odp_pktout_queue_t pktout; pkt_tx_stats_t *stats; odp_time_t cur_time, send_time_end, send_duration; odp_time_t burst_gap_end, burst_gap; uint32_t batch_len; int unsent_pkts = 0; odp_packet_t tx_packet[BATCH_LEN_MAX]; odp_time_t idle_start = ODP_TIME_NULL; thread_args_t *targs = arg; batch_len = targs->batch_len; if (batch_len > BATCH_LEN_MAX) batch_len = BATCH_LEN_MAX; thr_id = odp_thread_id(); globals = odp_shm_addr(odp_shm_lookup("test_globals")); stats = &globals->tx_stats[thr_id]; if (odp_pktout_queue(globals->pktio_tx, &pktout, 1) != 1) LOG_ABORT("Failed to get output queue for thread %d\n", thr_id); burst_gap = odp_time_local_from_ns( ODP_TIME_SEC_IN_NS / (targs->pps / targs->batch_len)); send_duration = odp_time_local_from_ns(targs->duration * ODP_TIME_SEC_IN_NS); odp_barrier_wait(&globals->tx_barrier); cur_time = odp_time_local(); send_time_end = odp_time_sum(cur_time, send_duration); burst_gap_end = cur_time; while (odp_time_cmp(send_time_end, cur_time) > 0) { unsigned alloc_cnt = 0, tx_cnt; if (odp_time_cmp(burst_gap_end, cur_time) > 0) { cur_time = odp_time_local(); if (!odp_time_cmp(idle_start, ODP_TIME_NULL)) idle_start = cur_time; continue; } if (odp_time_cmp(idle_start, ODP_TIME_NULL) > 0) { odp_time_t diff = odp_time_diff(cur_time, idle_start); stats->s.idle_ticks = odp_time_sum(diff, stats->s.idle_ticks); idle_start = ODP_TIME_NULL; } burst_gap_end = odp_time_sum(burst_gap_end, burst_gap); alloc_cnt = alloc_packets(tx_packet, batch_len - unsent_pkts); if (alloc_cnt != batch_len) stats->s.alloc_failures++; tx_cnt = send_packets(pktout, tx_packet, alloc_cnt); unsent_pkts = alloc_cnt - tx_cnt; stats->s.enq_failures += unsent_pkts; stats->s.tx_cnt += tx_cnt; cur_time = odp_time_local(); } VPRINT(" %02d: TxPkts %-8" PRIu64 " EnqFail %-6" PRIu64 " AllocFail %-6" PRIu64 " Idle %" PRIu64 "ms\n", thr_id, stats->s.tx_cnt, stats->s.enq_failures, stats->s.alloc_failures, odp_time_to_ns(stats->s.idle_ticks) / (uint64_t)ODP_TIME_MSEC_IN_NS); return 0; }