[DAPL2] DAPL Counters & 2.0.3 extensions to support counter retrieval.
[mirror/winof/.git] / ulp / dapl2 / dapl / common / dapl_evd_dequeue.c
1 /*\r
2  * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
3  *\r
4  * This Software is licensed under one of the following licenses:\r
5  *\r
6  * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
7  *    available from the Open Source Initiative, see\r
8  *    http://www.opensource.org/licenses/cpl.php.\r
9  *\r
10  * 2) under the terms of the "The BSD License" a copy of which is\r
11  *    available from the Open Source Initiative, see\r
12  *    http://www.opensource.org/licenses/bsd-license.php.\r
13  *\r
14  * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
15  *    copy of which is available from the Open Source Initiative, see\r
16  *    http://www.opensource.org/licenses/gpl-license.php.\r
17  *\r
18  * Licensee has the right to choose one of the above licenses.\r
19  *\r
20  * Redistributions of source code must retain the above copyright\r
21  * notice and one of the license notices.\r
22  *\r
23  * Redistributions in binary form must reproduce both the above copyright\r
24  * notice, one of the license notices in the documentation\r
25  * and/or other materials provided with the distribution.\r
26  */\r
27 \r
28 /**********************************************************************\r
29  * \r
30  * MODULE: dapl_evd_dequeue.c\r
31  *\r
32  * PURPOSE: Event Management\r
33  *\r
34  * Description:  Interfaces in this file are completely described in\r
35  *               the uDAPL 1.1 API, Chapter 6, section 3\r
36  *\r
37  * $Id:$\r
38  **********************************************************************/\r
39 \r
40 #include "dapl.h"\r
41 #include "dapl_ring_buffer_util.h"\r
42 #include "dapl_evd_util.h"\r
43 \r
44 /*\r
45  * dapl_evd_dequeue\r
46  * \r
47  * DAPL Requirements Version xxx, 6.3.2.7\r
48  * \r
49  * Remove first element from an event dispatcher\r
50  * \r
51  * Input:\r
52  *      evd_handle\r
53  * \r
54  * Output:\r
55  *      event\r
56  * \r
57  * Returns:\r
58  *      DAT_SUCCESS\r
59  *      DAT_INVALID_HANDLE\r
60  *      DAT_INVALID_PARAMETER\r
61  *      DAT_INVALID_STATE\r
62  *      DAT_QUEUE_EMPTY\r
63  */\r
64 \r
65 DAT_RETURN DAT_API dapl_evd_dequeue (\r
66     IN    DAT_EVD_HANDLE        evd_handle,\r
67     OUT   DAT_EVENT             *event)\r
68 \r
69 {\r
70     DAPL_EVD    *evd_ptr;\r
71     DAT_EVENT   *local_event;\r
72     DAT_RETURN  dat_status;\r
73 \r
74     dapl_dbg_log (DAPL_DBG_EVD_DEQUEUE,\r
75                   "dapl_evd_dequeue (%p, %p)\n",\r
76                   evd_handle, \r
77                   event);\r
78 \r
79     evd_ptr = (DAPL_EVD *)evd_handle;\r
80     dat_status = DAT_SUCCESS;\r
81 \r
82     if (DAPL_BAD_HANDLE (evd_handle, DAPL_MAGIC_EVD))\r
83     {\r
84         dat_status = DAT_ERROR (DAT_INVALID_HANDLE,0);\r
85         goto bail;\r
86     }\r
87 \r
88     if (event == NULL)\r
89     {\r
90         dat_status = DAT_ERROR (DAT_INVALID_PARAMETER,DAT_INVALID_ARG2);\r
91         goto bail;\r
92     }\r
93     DAPL_CNTR(evd_ptr, DCNT_EVD_DEQUEUE);\r
94 \r
95     /*\r
96      * We need to dequeue under lock, as the IB OS Access API\r
97      * restricts us from having multiple threads in CQ poll, and the\r
98      * DAPL 1.1 API allows multiple threads in dat_evd_dequeue()\r
99      */\r
100     dapl_os_lock ( &evd_ptr->header.lock );\r
101 \r
102     /*\r
103      * Make sure there are no other waiters and the evd is active.\r
104      * Currently this means only the OPEN state is allowed.\r
105      */\r
106     if (evd_ptr->evd_state != DAPL_EVD_STATE_OPEN || \r
107         evd_ptr->catastrophic_overflow)\r
108     {\r
109         dapl_os_unlock ( &evd_ptr->header.lock );\r
110         dat_status = DAT_ERROR (DAT_INVALID_STATE,0);\r
111         goto bail;\r
112     }\r
113 \r
114     /*\r
115      * Try the EVD rbuf first; poll from the CQ only if that's empty.\r
116      * This keeps events in order if dat_evd_wait() has copied events\r
117      * from CQ to EVD.  \r
118      */\r
119     local_event = (DAT_EVENT *)dapls_rbuf_remove (&evd_ptr->pending_event_queue);\r
120     if (local_event != NULL)\r
121     {\r
122         *event = *local_event;\r
123         dat_status = dapls_rbuf_add (&evd_ptr->free_event_queue, \r
124                                      local_event);\r
125         DAPL_CNTR(evd_ptr, DCNT_EVD_DEQUEUE_FOUND);\r
126 \r
127     }\r
128     else if (evd_ptr->ib_cq_handle != IB_INVALID_HANDLE)\r
129     {\r
130         dat_status = dapls_evd_cq_poll_to_event(evd_ptr, event);\r
131         DAPL_CNTR(evd_ptr, DCNT_EVD_DEQUEUE_POLL);\r
132     }\r
133     else\r
134     {\r
135         dat_status = DAT_ERROR (DAT_QUEUE_EMPTY,0);\r
136         DAPL_CNTR(evd_ptr, DCNT_EVD_DEQUEUE_NOT_FOUND);\r
137     }\r
138 \r
139     dapl_os_unlock ( &evd_ptr->header.lock );\r
140  bail:\r
141     dapl_dbg_log (DAPL_DBG_TYPE_RTN,\r
142                   "dapl_evd_dequeue () returns 0x%x\n", \r
143                   dat_status);\r
144 \r
145     return dat_status;\r
146 }\r
147 \r