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 2007 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 /* 32 * 33 * MODULE: dapl_evd_dequeue.c 34 * 35 * PURPOSE: Event Management 36 * 37 * Description: Interfaces in this file are completely described in 38 * the uDAPL 1.1 API, Chapter 6, section 3 39 * 40 * $Id: dapl_evd_dequeue.c,v 1.9 2003/07/30 18:13:38 hobie16 Exp $ 41 */ 42 43 #include "dapl.h" 44 #include "dapl_ring_buffer_util.h" 45 #include "dapl_evd_util.h" 46 47 /* 48 * dapl_evd_dequeue 49 * 50 * DAPL Requirements Version xxx, 6.3.2.7 51 * 52 * Remove first element from an event dispatcher 53 * 54 * Input: 55 * evd_handle 56 * 57 * Output: 58 * event 59 * 60 * Returns: 61 * DAT_SUCCESS 62 * DAT_INVALID_HANDLE 63 * DAT_INVALID_PARAMETER 64 * DAT_INVALID_STATE 65 * DAT_QUEUE_EMPTY 66 */ 67 68 DAT_RETURN dapl_evd_dequeue( 69 IN DAT_EVD_HANDLE evd_handle, 70 OUT DAT_EVENT *event) 71 { 72 DAPL_EVD *evd_ptr; 73 DAT_EVENT *local_event; 74 DAT_RETURN dat_status; 75 76 dapl_dbg_log(DAPL_DBG_TYPE_API, 77 "dapl_evd_dequeue (%p, %p)\n", 78 evd_handle, 79 event); 80 81 evd_ptr = (DAPL_EVD *)evd_handle; 82 dat_status = DAT_SUCCESS; 83 84 if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) { 85 dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 0); 86 goto bail; 87 } 88 89 if (event == NULL) { 90 dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); 91 goto bail; 92 } 93 94 /* 95 * We need to dequeue under lock, as the IB OS Access API 96 * restricts us from having multiple threads in CQ poll, and the 97 * DAPL 1.1 API allows multiple threads in dat_evd_dequeue() 98 */ 99 dapl_os_lock(&evd_ptr->header.lock); 100 101 /* 102 * Make sure there are no other waiters and the evd is active. 103 * Currently this means only the OPEN state is allowed. 104 */ 105 if (evd_ptr->evd_state != DAPL_EVD_STATE_OPEN || 106 evd_ptr->catastrophic_overflow) { 107 dapl_os_unlock(&evd_ptr->header.lock); 108 dat_status = DAT_ERROR(DAT_INVALID_STATE, 0); 109 goto bail; 110 } 111 112 /* 113 * Try the EVD rbuf first; poll from the CQ only if that's empty. 114 * This keeps events in order if dat_evd_wait() has copied events 115 * from CQ to EVD. 116 */ 117 if (evd_ptr->pending_event_queue.head != 118 evd_ptr->pending_event_queue.tail) { 119 local_event = (DAT_EVENT *) 120 dapls_rbuf_remove(&evd_ptr->pending_event_queue); 121 if (local_event != NULL) { 122 *event = *local_event; 123 dat_status = dapls_rbuf_add(&evd_ptr->free_event_queue, 124 local_event); 125 } else { /* should never happen */ 126 dat_status = DAT_ERROR(DAT_INTERNAL_ERROR, 0); 127 } 128 } else if (evd_ptr->ib_cq_handle == IB_INVALID_HANDLE) { 129 dat_status = DAT_ERROR(DAT_QUEUE_EMPTY, 0); 130 } else if ((evd_ptr->evd_flags & (DAT_EVD_CONNECTION_FLAG | 131 DAT_EVD_CR_FLAG | DAT_EVD_ASYNC_FLAG)) == 0) { 132 /* 133 * No need to drop into kernel, just check the CQ. 134 */ 135 dat_status = dapls_evd_cq_poll_to_event(evd_ptr, event); 136 } else { 137 /* poll for events with threshold and timeout both 0 */ 138 evd_ptr->threshold = 0; 139 140 dapl_os_unlock(&evd_ptr->header.lock); 141 dat_status = dapls_evd_copy_events(evd_ptr, 0); 142 if (dat_status != DAT_SUCCESS) { 143 dat_status = DAT_ERROR(DAT_QUEUE_EMPTY, 0); 144 goto bail; 145 } 146 147 dapl_os_lock(&evd_ptr->header.lock); 148 149 local_event = (DAT_EVENT *)dapls_rbuf_remove( 150 &evd_ptr->pending_event_queue); 151 if (local_event != NULL) { 152 *event = *local_event; 153 dat_status = dapls_rbuf_add(&evd_ptr->free_event_queue, 154 local_event); 155 } else { /* still didn't find anything */ 156 dat_status = DAT_ERROR(DAT_QUEUE_EMPTY, 0); 157 } 158 } 159 160 dapl_os_unlock(&evd_ptr->header.lock); 161 bail: 162 dapl_dbg_log(DAPL_DBG_TYPE_RTN, 163 "dapl_evd_dequeue () returns 0x%x\n", 164 dat_status); 165 166 return (dat_status); 167 } 168