Rev 2486 | Rev 2490 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2486 | Rev 2488 | ||
---|---|---|---|
Line 104... | Line 104... | ||
104 | 104 | ||
105 | atomic_t async_futex = FUTEX_INITIALIZER; |
105 | atomic_t async_futex = FUTEX_INITIALIZER; |
106 | static hash_table_t conn_hash_table; |
106 | static hash_table_t conn_hash_table; |
107 | static LIST_INITIALIZE(timeout_list); |
107 | static LIST_INITIALIZE(timeout_list); |
108 | 108 | ||
- | 109 | /** Structures of this type represent a waiting fibril. */ |
|
109 | typedef struct { |
110 | typedef struct { |
110 | /** Expiration time for waiting fibril. */ |
111 | /** Expiration time. */ |
111 | struct timeval expires; |
112 | struct timeval expires; |
112 | /** If true, this struct is in the timeout list. */ |
113 | /** If true, this struct is in the timeout list. */ |
113 | int inlist; |
114 | int inlist; |
- | 115 | /** Timeout list link. */ |
|
114 | link_t link; |
116 | link_t link; |
115 | 117 | ||
116 | /** Fibril waiting for this message. */ |
118 | /** Fibril waiting for this message. */ |
117 | fid_t fid; |
119 | fid_t fid; |
118 | /** If this fibril is currently active. */ |
120 | /** If true, this fibril is currently active. */ |
119 | int active; |
121 | int active; |
120 | /** If true, we timed out. */ |
122 | /** If true, we have timed out. */ |
121 | int timedout; |
123 | int timedout; |
122 | } awaiter_t; |
124 | } awaiter_t; |
123 | 125 | ||
124 | typedef struct { |
126 | typedef struct { |
125 | awaiter_t wdata; |
127 | awaiter_t wdata; |
- | 128 | ||
- | 129 | /** If reply was received. */ |
|
- | 130 | int done; |
|
- | 131 | /** Pointer to where the answer data is stored. */ |
|
- | 132 | ipc_call_t *dataptr; |
|
126 | 133 | ||
127 | int done; /**< If reply was received */ |
- | |
128 | ipc_call_t *dataptr; /**< Pointer where the answer data |
- | |
129 | * is stored */ |
- | |
130 | ipcarg_t retval; |
134 | ipcarg_t retval; |
131 | } amsg_t; |
135 | } amsg_t; |
132 | 136 | ||
133 | typedef struct { |
137 | typedef struct { |
134 | link_t link; |
138 | link_t link; |
Line 137... | Line 141... | ||
137 | } msg_t; |
141 | } msg_t; |
138 | 142 | ||
139 | typedef struct { |
143 | typedef struct { |
140 | awaiter_t wdata; |
144 | awaiter_t wdata; |
141 | 145 | ||
142 | link_t link; /**< Hash table link. */ |
146 | /** Hash table link. */ |
- | 147 | link_t link; |
|
- | 148 | ||
143 | ipcarg_t in_phone_hash; /**< Incoming phone hash. */ |
149 | /** Incoming phone hash. */ |
- | 150 | ipcarg_t in_phone_hash; |
|
- | 151 | ||
144 | link_t msg_queue; /**< Messages that should be delivered |
152 | /** Messages that should be delivered to this fibril. */ |
145 | * to this fibril. */ |
153 | link_t msg_queue; |
- | 154 | ||
146 | /* Structures for connection opening packet */ |
155 | /** Identification of the opening call. */ |
147 | ipc_callid_t callid; |
156 | ipc_callid_t callid; |
- | 157 | /** Call data of the opening call. */ |
|
148 | ipc_call_t call; |
158 | ipc_call_t call; |
- | 159 | ||
149 | ipc_callid_t close_callid; /* Identification of closing packet. */ |
160 | /** Identification of the closing call. */ |
- | 161 | ipc_callid_t close_callid; |
|
- | 162 | ||
- | 163 | /** Fibril function that will be used to handle the connection. */ |
|
150 | void (*cfibril)(ipc_callid_t, ipc_call_t *); |
164 | void (*cfibril)(ipc_callid_t, ipc_call_t *); |
151 | } connection_t; |
165 | } connection_t; |
152 | 166 | ||
153 | /** Identifier of the incoming connection handled by the current fibril. */ |
167 | /** Identifier of the incoming connection handled by the current fibril. */ |
154 | __thread connection_t *FIBRIL_connection; |
168 | __thread connection_t *FIBRIL_connection; |
- | 169 | ||
155 | /** If true, it is forbidden to use async_req functions and |
170 | /** If true, it is forbidden to use async_req functions and all preemption is |
156 | * all preemption is disabled */ |
171 | * disabled. */ |
157 | __thread int in_interrupt_handler; |
172 | __thread int in_interrupt_handler; |
158 | 173 | ||
159 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); |
174 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); |
160 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); |
175 | static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); |
161 | static async_client_conn_t client_connection = default_client_connection; |
176 | static async_client_conn_t client_connection = default_client_connection; |
162 | static async_client_conn_t interrupt_received = default_interrupt_received; |
177 | static async_client_conn_t interrupt_received = default_interrupt_received; |
163 | 178 | ||
164 | /* Hash table functions */ |
- | |
165 | #define CONN_HASH_TABLE_CHAINS 32 |
179 | #define CONN_HASH_TABLE_CHAINS 32 |
166 | 180 | ||
- | 181 | /** Compute hash into the connection hash table based on the source phone hash. |
|
- | 182 | * |
|
- | 183 | * @param key Pointer to source phone hash. |
|
- | 184 | * |
|
- | 185 | * @return Index into the connection hash table. |
|
- | 186 | */ |
|
167 | static hash_index_t conn_hash(unsigned long *key) |
187 | static hash_index_t conn_hash(unsigned long *key) |
168 | { |
188 | { |
169 | assert(key); |
189 | assert(key); |
170 | return ((*key) >> 4) % CONN_HASH_TABLE_CHAINS; |
190 | return ((*key) >> 4) % CONN_HASH_TABLE_CHAINS; |
171 | } |
191 | } |
172 | 192 | ||
- | 193 | /** Compare hash table item with a key. |
|
- | 194 | * |
|
- | 195 | * @param key Array containing the source phone hash as the only item. |
|
- | 196 | * @param keys Expected 1 but ignored. |
|
- | 197 | * @param item Connection hash table item. |
|
- | 198 | * |
|
- | 199 | * @return True on match, false otherwise. |
|
- | 200 | */ |
|
173 | static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) |
201 | static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) |
174 | { |
202 | { |
175 | connection_t *hs; |
203 | connection_t *hs; |
176 | 204 | ||
177 | hs = hash_table_get_instance(item, connection_t, link); |
205 | hs = hash_table_get_instance(item, connection_t, link); |
178 | 206 | ||
179 | return key[0] == hs->in_phone_hash; |
207 | return key[0] == hs->in_phone_hash; |
180 | } |
208 | } |
181 | 209 | ||
- | 210 | /** Connection hash table removal callback function. |
|
- | 211 | * |
|
- | 212 | * This function is called whenever a connection is removed from the connection |
|
- | 213 | * hash table. |
|
- | 214 | * |
|
- | 215 | * @param item Connection hash table item being removed. |
|
- | 216 | */ |
|
182 | static void conn_remove(link_t *item) |
217 | static void conn_remove(link_t *item) |
183 | { |
218 | { |
184 | free(hash_table_get_instance(item, connection_t, link)); |
219 | free(hash_table_get_instance(item, connection_t, link)); |
185 | } |
220 | } |
186 | 221 | ||
187 | 222 | ||
188 | /** Operations for NS hash table. */ |
223 | /** Operations for the connection hash table. */ |
189 | static hash_table_operations_t conn_hash_table_ops = { |
224 | static hash_table_operations_t conn_hash_table_ops = { |
190 | .hash = conn_hash, |
225 | .hash = conn_hash, |
191 | .compare = conn_compare, |
226 | .compare = conn_compare, |
192 | .remove_callback = conn_remove |
227 | .remove_callback = conn_remove |
193 | }; |
228 | }; |
194 | 229 | ||
195 | /** Insert sort timeout msg into timeouts list |
230 | /** Sort in current fibril's timeout request. |
196 | * |
231 | * |
- | 232 | * @param wd Wait data of the current fibril. |
|
197 | */ |
233 | */ |
198 | static void insert_timeout(awaiter_t *wd) |
234 | static void insert_timeout(awaiter_t *wd) |
199 | { |
235 | { |
200 | link_t *tmp; |
236 | link_t *tmp; |
201 | awaiter_t *cur; |
237 | awaiter_t *cur; |
Line 211... | Line 247... | ||
211 | tmp = tmp->next; |
247 | tmp = tmp->next; |
212 | } |
248 | } |
213 | list_append(&wd->link, tmp); |
249 | list_append(&wd->link, tmp); |
214 | } |
250 | } |
215 | 251 | ||
216 | /** Try to route a call to an appropriate connection fibril |
252 | /** Try to route a call to an appropriate connection fibril. |
217 | * |
253 | * |
218 | */ |
254 | */ |
219 | static int route_call(ipc_callid_t callid, ipc_call_t *call) |
255 | static int route_call(ipc_callid_t callid, ipc_call_t *call) |
220 | { |
256 | { |
221 | connection_t *conn; |
257 | connection_t *conn; |
Line 255... | Line 291... | ||
255 | futex_up(&async_futex); |
291 | futex_up(&async_futex); |
256 | 292 | ||
257 | return 1; |
293 | return 1; |
258 | } |
294 | } |
259 | 295 | ||
260 | /** Return new incoming message for the current (fibril-local) connection */ |
296 | /** Return new incoming message for the current (fibril-local) connection. |
- | 297 | * |
|
- | 298 | * @param call Storage where the incoming call data will be stored. |
|
- | 299 | * @param usecs Timeout in microseconds. Zero denotes no timeout. |
|
- | 300 | * |
|
- | 301 | * @return If no timeout was specified, then a hash of the |
|
- | 302 | * incoming call is returned. If a timeout is specified, |
|
- | 303 | * then a hash of the incoming call is returned unless |
|
- | 304 | * the timeout expires prior to receiving a message. In |
|
- | 305 | * that case zero is returned. |
|
- | 306 | */ |
|
261 | ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) |
307 | ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs) |
262 | { |
308 | { |
263 | msg_t *msg; |
309 | msg_t *msg; |
264 | ipc_callid_t callid; |
310 | ipc_callid_t callid; |
265 | connection_t *conn; |
311 | connection_t *conn; |
Line 278... | Line 324... | ||
278 | gettimeofday(&conn->wdata.expires, NULL); |
324 | gettimeofday(&conn->wdata.expires, NULL); |
279 | tv_add(&conn->wdata.expires, usecs); |
325 | tv_add(&conn->wdata.expires, usecs); |
280 | } else { |
326 | } else { |
281 | conn->wdata.inlist = 0; |
327 | conn->wdata.inlist = 0; |
282 | } |
328 | } |
283 | /* If nothing in queue, wait until something appears */ |
329 | /* If nothing in queue, wait until something arrives */ |
284 | while (list_empty(&conn->msg_queue)) { |
330 | while (list_empty(&conn->msg_queue)) { |
285 | if (usecs) |
331 | if (usecs) |
286 | insert_timeout(&conn->wdata); |
332 | insert_timeout(&conn->wdata); |
287 | 333 | ||
288 | conn->wdata.active = 0; |
334 | conn->wdata.active = 0; |
289 | fibril_schedule_next_adv(FIBRIL_TO_MANAGER); |
335 | fibril_schedule_next_adv(FIBRIL_TO_MANAGER); |
- | 336 | /* |
|
290 | /* Futex is up after getting back from async_manager |
337 | * Futex is up after getting back from async_manager get it |
291 | * get it again */ |
338 | * again. |
- | 339 | */ |
|
292 | futex_down(&async_futex); |
340 | futex_down(&async_futex); |
293 | if (usecs && conn->wdata.timedout && |
341 | if (usecs && conn->wdata.timedout && |
294 | list_empty(&conn->msg_queue)) { |
342 | list_empty(&conn->msg_queue)) { |
295 | /* If we timed out-> exit */ |
343 | /* If we timed out -> exit */ |
296 | futex_up(&async_futex); |
344 | futex_up(&async_futex); |
297 | return 0; |
345 | return 0; |
298 | } |
346 | } |
299 | } |
347 | } |
300 | 348 | ||
Line 308... | Line 356... | ||
308 | return callid; |
356 | return callid; |
309 | } |
357 | } |
310 | 358 | ||
311 | /** Fibril function that gets created on new connection |
359 | /** Fibril function that gets created on new connection |
312 | * |
360 | * |
313 | * This function is defined as a weak symbol - to be redefined in |
361 | * This function is defined as a weak symbol - to be redefined in user code. |
314 | * user code. |
- | |
315 | */ |
362 | */ |
316 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) |
363 | static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) |
317 | { |
364 | { |
318 | ipc_answer_fast(callid, ENOENT, 0, 0); |
365 | ipc_answer_fast(callid, ENOENT, 0, 0); |
319 | } |
366 | } |