Rev 1392 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1392 | Rev 1404 | ||
---|---|---|---|
Line 71... | Line 71... | ||
71 | * answer(msg); |
71 | * answer(msg); |
72 | * |
72 | * |
73 | * msg = get_msg(); |
73 | * msg = get_msg(); |
74 | * .... |
74 | * .... |
75 | * } |
75 | * } |
- | 76 | * |
|
- | 77 | * TODO: Detaching/joining dead psthreads? */ |
|
76 | */ |
78 | */ |
77 | #include <futex.h> |
79 | #include <futex.h> |
78 | #include <async.h> |
80 | #include <async.h> |
79 | #include <psthread.h> |
81 | #include <psthread.h> |
80 | #include <stdio.h> |
82 | #include <stdio.h> |
Line 97... | Line 99... | ||
97 | link_t link; |
99 | link_t link; |
98 | ipcarg_t in_phone_hash; /**< Incoming phone hash. */ |
100 | ipcarg_t in_phone_hash; /**< Incoming phone hash. */ |
99 | link_t msg_queue; /**< Messages that should be delivered to this thread */ |
101 | link_t msg_queue; /**< Messages that should be delivered to this thread */ |
100 | pstid_t ptid; /**< Thread associated with this connection */ |
102 | pstid_t ptid; /**< Thread associated with this connection */ |
101 | int active; /**< If this thread is currently active */ |
103 | int active; /**< If this thread is currently active */ |
102 | int opened; /* If the connection was accepted */ |
- | |
103 | /* Structures for connection opening packet */ |
104 | /* Structures for connection opening packet */ |
104 | ipc_callid_t callid; |
105 | ipc_callid_t callid; |
105 | ipc_call_t call; |
106 | ipc_call_t call; |
106 | } connection_t; |
107 | } connection_t; |
107 | 108 | ||
108 | __thread connection_t *PS_connection; |
109 | __thread connection_t *PS_connection; |
109 | 110 | ||
110 | /* Hash table functions */ |
111 | /* Hash table functions */ |
111 | 112 | ||
112 | #define ASYNC_HASH_TABLE_CHAINS 32 |
113 | #define CONN_HASH_TABLE_CHAINS 32 |
113 | 114 | ||
114 | static hash_index_t conn_hash(unsigned long *key) |
115 | static hash_index_t conn_hash(unsigned long *key) |
115 | { |
116 | { |
116 | assert(key); |
117 | assert(key); |
117 | return ((*key) >> 4) % ASYNC_HASH_TABLE_CHAINS; |
118 | return ((*key) >> 4) % CONN_HASH_TABLE_CHAINS; |
118 | } |
119 | } |
119 | 120 | ||
120 | static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) |
121 | static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) |
121 | { |
122 | { |
122 | connection_t *hs; |
123 | connection_t *hs; |
Line 172... | Line 173... | ||
172 | futex_up(&conn_futex); |
173 | futex_up(&conn_futex); |
173 | 174 | ||
174 | return 1; |
175 | return 1; |
175 | } |
176 | } |
176 | 177 | ||
- | 178 | /** Return new incoming message for current(thread-local) connection */ |
|
177 | ipc_callid_t async_get_call(ipc_call_t *call) |
179 | ipc_callid_t async_get_call(ipc_call_t *call) |
178 | { |
180 | { |
179 | msg_t *msg; |
181 | msg_t *msg; |
180 | ipc_callid_t callid; |
182 | ipc_callid_t callid; |
181 | connection_t *conn; |
183 | connection_t *conn; |
Line 197... | Line 199... | ||
197 | 199 | ||
198 | futex_up(&conn_futex); |
200 | futex_up(&conn_futex); |
199 | return callid; |
201 | return callid; |
200 | } |
202 | } |
201 | 203 | ||
- | 204 | /** Thread function that gets created on new connection |
|
- | 205 | * |
|
- | 206 | * This function is defined as a weak symbol - to be redefined in |
|
- | 207 | * user code. |
|
- | 208 | */ |
|
202 | void client_connection(ipc_callid_t callid, ipc_call_t *call) |
209 | void client_connection(ipc_callid_t callid, ipc_call_t *call) |
203 | { |
210 | { |
204 | printf("Got connection - no handler.\n"); |
211 | ipc_answer_fast(callid, ENOENT, 0, 0); |
205 | _exit(1); |
- | |
206 | } |
212 | } |
207 | 213 | ||
- | 214 | /** Wrapper for client connection thread |
|
- | 215 | * |
|
- | 216 | * When new connection arrives, thread with this function is created. |
|
- | 217 | * It calls client_connection and does final cleanup. |
|
- | 218 | * |
|
- | 219 | * @parameter arg Connection structure pointer |
|
- | 220 | */ |
|
208 | static int connection_thread(void *arg) |
221 | static int connection_thread(void *arg) |
209 | { |
222 | { |
- | 223 | unsigned long key; |
|
- | 224 | msg_t *msg; |
|
- | 225 | ||
210 | /* Setup thread local connection pointer */ |
226 | /* Setup thread local connection pointer */ |
211 | PS_connection = (connection_t *)arg; |
227 | PS_connection = (connection_t *)arg; |
212 | client_connection(PS_connection->callid, &PS_connection->call); |
228 | client_connection(PS_connection->callid, &PS_connection->call); |
213 | 229 | ||
- | 230 | /* Remove myself from connection hash table */ |
|
214 | futex_down(&conn_futex); |
231 | futex_down(&conn_futex); |
- | 232 | key = PS_connection->in_phone_hash; |
|
215 | /* TODO: remove myself from connection hash table */ |
233 | hash_table_remove(&conn_hash_table, &key, 1); |
216 | futex_up(&conn_futex); |
234 | futex_up(&conn_futex); |
217 | /* TODO: answer all unanswered messages in queue with |
235 | /* Answer all remaining messages with ehangup */ |
- | 236 | while (!list_empty(&PS_connection->msg_queue)) { |
|
- | 237 | msg = list_get_instance(PS_connection->msg_queue.next, msg_t, link); |
|
218 | * EHANGUP */ |
238 | list_remove(&msg->link); |
- | 239 | ipc_answer_fast(msg->callid, EHANGUP, 0, 0); |
|
- | 240 | free(msg); |
|
- | 241 | } |
|
219 | } |
242 | } |
220 | 243 | ||
221 | /** Create new thread for a new connection |
244 | /** Create new thread for a new connection |
222 | * |
245 | * |
223 | * Creates new thread for connection, fills in connection |
246 | * Creates new thread for connection, fills in connection |
Line 236... | Line 259... | ||
236 | ipc_answer_fast(callid, ENOMEM, 0, 0); |
259 | ipc_answer_fast(callid, ENOMEM, 0, 0); |
237 | return; |
260 | return; |
238 | } |
261 | } |
239 | conn->in_phone_hash = IPC_GET_ARG3(*call); |
262 | conn->in_phone_hash = IPC_GET_ARG3(*call); |
240 | list_initialize(&conn->msg_queue); |
263 | list_initialize(&conn->msg_queue); |
241 | conn->opened = 0; |
- | |
242 | conn->ptid = psthread_create(connection_thread, conn); |
264 | conn->ptid = psthread_create(connection_thread, conn); |
243 | conn->callid = callid; |
265 | conn->callid = callid; |
244 | conn->call = *call; |
266 | conn->call = *call; |
245 | conn->active = 1; /* We will activate it asap */ |
267 | conn->active = 1; /* We will activate it asap */ |
246 | list_initialize(&conn->link); |
268 | list_initialize(&conn->link); |
Line 295... | Line 317... | ||
295 | continue; |
317 | continue; |
296 | handle_call(callid, &call); |
318 | handle_call(callid, &call); |
297 | } |
319 | } |
298 | } |
320 | } |
299 | 321 | ||
- | 322 | /** Function to start async_manager as a standalone thread |
|
- | 323 | * |
|
- | 324 | * When more kernel threads are used, one async manager should |
|
- | 325 | * exist per thread. The particular implementation may change, |
|
- | 326 | * currently one async_manager is started automatically per kernel |
|
- | 327 | * thread except main thread. |
|
- | 328 | */ |
|
300 | static int async_manager_thread(void *arg) |
329 | static int async_manager_thread(void *arg) |
301 | { |
330 | { |
302 | futex_up(&conn_futex); /* conn_futex is always locked when entering |
331 | futex_up(&conn_futex); /* conn_futex is always locked when entering |
303 | * manager */ |
332 | * manager */ |
304 | async_manager(); |
333 | async_manager(); |
Line 320... | Line 349... | ||
320 | } |
349 | } |
321 | 350 | ||
322 | /** Initialize internal structures needed for async manager */ |
351 | /** Initialize internal structures needed for async manager */ |
323 | int _async_init(void) |
352 | int _async_init(void) |
324 | { |
353 | { |
325 | if (!hash_table_create(&conn_hash_table, ASYNC_HASH_TABLE_CHAINS, 1, &conn_hash_table_ops)) { |
354 | if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1, &conn_hash_table_ops)) { |
326 | printf("%s: cannot create hash table\n", "async"); |
355 | printf("%s: cannot create hash table\n", "async"); |
327 | return ENOMEM; |
356 | return ENOMEM; |
328 | } |
357 | } |
329 | 358 | ||
330 | } |
359 | } |