From: stansmith Date: Tue, 26 Jun 2007 23:16:10 +0000 (+0000) Subject: [DAPL] missing patch, Do not miss IB completions! X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=79993ba33b223805f2ee12cbf473418d9e155268;p=~shefty%2Frdma-win.git [DAPL] missing patch, Do not miss IB completions! git-svn-id: svn://openib.tc.cornell.edu/gen1@717 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- diff --git a/trunk/ulp/dapl/dapl/common/dapl_evd_wait.c b/trunk/ulp/dapl/dapl/common/dapl_evd_wait.c index 71f3bb88..ac3e3f48 100644 --- a/trunk/ulp/dapl/dapl/common/dapl_evd_wait.c +++ b/trunk/ulp/dapl/dapl/common/dapl_evd_wait.c @@ -1,26 +1,27 @@ /* * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved. * - * This Software is licensed under either one of the following two licenses: + * This Software is licensed under one of the following licenses: * * 1) under the terms of the "Common Public License 1.0" a copy of which is - * in the file LICENSE.txt in the root directory. The license is also * available from the Open Source Initiative, see * http://www.opensource.org/licenses/cpl.php. - * OR * - * 2) under the terms of the "The BSD License" a copy of which is in the file - * LICENSE2.txt in the root directory. The license is also available from - * the Open Source Initiative, see + * 2) under the terms of the "The BSD License" a copy of which is + * available from the Open Source Initiative, see * http://www.opensource.org/licenses/bsd-license.php. * - * Licensee has the right to choose either one of the above two licenses. + * 3) under the terms of the "GNU General Public License (GPL) Version 2" a + * copy of which is available from the Open Source Initiative, see + * http://www.opensource.org/licenses/gpl-license.php. + * + * Licensee has the right to choose one of the above licenses. * - * Redistributions of source code must retain both the above copyright - * notice and either one of the license notices. + * Redistributions of source code must retain the above copyright + * notice and one of the license notices. * * Redistributions in binary form must reproduce both the above copyright - * notice, either one of the license notices in the documentation + * notice, one of the license notices in the documentation * and/or other materials provided with the distribution. */ @@ -33,7 +34,7 @@ * Description: Interfaces in this file are completely defined in * the uDAPL 1.1 API specification * - * $Id$ + * $Id:$ **********************************************************************/ #include "dapl.h" @@ -73,9 +74,9 @@ DAT_RETURN dapl_evd_wait ( DAPL_EVD *evd_ptr; DAT_RETURN dat_status; DAT_EVENT *local_event; - DAT_BOOLEAN waitable,notify_needed; + DAT_BOOLEAN notify_requested = DAT_FALSE; + DAT_BOOLEAN waitable; DAPL_EVD_STATE evd_state; - DAT_COUNT total_events,new_events; dapl_dbg_log (DAPL_DBG_TYPE_API, "dapl_evd_wait (%p, %d, %d, %p, %p)\n", @@ -123,10 +124,11 @@ DAT_RETURN dapl_evd_wait ( } dapl_dbg_log (DAPL_DBG_TYPE_EVD, - "dapl_evd_wait: EVD %p, CQ %p, Timeout %d, Threshold %d\n", - evd_ptr,(void *)evd_ptr->ib_cq_handle, time_out, threshold); + "dapl_evd_wait: EVD %p, CQ %p\n", + evd_ptr, + (void *)evd_ptr->ib_cq_handle); - /* + /* * Make sure there are no other waiters and the evd is active. * Currently this means only the OPEN state is allowed. * Do this atomically. We need to take a lock to synchronize @@ -143,12 +145,24 @@ DAT_RETURN dapl_evd_wait ( (DAT_COUNT) DAPL_EVD_STATE_OPEN, (DAT_COUNT) DAPL_EVD_STATE_WAITED ); dapl_os_unlock ( &evd_ptr->header.lock ); - if ( evd_state != DAPL_EVD_STATE_OPEN || !waitable) + + if ( evd_state != DAPL_EVD_STATE_OPEN ) { + /* Bogus state, bail out */ dat_status = DAT_ERROR (DAT_INVALID_STATE,0); goto bail; } + if (!waitable) + { + /* This EVD is not waitable, reset the state and bail */ + (void) dapl_os_atomic_assign ((DAPL_ATOMIC *)&evd_ptr->evd_state, + (DAT_COUNT) DAPL_EVD_STATE_WAITED, + evd_state); + dat_status = DAT_ERROR (DAT_INVALID_STATE, DAT_INVALID_STATE_EVD_UNWAITABLE); + goto bail; + } + /* * We now own the EVD, even though we don't have the lock anymore, * because we're in the WAITED state. @@ -156,120 +170,92 @@ DAT_RETURN dapl_evd_wait ( evd_ptr->threshold = threshold; - for (;;) + for (;;) { - /* - * Ideally we'd just check the number of entries on the CQ, but - * we don't have a way to do that. Because we have to set *nmore - * at some point in this routine, we'll need to do this copy - * sometime even if threshold == 1. - * - * For connection evd or async evd, the function checks and - * return right away if the ib_cq_handle associate with these evd - * equal to IB_INVALID_HANDLE - */ - /* Logic to prevent missing completion between copy_cq (poll) - * and completion_notify (re-arm) - */ - notify_needed = TRUE; - new_events = 0; - while (TRUE) - { - dapls_evd_copy_cq(evd_ptr); /* poll for new completions */ - total_events = dapls_rbuf_count (&evd_ptr->pending_event_queue); - new_events = total_events - new_events; - if (total_events >= threshold || - (!new_events && notify_needed == FALSE)) - { - break; - } - - /* - * Do not enable the completion notification if this evd is not - * a DTO_EVD or RMR_BIND_EVD - */ - if ( (evd_ptr->evd_flags & DAT_EVD_DTO_FLAG) || - (evd_ptr->evd_flags & DAT_EVD_RMR_BIND_FLAG) ) - { - - if (evd_ptr->completion_type == DAPL_EVD_STATE_SOLICITED_WAIT) - { - dat_status = dapls_ib_completion_notify ( - evd_ptr->header.owner_ia->hca_ptr->ib_hca_handle, - evd_ptr->ib_cq_handle, - IB_NOTIFY_ON_SOLIC_COMP); - } - else - { - dat_status = dapls_ib_n_completions_notify ( - evd_ptr->header.owner_ia->hca_ptr->ib_hca_handle, - evd_ptr->ib_cq_handle, - threshold - total_events ); - } - - notify_needed = FALSE; - new_events = total_events; - - /* FIXME report error */ - dapl_os_assert(dat_status == DAT_SUCCESS); - } - else - { - break; - } - - } /* while completions < threshold, and rearm needed */ - - if (total_events >= threshold) - { - break; - } - - /* - * Unused by poster; it has no way to tell how many - * items are on the queue without copying them over to the - * EVD queue, and we're the only ones allowed to dequeue - * from the CQ for synchronization/locking reasons. - */ - evd_ptr->threshold = threshold; - - if (evd_ptr->cq_wait_obj_handle) - { - dat_status = dapls_ib_wait_object_wait ( - evd_ptr->cq_wait_obj_handle, time_out ); - } - else - { - dat_status = dapl_os_wait_object_wait ( - &evd_ptr->wait_object, time_out ); - } - - /* See if we were awakened by evd_set_unwaitable */ - if ( !evd_ptr->evd_waitable ) - { - dat_status = DAT_ERROR (DAT_INVALID_STATE,0); - } - - if (dat_status != DAT_SUCCESS) - { -#if 1 - dapls_evd_copy_cq(evd_ptr); /* poll */ - dapl_dbg_log (DAPL_DBG_TYPE_EVD, - "dapl_evd_wait: WAKEUP ERROR: EVD %p, CQ %p, events? %d\n", - evd_ptr,(void *)evd_ptr->ib_cq_handle, - dapls_rbuf_count(&evd_ptr->pending_event_queue) ); + /* + * Ideally we'd just check the number of entries on the CQ, but + * we don't have a way to do that. Because we have to set *nmore + * at some point in this routine, we'll need to do this copy + * sometime even if threshold == 1. + * + * For connection evd or async evd, the function checks and + * return right away if the ib_cq_handle associate with these evd + * equal to IB_INVALID_HANDLE + */ + dapls_evd_copy_cq(evd_ptr); + + if (dapls_rbuf_count(&evd_ptr->pending_event_queue) >= threshold) + { + break; + } + + /* + * Do not enable the completion notification if this evd is not + * a DTO_EVD or RMR_BIND_EVD + */ + if ( (!notify_requested) && + ((evd_ptr->evd_flags & DAT_EVD_DTO_FLAG) || + (evd_ptr->evd_flags & DAT_EVD_RMR_BIND_FLAG)) ) + { + dat_status = dapls_ib_completion_notify ( + evd_ptr->header.owner_ia->hca_ptr->ib_hca_handle, + evd_ptr->ib_cq_handle, + (evd_ptr->completion_type == DAPL_EVD_STATE_SOLICITED_WAIT) ? + IB_NOTIFY_ON_SOLIC_COMP : IB_NOTIFY_ON_NEXT_COMP ); + + DAPL_CNTR(DCNT_EVD_WAIT_CMP_NTFY); + /* FIXME report error */ + dapl_os_assert(dat_status == DAT_SUCCESS); + + notify_requested = DAT_TRUE; + + /* Try again. */ + continue; + } + + + /* + * Unused by poster; it has no way to tell how many + * items are on the queue without copying them over to the + * EVD queue, and we're the only ones allowed to dequeue + * from the CQ for synchronization/locking reasons. + */ + evd_ptr->threshold = threshold; + + DAPL_CNTR(DCNT_EVD_WAIT_BLOCKED); + +#ifdef CQ_WAIT_OBJECT + if (evd_ptr->cq_wait_obj_handle) + dat_status = dapls_ib_wait_object_wait ( + evd_ptr->cq_wait_obj_handle, time_out ); + else #endif + dat_status = dapl_os_wait_object_wait ( + &evd_ptr->wait_object, time_out ); + /* + * FIXME: if the thread loops around and waits again + * the time_out value needs to be updated. + */ - /* - * If the status is DAT_TIMEOUT, we'll break out of the - * loop, *not* dequeue an event (because dat_status - * != DAT_SUCCESS), set *nmore (as we should for timeout) - * and return DAT_TIMEOUT. - */ - break; - } - - } /* for(;;) */ + notify_requested = DAT_FALSE; /* We've used it up. */ + + /* See if we were awakened by evd_set_unwaitable */ + if ( !evd_ptr->evd_waitable ) + { + dat_status = DAT_ERROR (DAT_INVALID_STATE,0); + } + + if (dat_status != DAT_SUCCESS) + { + /* + * If the status is DAT_TIMEOUT, we'll break out of the + * loop, *not* dequeue an event (because dat_status + * != DAT_SUCCESS), set *nmore (as we should for timeout) + * and return DAT_TIMEOUT. + */ + break; + } + } evd_ptr->evd_state = DAPL_EVD_STATE_OPEN; @@ -286,7 +272,7 @@ DAT_RETURN dapl_evd_wait ( */ *nmore = dapls_rbuf_count(&evd_ptr->pending_event_queue); -bail: + bail: dapl_dbg_log (DAPL_DBG_TYPE_RTN, "dapl_evd_wait () returns 0x%x\n", dat_status);