Changeset 936351c1 in mainline for libipc/generic/ipc.c


Ignore:
Timestamp:
2006-03-14T23:48:33Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d73942c
Parents:
4f34b6a
Message:

Completed asynchronous IPC.
Fixed sbrk.
Cleared some unnecessary defines in malloc.
Changed u8 * to char * in list.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libipc/generic/ipc.c

    r4f34b6a r936351c1  
    2929#include <ipc.h>
    3030#include <libc.h>
    31 
    32 int ipc_call_sync(int phoneid, sysarg_t method, sysarg_t arg1,
    33                   sysarg_t *result)
     31#include <malloc.h>
     32#include <errno.h>
     33#include <list.h>
     34#include <stdio.h>
     35#include <unistd.h>
     36
     37/** Structure used for keeping track of sent async msgs
     38 * and queing unsent msgs
     39 *
     40 */
     41typedef struct {
     42        link_t list;
     43
     44        ipc_async_callback_t callback;
     45        void *private;
     46        union {
     47                ipc_callid_t callid;
     48                struct {
     49                        int phoneid;
     50                        ipc_data_t data;
     51                } msg;
     52        }u;
     53} async_call_t;
     54
     55LIST_INITIALIZE(dispatched_calls);
     56LIST_INITIALIZE(queued_calls);
     57
     58int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1,
     59                  ipcarg_t *result)
    3460{
    3561        ipc_data_t resdata;
    3662        int callres;
    3763       
    38         callres = __SYSCALL4(SYS_IPC_CALL_SYNC, phoneid, method, arg1,
     64        callres = __SYSCALL4(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
    3965                             (sysarg_t)&resdata);
    4066        if (callres)
     
    4571}
    4672
    47 int ipc_call_sync_3(int phoneid, sysarg_t method, sysarg_t arg1,
    48                     sysarg_t arg2, sysarg_t arg3,
    49                     sysarg_t *result1, sysarg_t *result2, sysarg_t *result3)
     73int ipc_call_sync_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
     74                    ipcarg_t arg2, ipcarg_t arg3,
     75                    ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3)
    5076{
    5177        ipc_data_t data;
     
    5783        IPC_SET_ARG3(data, arg3);
    5884
    59         callres = __SYSCALL2(SYS_IPC_CALL_SYNC_MEDIUM, phoneid, (sysarg_t)&data);
     85        callres = __SYSCALL2(SYS_IPC_CALL_SYNC, phoneid, (sysarg_t)&data);
    6086        if (callres)
    6187                return callres;
     
    7096}
    7197
     98/** Syscall to send asynchronous message */
     99static  ipc_callid_t _ipc_call_async(int phoneid, ipc_data_t *data)
     100{
     101        return __SYSCALL2(SYS_IPC_CALL_ASYNC, phoneid, (sysarg_t)data);
     102}
     103
    72104/** Send asynchronous message
    73105 *
     
    75107 * - if message cannot be temporarily sent, add to queue
    76108 */
    77 void ipc_call_async_2(int phoneid, sysarg_t method, sysarg_t arg1,
    78                       sysarg_t arg2,
     109void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1,
     110                      ipcarg_t arg2, void *private,
    79111                      ipc_async_callback_t callback)
    80112{
     113        async_call_t *call;
    81114        ipc_callid_t callid;
    82         ipc_data_t data; /* Data storage for saving calls */
    83 
    84         callid = __SYSCALL4(SYS_IPC_CALL_ASYNC, phoneid, method, arg1, arg2);
     115
     116        call = malloc(sizeof(*call));
     117        if (!call) {
     118                callback(private, ENOMEM, NULL);
     119        }
     120               
     121        callid = __SYSCALL4(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, arg2);
    85122        if (callid == IPC_CALLRET_FATAL) {
    86123                /* Call asynchronous handler with error code */
    87                 IPC_SET_RETVAL(data, IPC_CALLRET_FATAL);
    88                 callback(&data);
     124                IPC_SET_RETVAL(call->u.msg.data, ENOENT);
     125                callback(private, ENOENT, NULL);
     126                free(call);
    89127                return;
    90128        }
     129
     130        call->callback = callback;
     131        call->private = private;
     132
    91133        if (callid == IPC_CALLRET_TEMPORARY) {
    92134                /* Add asynchronous call to queue of non-dispatched async calls */
    93                 IPC_SET_METHOD(data, method);
    94                 IPC_SET_ARG1(data, arg1);
    95                 IPC_SET_ARG2(data, arg2);
    96                
     135                call->u.msg.phoneid = phoneid;
     136                IPC_SET_METHOD(call->u.msg.data, method);
     137                IPC_SET_ARG1(call->u.msg.data, arg1);
     138                IPC_SET_ARG2(call->u.msg.data, arg2);
     139
     140                list_append(&call->list, &queued_calls);
    97141                return;
    98142        }
    99         /* Add callid to list of dispatched calls */
    100        
     143        call->u.callid = callid;
     144        /* Add call to list of dispatched calls */
     145        list_append(&call->list, &dispatched_calls);
    101146}
    102147
    103148
    104149/** Send answer to a received call */
    105 void ipc_answer(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
    106                 sysarg_t arg2)
     150void ipc_answer(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
     151                ipcarg_t arg2)
    107152{
    108153        __SYSCALL4(SYS_IPC_ANSWER, callid, retval, arg1, arg2);
     
    116161}
    117162
     163/** Try to dispatch queed calls from async queue */
     164static void try_dispatch_queued_calls(void)
     165{
     166        async_call_t *call;
     167        ipc_callid_t callid;
     168
     169        while (!list_empty(&queued_calls)) {
     170                call = list_get_instance(queued_calls.next, async_call_t,
     171                                         list);
     172
     173                callid = _ipc_call_async(call->u.msg.phoneid,
     174                                         &call->u.msg.data);
     175                if (callid == IPC_CALLRET_TEMPORARY)
     176                        break;
     177                list_remove(&call->list);
     178                if (callid == IPC_CALLRET_FATAL) {
     179                        call->callback(call->private, ENOENT, NULL);
     180                        free(call);
     181                } else {
     182                        call->u.callid = callid;
     183                        list_append(&call->list, &dispatched_calls);
     184                }
     185        }
     186}
     187
     188/** Handle received answer
     189 *
     190 * TODO: Make it use hash table
     191 *
     192 * @param callid Callid (with first bit set) of the answered call
     193 */
     194static void handle_answer(ipc_callid_t callid, ipc_data_t *data)
     195{
     196        link_t *item;
     197        async_call_t *call;
     198
     199        callid &= ~IPC_CALLID_ANSWERED;
     200       
     201        for (item = dispatched_calls.next; item != &dispatched_calls;
     202             item = item->next) {
     203                call = list_get_instance(item, async_call_t, list);
     204                if (call->u.callid == callid) {
     205                        list_remove(&call->list);
     206                        call->callback(call->private,
     207                                       IPC_GET_RETVAL(*data),
     208                                       data);
     209                        return;
     210                }
     211        }
     212        printf("Received unidentified answer: %P!!!\n", callid);
     213}
     214
     215
    118216/** Wait for IPC call and return
    119217 *
    120218 * - dispatch ASYNC reoutines in the background
     219 * @param data Space where the message is stored
     220 * @return Callid or 0 if nothing available and started with
     221 *         IPC_WAIT_NONBLOCKING
    121222 */
    122223int ipc_wait_for_call(ipc_data_t *data, int flags)
     
    125226
    126227        do {
    127                 /* Try to dispatch non-dispatched async calls */
     228                try_dispatch_queued_calls();
     229
    128230                callid = _ipc_wait_for_call(data, flags);
    129                 if (callid & IPC_CALLID_ANSWERED) {
    130                         /* TODO: Call async answer handler */
    131                 }
     231                /* Handle received answers */
     232                if (callid & IPC_CALLID_ANSWERED)
     233                        handle_answer(callid, data);
    132234        } while (callid & IPC_CALLID_ANSWERED);
     235
    133236        return callid;
    134237}
Note: See TracChangeset for help on using the changeset viewer.