Changeset 01ff41c in mainline for libc/generic/async.c


Ignore:
Timestamp:
2006-05-27T22:28:25Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7f5b37a
Parents:
7f9cd77
Message:

Added functions to async framework for reasonable sending asynchronous
messages.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libc/generic/async.c

    r7f9cd77 r01ff41c  
    9292#include <errno.h>
    9393
    94 static atomic_t conn_futex = FUTEX_INITIALIZER;
     94static atomic_t async_futex = FUTEX_INITIALIZER;
    9595static hash_table_t conn_hash_table;
     96
     97typedef struct {
     98        pstid_t ptid;                /**< Thread waiting for this message */
     99        int active;                  /**< If this thread is currently active */
     100        int done;                    /**< If reply was received */
     101        ipc_call_t *dataptr;         /**< Pointer where the answer data
     102                                      *   should be stored */
     103        ipcarg_t retval;
     104} amsg_t;
    96105
    97106typedef struct {
     
    116125
    117126/* Hash table functions */
    118 
    119127#define CONN_HASH_TABLE_CHAINS  32
    120128
     
    147155};
    148156
     157/*************************************************/
     158
    149159/** Try to route a call to an appropriate connection thread
    150160 *
     
    157167        unsigned long key;
    158168
    159         futex_down(&conn_futex);
     169        futex_down(&async_futex);
    160170
    161171        key = call->in_phone_hash;
    162172        hlp = hash_table_find(&conn_hash_table, &key);
    163173        if (!hlp) {
    164                 futex_up(&conn_futex);
     174                futex_up(&async_futex);
    165175                return 0;
    166176        }
     
    177187        }
    178188
    179         futex_up(&conn_futex);
     189        futex_up(&async_futex);
    180190
    181191        return 1;
     
    189199        connection_t *conn;
    190200       
    191         futex_down(&conn_futex);
     201        futex_down(&async_futex);
    192202
    193203        conn = PS_connection;
     
    204214        free(msg);
    205215       
    206         futex_up(&conn_futex);
     216        futex_up(&async_futex);
    207217        return callid;
    208218}
     
    237247
    238248        /* Remove myself from connection hash table */
    239         futex_down(&conn_futex);
     249        futex_down(&async_futex);
    240250        key = conn->in_phone_hash;
    241251        hash_table_remove(&conn_hash_table, &key, 1);
    242         futex_up(&conn_futex);
     252        futex_up(&async_futex);
    243253        /* Answer all remaining messages with ehangup */
    244254        while (!list_empty(&conn->msg_queue)) {
     
    289299        }
    290300        key = conn->in_phone_hash;
    291         futex_down(&conn_futex);
     301        futex_down(&async_futex);
    292302        /* Add connection to hash table */
    293303        hash_table_insert(&conn_hash_table, &key, &conn->link);
    294         futex_up(&conn_futex);
     304        futex_up(&async_futex);
    295305
    296306        psthread_add_ready(conn->ptid);
     
    299309}
    300310
    301 /** Handle call to a task */
     311/** Handle call that was received */
    302312static void handle_call(ipc_callid_t callid, ipc_call_t *call)
    303313{
     
    325335        while (1) {
    326336                if (psthread_schedule_next_adv(PS_FROM_MANAGER)) {
    327                         futex_up(&conn_futex); /* conn_futex is always held
     337                        futex_up(&async_futex); /* async_futex is always held
    328338                                                * when entering manager thread
    329339                                                */
     
    334344                if (callid & IPC_CALLID_ANSWERED)
    335345                        continue;
     346
    336347                handle_call(callid, &call);
    337348        }
     
    347358static int async_manager_thread(void *arg)
    348359{
    349         futex_up(&conn_futex); /* conn_futex is always locked when entering
     360        futex_up(&async_futex); /* async_futex is always locked when entering
    350361                                * manager */
    351362        async_manager();
     
    376387       
    377388}
     389
     390/** IPC handler for messages in async framework
     391 *
     392 * Notify thread that is waiting for this message, that it arrived
     393 */
     394static void reply_received(void *private, int retval,
     395                           ipc_call_t *data)
     396{
     397        amsg_t *msg = (amsg_t *) private;
     398
     399        msg->retval = retval;
     400
     401        futex_down(&async_futex);
     402        /* Copy data after futex_down, just in case the
     403         * call was detached
     404         */
     405        if (msg->dataptr)
     406                *msg->dataptr = *data;
     407       
     408        msg->done = 1;
     409        if (! msg->active) {
     410                msg->active = 1;
     411                psthread_add_ready(msg->ptid);
     412        }
     413        futex_up(&async_futex);
     414}
     415
     416/** Send message and return id of the sent message
     417 *
     418 * The return value can be used as input for async_wait() to wait
     419 * for completion.
     420 */
     421aid_t async_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
     422                   ipc_call_t *dataptr)
     423{
     424        amsg_t *msg;
     425
     426        msg = malloc(sizeof(*msg));
     427        msg->active = 1;
     428        msg->done = 0;
     429        msg->dataptr = dataptr;
     430        ipc_call_async_2(phoneid,method,arg1,arg2,msg,reply_received);
     431
     432        return (aid_t) msg;
     433}
     434
     435/** Wait for a message sent by async framework
     436 *
     437 * @param amsgid Message ID to wait for
     438 * @param retval Pointer to variable where will be stored retval
     439 *               of the answered message. If NULL, it is ignored.
     440 *
     441 */
     442void async_wait_for(aid_t amsgid, ipcarg_t *retval)
     443{
     444        amsg_t *msg = (amsg_t *) amsgid;
     445        connection_t *conn;
     446
     447        futex_down(&async_futex);
     448        if (msg->done) {
     449                futex_up(&async_futex);
     450                goto done;
     451        }
     452
     453        msg->ptid = psthread_get_id();
     454        msg->active = 0;
     455        /* Leave locked async_futex when entering this function */
     456        psthread_schedule_next_adv(PS_TO_MANAGER);
     457        /* futex is up automatically after psthread_schedule_next...*/
     458done:
     459        if (retval)
     460                *retval = msg->retval;
     461        free(msg);
     462}
Note: See TracChangeset for help on using the changeset viewer.