Subversion Repositories HelenOS-historic

Rev

Rev 1392 | Rev 1405 | Go to most recent revision | 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
}