1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 /* 32 * 33 * MODULE: dapl_evd_wait.c 34 * 35 * PURPOSE: EVENT management 36 * 37 * Description: Interfaces in this file are completely defined in 38 * the uDAPL 1.1 API specification 39 * 40 * $Id: dapl_evd_wait.c,v 1.22 2003/08/20 13:18:36 sjs2 Exp $ 41 */ 42 43 #include "dapl.h" 44 #include "dapl_evd_util.h" 45 #include "dapl_ring_buffer_util.h" 46 #include "dapl_adapter_util.h" 47 48 /* 49 * dapl_evd_wait 50 * 51 * UDAPL Requirements Version xxx, 52 * 53 * Wait, up to specified timeout, for notification event on EVD. 54 * Then return first available event. 55 * 56 * Input: 57 * evd_handle 58 * timeout 59 * 60 * Output: 61 * event 62 * 63 * Returns: 64 * DAT_SUCCESS 65 * DAT_INVALID_PARAMETER 66 * DAT_INVALID_STATE 67 */ 68 DAT_RETURN dapl_evd_wait( 69 IN DAT_EVD_HANDLE evd_handle, 70 IN DAT_TIMEOUT time_out, 71 IN DAT_COUNT threshold, 72 OUT DAT_EVENT *event, 73 OUT DAT_COUNT *nmore) 74 75 { 76 DAPL_EVD *evd_ptr; 77 DAT_RETURN dat_status; 78 DAT_EVENT *local_event; 79 DAT_BOOLEAN waitable; 80 DAPL_EVD_STATE evd_state; 81 82 dapl_dbg_log(DAPL_DBG_TYPE_API, 83 "dapl_evd_wait (%p, %d, %d, %p, %p)\n", 84 evd_handle, 85 time_out, 86 threshold, 87 event, 88 nmore); 89 90 evd_ptr = (DAPL_EVD *)evd_handle; 91 dat_status = DAT_SUCCESS; 92 93 if (DAPL_BAD_HANDLE(evd_ptr, DAPL_MAGIC_EVD)) { 94 /* 95 * We return directly rather than bailing because 96 * bailing attempts to update the evd, and we don't have 97 * one. 98 */ 99 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 0); 100 goto bail; 101 } 102 if (!event) { 103 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4); 104 goto bail; 105 } 106 if (!nmore) { 107 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5); 108 goto bail; 109 } 110 if (threshold <= 0 || 111 (threshold > 1 && 112 evd_ptr->completion_type != DAPL_EVD_STATE_THRESHOLD)) { 113 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); 114 goto bail; 115 } 116 if (evd_ptr->catastrophic_overflow) { 117 dat_status = DAT_ERROR(DAT_INVALID_STATE, 0); 118 goto bail; 119 } 120 121 dapl_dbg_log(DAPL_DBG_TYPE_EVD, 122 "dapl_evd_wait: EVD %p, CQ %p\n", 123 evd_ptr, 124 (void *)evd_ptr->ib_cq_handle); 125 126 /* 127 * Make sure there are no other waiters and the evd is active. 128 * Currently this means only the OPEN state is allowed. 129 * We need to take a lock to synchronize with dapl_evd_dequeue(). 130 */ 131 132 dapl_os_lock(&evd_ptr->header.lock); 133 waitable = evd_ptr->evd_waitable; 134 evd_state = evd_ptr->evd_state; 135 if (evd_state != DAPL_EVD_STATE_OPEN || !waitable) { 136 dapl_os_unlock(&evd_ptr->header.lock); 137 dat_status = DAT_ERROR(DAT_INVALID_STATE, 0); 138 goto bail; 139 } 140 evd_ptr->evd_state = DAPL_EVD_STATE_WAITED; 141 dapl_os_unlock(&evd_ptr->header.lock); 142 143 /* 144 * We now own the EVD, we don't have the lock anymore, 145 * because we're in the WAITED state. 146 */ 147 148 evd_ptr->threshold = threshold; 149 150 /* return pending events immediately without further polling */ 151 if (dapls_rbuf_count(&evd_ptr->pending_event_queue) > 0) { 152 evd_ptr->evd_state = DAPL_EVD_STATE_OPEN; 153 dat_status = DAT_SUCCESS; 154 } else { 155 dat_status = dapls_evd_copy_events(evd_ptr, time_out); 156 evd_ptr->evd_state = DAPL_EVD_STATE_OPEN; 157 if (DAT_GET_TYPE(dat_status) == DAT_INTERRUPTED_CALL) { 158 goto bail; 159 } 160 if (!evd_ptr->evd_waitable) { 161 /* See if we were awakened by evd_set_unwaitable */ 162 dat_status = DAT_ERROR(DAT_INVALID_STATE, 0); 163 goto bail; 164 } 165 if (dapls_rbuf_count(&evd_ptr->pending_event_queue) == 0) { 166 dat_status = DAT_ERROR(DAT_TIMEOUT_EXPIRED, 0); 167 } 168 } 169 170 if (dat_status == DAT_SUCCESS) { 171 local_event = dapls_rbuf_remove(&evd_ptr->pending_event_queue); 172 *event = *local_event; 173 dat_status = dapls_rbuf_add(&evd_ptr->free_event_queue, 174 local_event); 175 dapl_os_assert(dat_status == DAT_SUCCESS); 176 } 177 178 /* 179 * Valid if dat_status == DAT_SUCCESS || dat_status == DAT_TIMEOUT 180 * Undefined otherwise, so ok to set it. 181 */ 182 *nmore = dapls_rbuf_count(&evd_ptr->pending_event_queue); 183 184 bail: 185 dapl_dbg_log(DAPL_DBG_TYPE_RTN, 186 "dapl_evd_wait () returns 0x%x\n", 187 dat_status); 188 189 return (dat_status); 190 } 191