[WSD] wait for all WQ to return before destroying the socket.
[mirror/winof/.git] / ulp / wsd / user / sockinfo.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 2006 Mellanox Technologies.  All rights reserved.\r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  *\r
30  * $Id$\r
31  */\r
32 \r
33 #include "ibspdebug.h"\r
34 #if defined(EVENT_TRACING)\r
35 #include "sockinfo.tmh"\r
36 #endif\r
37 \r
38 #include "ibspdll.h"\r
39 \r
40 \r
41 static void\r
42 free_socket_info(\r
43         IN                              struct ibsp_socket_info         *socket_info );\r
44 \r
45 /* \r
46  * Function: create_socket_info\r
47  * \r
48  *  Description:\r
49  *    Allocates a new socket info context structure and initializes some fields.\r
50 */\r
51 struct ibsp_socket_info *\r
52 create_socket_info(\r
53         OUT                             LPINT                                           lpErrno )\r
54 {\r
55         struct ibsp_socket_info *socket_info;\r
56 \r
57         IBSP_ENTER( IBSP_DBG_SI );\r
58 \r
59         socket_info = HeapAlloc( g_ibsp.heap,\r
60                 HEAP_ZERO_MEMORY, sizeof(struct ibsp_socket_info) );\r
61         if( socket_info == NULL )\r
62         {\r
63                 IBSP_PRINT_EXIT(TRACE_LEVEL_INFORMATION, IBSP_DBG_SI,\r
64                         ("HeapAlloc() failed: %d\n", GetLastError()) );\r
65                 *lpErrno = WSAENOBUFS;\r
66                 return NULL;\r
67         }\r
68 \r
69         cl_spinlock_construct( &socket_info->mutex1 );\r
70         cl_spinlock_construct( &socket_info->send_lock );\r
71         cl_spinlock_construct( &socket_info->recv_lock );\r
72         cl_qlist_init( &socket_info->mr_list );\r
73         cl_qlist_init( &socket_info->listen.list );\r
74 \r
75         if( cl_spinlock_init( &socket_info->mutex1 ) != CL_SUCCESS )\r
76                 goto err;\r
77 \r
78         if( cl_spinlock_init( &socket_info->send_lock ) != CL_SUCCESS )\r
79                 goto err;\r
80 \r
81         if( cl_spinlock_init( &socket_info->recv_lock ) != CL_SUCCESS )\r
82                 goto err;\r
83 \r
84 #ifdef _DEBUG_\r
85         memset( socket_info->recv_wr, 0x38, sizeof(socket_info->send_wr) );\r
86         memset( socket_info->recv_wr, 0x38, sizeof(socket_info->recv_wr) );\r
87         memset( socket_info->recv_wr, 0x38, sizeof(socket_info->dup_wr) );\r
88 #endif\r
89 \r
90         socket_info->switch_socket =\r
91                 g_ibsp.up_call_table.lpWPUCreateSocketHandle(\r
92                 0, (DWORD_PTR)socket_info, lpErrno );\r
93 \r
94         if( socket_info->switch_socket == INVALID_SOCKET )\r
95         {\r
96                 IBSP_ERROR( ("WPUCreateSocketHandle() failed: %d", *lpErrno) );\r
97 err:\r
98                 free_socket_info( socket_info );\r
99                 IBSP_EXIT( IBSP_DBG_SI );\r
100                 return NULL;\r
101         }\r
102 \r
103         STAT_INC( wpusocket_num );\r
104 \r
105         /*\r
106          * Preset to 1, IBSPCloseSocket will decrement it, and switch socket\r
107          * will be freed once it goes to zero.\r
108          */\r
109         socket_info->ref_cnt1 = 1;\r
110 \r
111         IBSP_PRINT(TRACE_LEVEL_INFORMATION, IBSP_DBG_SI, ("socket_info (%p), switch socket (%p)\n",\r
112                 socket_info, (void*)socket_info->switch_socket) );\r
113 \r
114         IBSP_EXIT( IBSP_DBG_SI );\r
115         return socket_info;\r
116 }\r
117 \r
118 \r
119 static void\r
120 free_socket_info(\r
121         IN                              struct ibsp_socket_info         *p_socket )\r
122 {\r
123         int             ret, error;\r
124 \r
125         if( p_socket->switch_socket != INVALID_SOCKET )\r
126         {\r
127                 /* ref_cnt hit zero - destroy the switch socket. */\r
128                 IBSP_PRINT(TRACE_LEVEL_INFORMATION, IBSP_DBG_SI,\r
129                         ("socket=0x%p calling lpWPUCloseSocketHandle=0x%p\n",\r
130                         p_socket, (void*)p_socket->switch_socket) );\r
131 \r
132                 ret = g_ibsp.up_call_table.lpWPUCloseSocketHandle(\r
133                         p_socket->switch_socket, &error );\r
134                 if( ret == SOCKET_ERROR )\r
135                 {\r
136                         IBSP_ERROR( ("WPUCloseSocketHandle failed: %d\n", error) );\r
137                 }\r
138                 else\r
139                 {\r
140                         STAT_DEC( wpusocket_num );\r
141                 }\r
142                 p_socket->switch_socket = INVALID_SOCKET;\r
143         }\r
144 \r
145         CL_ASSERT( !p_socket->qp );\r
146         CL_ASSERT( !p_socket->conn_item.p_map );\r
147         CL_ASSERT(!p_socket->send_cnt && !p_socket->recv_cnt);\r
148         cl_spinlock_destroy( &p_socket->mutex1 );\r
149 \r
150         cl_spinlock_destroy( &p_socket->send_lock );\r
151         cl_spinlock_destroy( &p_socket->recv_lock );\r
152 \r
153         HeapFree( g_ibsp.heap, 0, p_socket );\r
154 }\r
155 \r
156 \r
157 /* \r
158  * Function: deref_sock_info\r
159  * \r
160  * Description:\r
161  *      This routine decrements a socket context's reference count, and if\r
162  *      it reaches zero, frees the socket context structure.\r
163  */\r
164 void AL_API\r
165 deref_socket_info(\r
166         IN                              struct ibsp_socket_info         *p_socket )\r
167 {\r
168         IBSP_ENTER( IBSP_DBG_SI );\r
169 \r
170         if( !cl_atomic_dec( &p_socket->ref_cnt1 ) )\r
171         {\r
172                 free_socket_info( p_socket );\r
173                 IBSP_PRINT(TRACE_LEVEL_INFORMATION, IBSP_DBG_SI, ("Freed socket_info (%p)\n", p_socket) );\r
174         }\r
175         IBSP_EXIT( IBSP_DBG_SI );\r
176 }\r