/** * Copyright (C) Mellanox Technologies Ltd. 2001-2015. ALL RIGHTS RESERVED. * * See file LICENSE for terms. */ #include "ud_base.h" #include extern "C" { #include #include #include #include } class test_ud_pending : public ud_base_test { public: uct_pending_req_t m_r[64]; void dispatch_req(uct_pending_req_t *r) { EXPECT_UCS_OK(tx(m_e1)); } void post_pending_reqs(void) { int i; req_count = 0; me = this; m_e1->connect_to_iface(0, *m_e2); disable_async(m_e1); disable_async(m_e2); set_tx_win(m_e1, UCT_UD_CA_MAX_WINDOW); /* ep is not connected yet */ EXPECT_EQ(UCS_ERR_NO_RESOURCE, tx(m_e1)); /* queuee some work */ for(i = 0; i < N; i++) { m_r[i].func = pending_cb_dispatch; EXPECT_EQ(UCS_OK, uct_ep_pending_add(m_e1->ep(0), &m_r[i], 0)); } } void check_pending_reqs(bool wait) { /* wait for all work to be complete */ ucs_time_t start_time = ucs_get_time(); while (wait && (req_count < N) && (ucs_get_time() < start_time + ucs_time_from_sec(10.0))) { progress(); } EXPECT_EQ(N, req_count); uct_ep_pending_purge(m_e1->ep(0), purge_cb, NULL); } static const int N; static const int W; static int req_count; static test_ud_pending *me; static ucs_status_t pending_cb_dispatch(uct_pending_req_t *r) { req_count++; me->dispatch_req(r); return UCS_OK; } static ucs_status_t pending_cb(uct_pending_req_t *r) { req_count++; return UCS_OK; } static void purge_cb(uct_pending_req_t *r, void *arg) { req_count++; } static ucs_status_t pending_cb_busy(uct_pending_req_t *r) { return UCS_ERR_BUSY; } }; const int test_ud_pending::N = 13; const int test_ud_pending::W = 6; int test_ud_pending::req_count = 0; test_ud_pending *test_ud_pending::me = 0; /* add/purge requests */ UCS_TEST_SKIP_COND_P(test_ud_pending, async_progress, !check_caps(UCT_IFACE_FLAG_PUT_SHORT)) { uct_pending_req_t r[N]; int i; req_count = 0; connect(); set_tx_win(m_e1, 2); EXPECT_UCS_OK(tx(m_e1)); for(i = 0; i < N; i++) { EXPECT_EQ(UCS_OK, uct_ep_pending_add(m_e1->ep(0), &r[i], 0)); } twait(300); /* requests must not be dispatched from async progress */ EXPECT_EQ(0, req_count); uct_ep_pending_purge(m_e1->ep(0), purge_cb, NULL); EXPECT_EQ(N, req_count); } UCS_TEST_SKIP_COND_P(test_ud_pending, sync_progress, !check_caps(UCT_IFACE_FLAG_PUT_SHORT)) { uct_pending_req_t r[N]; int i; req_count = 0; connect(); set_tx_win(m_e1, 2); EXPECT_UCS_OK(tx(m_e1)); for(i = 0; i < N; i++) { r[i].func = pending_cb; EXPECT_EQ(UCS_OK, uct_ep_pending_add(m_e1->ep(0), &r[i], 0)); } wait_for_value(&req_count, N, true); /* requests must be dispatched from progress */ EXPECT_EQ(N, req_count); uct_ep_pending_purge(m_e1->ep(0), purge_cb, NULL); EXPECT_EQ(N, req_count); } UCS_TEST_SKIP_COND_P(test_ud_pending, err_busy, !check_caps(UCT_IFACE_FLAG_PUT_SHORT)) { uct_pending_req_t r[N]; int i; req_count = 0; connect(); set_tx_win(m_e1, 2); EXPECT_UCS_OK(tx(m_e1)); for(i = 0; i < N; i++) { r[i].func = pending_cb_busy; EXPECT_EQ(UCS_OK, uct_ep_pending_add(m_e1->ep(0), &r[i], 0)); } short_progress_loop(); /* requests will not be dispatched from progress */ EXPECT_EQ(0, req_count); uct_ep_pending_purge(m_e1->ep(0), purge_cb, NULL); EXPECT_EQ(N, req_count); } UCS_TEST_SKIP_COND_P(test_ud_pending, connect, !check_caps(UCT_IFACE_FLAG_PUT_SHORT)) { post_pending_reqs(); check_pending_reqs(true); } UCS_TEST_SKIP_COND_P(test_ud_pending, flush, !check_caps(UCT_IFACE_FLAG_PUT_SHORT)) { post_pending_reqs(); flush(); check_pending_reqs(false); } UCS_TEST_SKIP_COND_P(test_ud_pending, window, !check_caps(UCT_IFACE_FLAG_PUT_SHORT)) { int i; uct_pending_req_t r; req_count = 0; me = this; connect(); set_tx_win(m_e1, W+1); for (i = 0; i < W; i ++) { EXPECT_UCS_OK(tx(m_e1)); } EXPECT_EQ(UCS_ERR_NO_RESOURCE, tx(m_e1)); r.func = pending_cb_dispatch; EXPECT_EQ(UCS_OK, uct_ep_pending_add(m_e1->ep(0), &r, 0)); wait_for_value(&req_count, 1, true); EXPECT_EQ(1, req_count); uct_ep_pending_purge(m_e1->ep(0), purge_cb, NULL); } UCS_TEST_SKIP_COND_P(test_ud_pending, tx_wqe, !check_caps(UCT_IFACE_FLAG_PUT_SHORT)) { int i; uct_pending_req_t r; ucs_status_t status; req_count = 0; me = this; disable_async(m_e1); disable_async(m_e2); connect(); /* set big window */ set_tx_win(m_e1, 8192); i = 0; do { status = tx(m_e1); i++; } while (status == UCS_OK); r.func = pending_cb_dispatch; EXPECT_EQ(UCS_OK, uct_ep_pending_add(m_e1->ep(0), &r, 0)); wait_for_value(&req_count, 1, true); EXPECT_EQ(1, req_count); short_progress_loop(); uct_ep_pending_purge(m_e1->ep(0), purge_cb, NULL); } UCT_INSTANTIATE_UD_TEST_CASE(test_ud_pending)