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 | } |