dapl_evd_dequeue.c revision 9517:b4839b0aa7a4
1129470Spjd/*
2129470Spjd * CDDL HEADER START
3173313Smarcel *
4173313Smarcel * The contents of this file are subject to the terms of the
5176852Sdelphij * Common Development and Distribution License (the "License").
6176852Sdelphij * You may not use this file except in compliance with the License.
7176852Sdelphij *
8176852Sdelphij * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9173313Smarcel * or http://www.opensolaris.org/os/licensing.
10173313Smarcel * See the License for the specific language governing permissions
11176852Sdelphij * and limitations under the License.
12173313Smarcel *
13179550Smarcel * When distributing Covered Code, include this CDDL HEADER in each
14173313Smarcel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15173313Smarcel * If applicable, add the following below this CDDL HEADER, with the
16173313Smarcel * fields enclosed by brackets "[]" replaced with your own identifying
17173313Smarcel * information: Portions Copyright [yyyy] [name of copyright owner]
18173313Smarcel *
19173313Smarcel * CDDL HEADER END
20173313Smarcel */
21173313Smarcel
22129470Spjd/*
23129470Spjd * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
24129470Spjd */
25173313Smarcel
26173313Smarcel/*
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
68DAT_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);
161bail:
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