Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/generic/ipc.c

    r10477601 r228e490  
    4545#include <errno.h>
    4646#include <adt/list.h>
     47#include <stdio.h>
     48#include <unistd.h>
    4749#include <futex.h>
     50#include <kernel/synch/synch.h>
     51#include <async.h>
    4852#include <fibril.h>
     53#include <assert.h>
    4954
    5055/**
    51  * Structures of this type are used for keeping track
    52  * of sent asynchronous calls and queing unsent calls.
     56 * Structures of this type are used for keeping track of sent asynchronous calls
     57 * and queing unsent calls.
    5358 */
    5459typedef struct {
    5560        link_t list;
    56        
     61
    5762        ipc_async_callback_t callback;
    5863        void *private;
    59        
    6064        union {
    6165                ipc_callid_t callid;
     
    6569                } msg;
    6670        } u;
    67        
    68         /** Fibril waiting for sending this call. */
    69         fid_t fid;
     71        fid_t fid;      /**< Fibril waiting for sending this call. */
    7072} async_call_t;
    7173
     
    7476/** List of asynchronous calls that were not accepted by kernel.
    7577 *
    76  * Protected by async_futex, because if the call is not accepted
    77  * by the kernel, the async framework is used automatically.
    78  *
     78 * It is protected by async_futex, because if the call cannot be sent into the
     79 * kernel, the async framework is used automatically.
    7980 */
    8081LIST_INITIALIZE(queued_calls);
     
    8283static atomic_t ipc_futex = FUTEX_INITIALIZER;
    8384
    84 /** Fast synchronous call.
    85  *
    86  * Only three payload arguments can be passed using this function. However,
    87  * this function is faster than the generic ipc_call_sync_slow() because
    88  * the payload is passed directly in registers.
    89  *
    90  * @param phoneid Phone handle for the call.
    91  * @param method  Requested method.
    92  * @param arg1    Service-defined payload argument.
    93  * @param arg2    Service-defined payload argument.
    94  * @param arg3    Service-defined payload argument.
    95  * @param result1 If non-NULL, the return ARG1 will be stored there.
    96  * @param result2 If non-NULL, the return ARG2 will be stored there.
    97  * @param result3 If non-NULL, the return ARG3 will be stored there.
    98  * @param result4 If non-NULL, the return ARG4 will be stored there.
    99  * @param result5 If non-NULL, the return ARG5 will be stored there.
    100  *
    101  * @return Negative values representing IPC errors.
    102  * @return Otherwise the RETVAL of the answer.
    103  *
    104  */
    105 int ipc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1,
    106     sysarg_t arg2, sysarg_t arg3, sysarg_t *result1, sysarg_t *result2,
    107     sysarg_t *result3, sysarg_t *result4, sysarg_t *result5)
     85/** Make a fast synchronous call.
     86 *
     87 * Only three payload arguments can be passed using this function. However, this
     88 * function is faster than the generic ipc_call_sync_slow() because the payload
     89 * is passed directly in registers.
     90 *
     91 * @param phoneid       Phone handle for the call.
     92 * @param method        Requested method.
     93 * @param arg1          Service-defined payload argument.
     94 * @param arg2          Service-defined payload argument.
     95 * @param arg3          Service-defined payload argument.
     96 * @param result1       If non-NULL, the return ARG1 will be stored there.
     97 * @param result2       If non-NULL, the return ARG2 will be stored there.
     98 * @param result3       If non-NULL, the return ARG3 will be stored there.
     99 * @param result4       If non-NULL, the return ARG4 will be stored there.
     100 * @param result5       If non-NULL, the return ARG5 will be stored there.
     101 *
     102 * @return              Negative values represent errors returned by IPC.
     103 *                      Otherwise the RETVAL of the answer is returned.
     104 */
     105int
     106ipc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1, sysarg_t arg2,
     107    sysarg_t arg3, sysarg_t *result1, sysarg_t *result2, sysarg_t *result3,
     108    sysarg_t *result4, sysarg_t *result5)
    108109{
    109110        ipc_call_t resdata;
    110         int callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
     111        int callres;
     112       
     113        callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
    111114            arg2, arg3, (sysarg_t) &resdata);
    112115        if (callres)
    113116                return callres;
    114        
    115117        if (result1)
    116118                *result1 = IPC_GET_ARG1(resdata);
     
    123125        if (result5)
    124126                *result5 = IPC_GET_ARG5(resdata);
    125        
     127
    126128        return IPC_GET_RETVAL(resdata);
    127129}
    128130
    129 /** Synchronous call transmitting 5 arguments of payload.
     131/** Make a synchronous call transmitting 5 arguments of payload.
    130132 *
    131133 * @param phoneid Phone handle for the call.
     
    142144 * @param result5 If non-NULL, storage for the fifth return argument.
    143145 *
    144  * @return Negative values representing IPC errors.
    145  * @return Otherwise the RETVAL of the answer.
    146  *
    147  */
    148 int ipc_call_sync_slow(int phoneid, sysarg_t imethod, sysarg_t arg1,
    149     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
    150     sysarg_t *result1, sysarg_t *result2, sysarg_t *result3, sysarg_t *result4,
    151     sysarg_t *result5)
     146 * @return Negative value means IPC error.
     147 *         Otherwise the RETVAL of the answer.
     148 *
     149 */
     150int
     151ipc_call_sync_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
     152    sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *result1,
     153    sysarg_t *result2, sysarg_t *result3, sysarg_t *result4, sysarg_t *result5)
    152154{
    153155        ipc_call_t data;
     
    179181}
    180182
    181 /** Send asynchronous message via syscall.
     183/** Syscall to send asynchronous message.
    182184 *
    183185 * @param phoneid Phone handle for the call.
     
    187189 *
    188190 */
    189 static ipc_callid_t ipc_call_async_internal(int phoneid, ipc_call_t *data)
     191static ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data)
    190192{
    191193        return __SYSCALL2(SYS_IPC_CALL_ASYNC_SLOW, phoneid, (sysarg_t) data);
    192194}
    193195
    194 /** Prolog for ipc_call_async_*() functions.
    195  *
    196  * @param private  Argument for the answer/error callback.
    197  * @param callback Answer/error callback.
    198  *
    199  * @return New, partially initialized async_call structure or NULL.
    200  *
     196/** Prolog to ipc_call_async_*() functions.
     197 *
     198 * @param private       Argument for the answer/error callback.
     199 * @param callback      Answer/error callback.
     200 *
     201 * @return              New, partially initialized async_call structure or NULL.
    201202 */
    202203static inline async_call_t *ipc_prepare_async(void *private,
    203204    ipc_async_callback_t callback)
    204205{
    205         async_call_t *call =
    206             (async_call_t *) malloc(sizeof(async_call_t));
     206        async_call_t *call;
     207
     208        call = malloc(sizeof(*call));
    207209        if (!call) {
    208210                if (callback)
    209211                        callback(private, ENOMEM, NULL);
    210                
    211212                return NULL;
    212213        }
    213        
    214214        call->callback = callback;
    215215        call->private = private;
    216        
     216
    217217        return call;
    218218}
    219219
    220 /** Epilog for ipc_call_async_*() functions.
    221  *
    222  * @param callid      Value returned by the SYS_IPC_CALL_ASYNC_* syscall.
    223  * @param phoneid     Phone handle through which the call was made.
    224  * @param call        Structure returned by ipc_prepare_async().
    225  * @param can_preempt If true, the current fibril can be preempted
    226  *                    in this call.
    227  *
     220/** Epilogue of ipc_call_async_*() functions.
     221 *
     222 * @param callid        Value returned by the SYS_IPC_CALL_ASYNC_* syscall.
     223 * @param phoneid       Phone handle through which the call was made.
     224 * @param call          async_call structure returned by ipc_prepare_async().
     225 * @param can_preempt   If non-zero, the current fibril can be preempted in this
     226 *                      call.
    228227 */
    229228static inline void ipc_finish_async(ipc_callid_t callid, int phoneid,
    230     async_call_t *call, bool can_preempt)
    231 {
    232         if (!call) {
    233                 /* Nothing to do regardless if failed or not */
     229    async_call_t *call, int can_preempt)
     230{
     231        if (!call) { /* Nothing to do regardless if failed or not */
    234232                futex_up(&ipc_futex);
    235233                return;
    236234        }
    237        
     235
    238236        if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
    239237                futex_up(&ipc_futex);
    240                
    241238                /* Call asynchronous handler with error code */
    242239                if (call->callback)
    243240                        call->callback(call->private, ENOENT, NULL);
    244                
    245241                free(call);
    246242                return;
    247243        }
    248        
     244
    249245        if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
    250246                futex_up(&ipc_futex);
    251                
     247
    252248                call->u.msg.phoneid = phoneid;
    253249               
    254250                futex_down(&async_futex);
    255251                list_append(&call->list, &queued_calls);
    256                
     252
    257253                if (can_preempt) {
    258254                        call->fid = fibril_get_id();
     
    263259                        futex_up(&async_futex);
    264260                }
    265                
    266261                return;
    267262        }
    268        
    269263        call->u.callid = callid;
    270        
    271264        /* Add call to the list of dispatched calls */
    272265        list_append(&call->list, &dispatched_calls);
    273266        futex_up(&ipc_futex);
    274 }
    275 
    276 /** Fast asynchronous call.
     267       
     268}
     269
     270/** Make a fast asynchronous call.
    277271 *
    278272 * This function can only handle four arguments of payload. It is, however,
     
    280274 *
    281275 * Note that this function is a void function.
    282  *
    283  * During normal operation, answering this call will trigger the callback.
    284  * In case of fatal error, the callback handler is called with the proper
    285  * error code. If the call cannot be temporarily made, it is queued.
     276 * During normal opertation, answering this call will trigger the callback.
     277 * In case of fatal error, call the callback handler with the proper error code.
     278 * If the call cannot be temporarily made, queue it.
    286279 *
    287280 * @param phoneid     Phone handle for the call.
     
    293286 * @param private     Argument to be passed to the answer/error callback.
    294287 * @param callback    Answer or error callback.
    295  * @param can_preempt If true, the current fibril will be preempted in
     288 * @param can_preempt If non-zero, the current fibril will be preempted in
    296289 *                    case the kernel temporarily refuses to accept more
    297290 *                    asynchronous calls.
     
    300293void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1,
    301294    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private,
    302     ipc_async_callback_t callback, bool can_preempt)
     295    ipc_async_callback_t callback, int can_preempt)
    303296{
    304297        async_call_t *call = NULL;
     
    311304       
    312305        /*
    313          * We need to make sure that we get callid
    314          * before another thread accesses the queue again.
     306         * We need to make sure that we get callid before another thread
     307         * accesses the queue again.
    315308         */
    316        
    317309        futex_down(&ipc_futex);
    318310        ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid,
     
    325317                                return;
    326318                }
    327                
    328319                IPC_SET_IMETHOD(call->u.msg.data, imethod);
    329320                IPC_SET_ARG1(call->u.msg.data, arg1);
     
    331322                IPC_SET_ARG3(call->u.msg.data, arg3);
    332323                IPC_SET_ARG4(call->u.msg.data, arg4);
    333                
    334324                /*
    335325                 * To achieve deterministic behavior, we always zero out the
    336326                 * arguments that are beyond the limits of the fast version.
    337327                 */
    338                
    339328                IPC_SET_ARG5(call->u.msg.data, 0);
    340329        }
    341        
    342330        ipc_finish_async(callid, phoneid, call, can_preempt);
    343331}
    344332
    345 /** Asynchronous call transmitting the entire payload.
     333/** Make an asynchronous call transmitting the entire payload.
    346334 *
    347335 * Note that this function is a void function.
    348  *
    349  * During normal operation, answering this call will trigger the callback.
    350  * In case of fatal error, the callback handler is called with the proper
    351  * error code. If the call cannot be temporarily made, it is queued.
     336 * During normal opertation, answering this call will trigger the callback.
     337 * In case of fatal error, call the callback handler with the proper error code.
     338 * If the call cannot be temporarily made, queue it.
    352339 *
    353340 * @param phoneid     Phone handle for the call.
     
    360347 * @param private     Argument to be passed to the answer/error callback.
    361348 * @param callback    Answer or error callback.
    362  * @param can_preempt If true, the current fibril will be preempted in
     349 * @param can_preempt If non-zero, the current fibril will be preempted in
    363350 *                    case the kernel temporarily refuses to accept more
    364351 *                    asynchronous calls.
     
    367354void ipc_call_async_slow(int phoneid, sysarg_t imethod, sysarg_t arg1,
    368355    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, void *private,
    369     ipc_async_callback_t callback, bool can_preempt)
    370 {
    371         async_call_t *call = ipc_prepare_async(private, callback);
     356    ipc_async_callback_t callback, int can_preempt)
     357{
     358        async_call_t *call;
     359        ipc_callid_t callid;
     360
     361        call = ipc_prepare_async(private, callback);
    372362        if (!call)
    373363                return;
    374        
     364
    375365        IPC_SET_IMETHOD(call->u.msg.data, imethod);
    376366        IPC_SET_ARG1(call->u.msg.data, arg1);
     
    379369        IPC_SET_ARG4(call->u.msg.data, arg4);
    380370        IPC_SET_ARG5(call->u.msg.data, arg5);
    381        
    382371        /*
    383          * We need to make sure that we get callid
    384          * before another threadaccesses the queue again.
     372         * We need to make sure that we get callid before another thread
     373         * accesses the queue again.
    385374         */
    386        
    387375        futex_down(&ipc_futex);
    388         ipc_callid_t callid =
    389             ipc_call_async_internal(phoneid, &call->u.msg.data);
    390        
     376        callid = _ipc_call_async(phoneid, &call->u.msg.data);
     377
    391378        ipc_finish_async(callid, phoneid, call, can_preempt);
    392379}
    393380
    394 /** Answer received call (fast version).
     381
     382/** Answer a received call - fast version.
    395383 *
    396384 * The fast answer makes use of passing retval and first four arguments in
    397385 * registers. If you need to return more, use the ipc_answer_slow() instead.
    398386 *
    399  * @param callid Hash of the call being answered.
    400  * @param retval Return value.
    401  * @param arg1   First return argument.
    402  * @param arg2   Second return argument.
    403  * @param arg3   Third return argument.
    404  * @param arg4   Fourth return argument.
    405  *
    406  * @return Zero on success.
    407  * @return Value from @ref errno.h on failure.
    408  *
     387 * @param callid        Hash of the call being answered.
     388 * @param retval        Return value.
     389 * @param arg1          First return argument.
     390 * @param arg2          Second return argument.
     391 * @param arg3          Third return argument.
     392 * @param arg4          Fourth return argument.
     393 *
     394 * @return              Zero on success or a value from @ref errno.h on failure.
    409395 */
    410396sysarg_t ipc_answer_fast(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     
    415401}
    416402
    417 /** Answer received call (entire payload).
    418  *
    419  * @param callid Hash of the call being answered.
    420  * @param retval Return value.
    421  * @param arg1   First return argument.
    422  * @param arg2   Second return argument.
    423  * @param arg3   Third return argument.
    424  * @param arg4   Fourth return argument.
    425  * @param arg5   Fifth return argument.
    426  *
    427  * @return Zero on success.
    428  * @return Value from @ref errno.h on failure.
    429  *
     403/** Answer a received call - slow full version.
     404 *
     405 * @param callid        Hash of the call being answered.
     406 * @param retval        Return value.
     407 * @param arg1          First return argument.
     408 * @param arg2          Second return argument.
     409 * @param arg3          Third return argument.
     410 * @param arg4          Fourth return argument.
     411 * @param arg5          Fifth return argument.
     412 *
     413 * @return              Zero on success or a value from @ref errno.h on failure.
    430414 */
    431415sysarg_t ipc_answer_slow(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     
    433417{
    434418        ipc_call_t data;
    435        
     419
    436420        IPC_SET_RETVAL(data, retval);
    437421        IPC_SET_ARG1(data, arg1);
     
    440424        IPC_SET_ARG4(data, arg4);
    441425        IPC_SET_ARG5(data, arg5);
    442        
     426
    443427        return __SYSCALL2(SYS_IPC_ANSWER_SLOW, callid, (sysarg_t) &data);
    444428}
    445429
    446 /** Try to dispatch queued calls from the async queue.
    447  *
    448  */
    449 static void dispatch_queued_calls(void)
    450 {
     430
     431/** Try to dispatch queued calls from the async queue. */
     432static void try_dispatch_queued_calls(void)
     433{
     434        async_call_t *call;
     435        ipc_callid_t callid;
     436
    451437        /** @todo
    452          * Integrate intelligently ipc_futex so that it is locked during
    453          * ipc_call_async_*() until it is added to dispatched_calls.
     438         * Integrate intelligently ipc_futex, so that it is locked during
     439         * ipc_call_async_*(), until it is added to dispatched_calls.
    454440         */
    455        
    456441        futex_down(&async_futex);
    457        
    458442        while (!list_empty(&queued_calls)) {
    459                 async_call_t *call =
    460                     list_get_instance(queued_calls.next, async_call_t, list);
    461                 ipc_callid_t callid =
    462                     ipc_call_async_internal(call->u.msg.phoneid, &call->u.msg.data);
    463                
    464                 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY)
     443                call = list_get_instance(queued_calls.next, async_call_t, list);
     444                callid = _ipc_call_async(call->u.msg.phoneid,
     445                    &call->u.msg.data);
     446                if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
    465447                        break;
    466                
     448                }
    467449                list_remove(&call->list);
    468                
     450
    469451                futex_up(&async_futex);
    470                
    471452                if (call->fid)
    472453                        fibril_add_ready(call->fid);
     
    475456                        if (call->callback)
    476457                                call->callback(call->private, ENOENT, NULL);
    477                        
    478458                        free(call);
    479459                } else {
    480460                        call->u.callid = callid;
    481                        
    482461                        futex_down(&ipc_futex);
    483462                        list_append(&call->list, &dispatched_calls);
    484463                        futex_up(&ipc_futex);
    485464                }
    486                
    487465                futex_down(&async_futex);
    488466        }
    489        
    490467        futex_up(&async_futex);
    491468}
    492469
    493 /** Handle received answer.
     470/** Handle a received answer.
    494471 *
    495472 * Find the hash of the answer and call the answer callback.
    496473 *
    497  * The answer has the same hash as the request OR'ed with
    498  * the IPC_CALLID_ANSWERED bit.
    499  *
    500  * @todo Use hash table.
    501  *
    502  * @param callid Hash of the received answer.
    503  * @param data   Call data of the answer.
    504  *
     474 * @todo Make it use hash table.
     475 *
     476 * @param callid        Hash of the received answer.
     477 *                      The answer has the same hash as the request OR'ed with
     478 *                      the IPC_CALLID_ANSWERED bit.
     479 * @param data          Call data of the answer.
    505480 */
    506481static void handle_answer(ipc_callid_t callid, ipc_call_t *data)
    507482{
     483        link_t *item;
     484        async_call_t *call;
     485
    508486        callid &= ~IPC_CALLID_ANSWERED;
    509487       
    510488        futex_down(&ipc_futex);
    511        
    512         link_t *item;
    513489        for (item = dispatched_calls.next; item != &dispatched_calls;
    514490            item = item->next) {
    515                 async_call_t *call =
    516                     list_get_instance(item, async_call_t, list);
    517                
     491                call = list_get_instance(item, async_call_t, list);
    518492                if (call->u.callid == callid) {
    519493                        list_remove(&call->list);
    520                        
    521494                        futex_up(&ipc_futex);
    522                        
    523495                        if (call->callback)
    524                                 call->callback(call->private,
     496                                call->callback(call->private, 
    525497                                    IPC_GET_RETVAL(*data), data);
    526                        
    527498                        free(call);
    528499                        return;
    529500                }
    530501        }
    531        
    532502        futex_up(&ipc_futex);
    533503}
    534504
    535 /** Wait for first IPC call to come.
    536  *
    537  * @param call  Incoming call storage.
    538  * @param usec  Timeout in microseconds
    539  * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking).
    540  *
    541  * @return Hash of the call. Note that certain bits have special
    542  *         meaning: IPC_CALLID_ANSWERED is set in an answer
    543  *         and IPC_CALLID_NOTIFICATION is used for notifications.
    544  *
    545  */
    546 ipc_callid_t ipc_wait_cycle(ipc_call_t *call, sysarg_t usec,
    547     unsigned int flags)
    548 {
    549         ipc_callid_t callid =
    550             __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
    551        
     505
     506/** Wait for a first call to come.
     507 *
     508 * @param call          Storage where the incoming call data will be stored.
     509 * @param usec          Timeout in microseconds
     510 * @param flags         Flags passed to SYS_IPC_WAIT (blocking, nonblocking).
     511 *
     512 * @return              Hash of the call. Note that certain bits have special
     513 *                      meaning. IPC_CALLID_ANSWERED will be set in an answer
     514 *                      and IPC_CALLID_NOTIFICATION is used for notifications.
     515 *                     
     516 */
     517ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags)
     518{
     519        ipc_callid_t callid;
     520
     521        callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);
    552522        /* Handle received answers */
    553523        if (callid & IPC_CALLID_ANSWERED) {
    554524                handle_answer(callid, call);
    555                 dispatch_queued_calls();
     525                try_dispatch_queued_calls();
    556526        }
    557        
     527
    558528        return callid;
    559529}
    560530
    561 /** Interrupt one thread of this task from waiting for IPC.
    562  *
    563  */
    564 void ipc_poke(void)
    565 {
    566         __SYSCALL0(SYS_IPC_POKE);
    567 }
    568 
    569 /** Wait for first IPC call to come.
    570  *
    571  * Only requests are returned, answers are processed internally.
    572  *
    573  * @param call Incoming call storage.
    574  * @param usec Timeout in microseconds
    575  *
    576  * @return Hash of the call.
    577  *
    578  */
    579 ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, sysarg_t usec)
     531/** Wait some time for an IPC call.
     532 *
     533 * The call will return after an answer is received.
     534 *
     535 * @param call          Storage where the incoming call data will be stored.
     536 * @param usec          Timeout in microseconds.
     537 *
     538 * @return              Hash of the answer.
     539 */
     540ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec)
    580541{
    581542        ipc_callid_t callid;
    582        
     543
    583544        do {
    584545                callid = ipc_wait_cycle(call, usec, SYNCH_FLAGS_NONE);
    585546        } while (callid & IPC_CALLID_ANSWERED);
    586        
     547
    587548        return callid;
    588549}
     
    590551/** Check if there is an IPC call waiting to be picked up.
    591552 *
    592  * Only requests are returned, answers are processed internally.
    593  *
    594  * @param call Incoming call storage.
    595  *
    596  * @return Hash of the call.
    597  *
     553 * @param call          Storage where the incoming call will be stored.
     554 * @return              Hash of the answer.
    598555 */
    599556ipc_callid_t ipc_trywait_for_call(ipc_call_t *call)
    600557{
    601558        ipc_callid_t callid;
    602        
     559
    603560        do {
    604561                callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT,
    605562                    SYNCH_FLAGS_NON_BLOCKING);
    606563        } while (callid & IPC_CALLID_ANSWERED);
    607        
     564
    608565        return callid;
    609566}
    610567
    611 /** Request callback connection.
    612  *
    613  * The @a taskhash and @a phonehash identifiers returned
    614  * by the kernel can be used for connection tracking.
    615  *
    616  * @param phoneid   Phone handle used for contacting the other side.
    617  * @param arg1      User defined argument.
    618  * @param arg2      User defined argument.
    619  * @param arg3      User defined argument.
    620  * @param taskhash  Opaque identifier of the client task.
    621  * @param phonehash Opaque identifier of the phone that will
    622  *                  be used for incoming calls.
    623  *
    624  * @return Zero on success or a negative error code.
    625  *
    626  */
    627 int ipc_connect_to_me(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
    628     sysarg_t *taskhash, sysarg_t *phonehash)
     568/** Interrupt one thread of this task from waiting for IPC. */
     569void ipc_poke(void)
     570{
     571        __SYSCALL0(SYS_IPC_POKE);
     572}
     573
     574/** Ask destination to do a callback connection.
     575 *
     576 * @param phoneid       Phone handle used for contacting the other side.
     577 * @param arg1          Service-defined argument.
     578 * @param arg2          Service-defined argument.
     579 * @param arg3          Service-defined argument.
     580 * @param phonehash     Storage where the library will store an opaque
     581 *                      identifier of the phone that will be used for incoming
     582 *                      calls. This identifier can be used for connection
     583 *                      tracking.
     584 *
     585 * @return              Zero on success or a negative error code.
     586 */
     587int ipc_connect_to_me(int phoneid, int arg1, int arg2, int arg3,
     588    sysarg_t *phonehash)
    629589{
    630590        return ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2,
    631             arg3, NULL, NULL, NULL, taskhash, phonehash);
    632 }
    633 
    634 /** Request new connection.
    635  *
    636  * @param phoneid Phone handle used for contacting the other side.
    637  * @param arg1    User defined argument.
    638  * @param arg2    User defined argument.
    639  * @param arg3    User defined argument.
    640  *
    641  * @return New phone handle on success or a negative error code.
    642  *
    643  */
    644 int ipc_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
     591            arg3, NULL, NULL, NULL, NULL, phonehash);
     592}
     593
     594/** Ask through phone for a new connection to some service.
     595 *
     596 * @param phoneid       Phone handle used for contacting the other side.
     597 * @param arg1          User defined argument.
     598 * @param arg2          User defined argument.
     599 * @param arg3          User defined argument.
     600 *
     601 * @return              New phone handle on success or a negative error code.
     602 */
     603int ipc_connect_me_to(int phoneid, int arg1, int arg2, int arg3)
    645604{
    646605        sysarg_t newphid;
    647         int res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
     606        int res;
     607
     608        res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
    648609            NULL, NULL, NULL, NULL, &newphid);
    649610        if (res)
    650611                return res;
    651        
    652612        return newphid;
    653613}
    654614
    655 /** Request new connection (blocking)
     615/** Ask through phone for a new connection to some service.
    656616 *
    657617 * If the connection is not available at the moment, the
    658  * call should block. This has to be, however, implemented
    659  * on the server side.
    660  *
    661  * @param phoneid Phone handle used for contacting the other side.
    662  * @param arg1    User defined argument.
    663  * @param arg2    User defined argument.
    664  * @param arg3    User defined argument.
    665  *
    666  * @return New phone handle on success or a negative error code.
    667  *
    668  */
    669 int ipc_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
    670     sysarg_t arg3)
     618 * call will block.
     619 *
     620 * @param phoneid       Phone handle used for contacting the other side.
     621 * @param arg1          User defined argument.
     622 * @param arg2          User defined argument.
     623 * @param arg3          User defined argument.
     624 *
     625 * @return              New phone handle on success or a negative error code.
     626 */
     627int ipc_connect_me_to_blocking(int phoneid, int arg1, int arg2, int arg3)
    671628{
    672629        sysarg_t newphid;
    673         int res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
     630        int res;
     631
     632        res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
    674633            IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
    675634        if (res)
    676635                return res;
    677        
    678636        return newphid;
    679637}
     
    681639/** Hang up a phone.
    682640 *
    683  * @param phoneid Handle of the phone to be hung up.
    684  *
    685  * @return Zero on success or a negative error code.
    686  *
     641 * @param phoneid       Handle of the phone to be hung up.
     642 *
     643 * @return              Zero on success or a negative error code.
    687644 */
    688645int ipc_hangup(int phoneid)
     
    691648}
    692649
     650/** Register IRQ notification.
     651 *
     652 * @param inr           IRQ number.
     653 * @param devno         Device number of the device generating inr.
     654 * @param method        Use this method for notifying me.
     655 * @param ucode         Top-half pseudocode handler.
     656 *
     657 * @return              Value returned by the kernel.
     658 */
     659int ipc_register_irq(int inr, int devno, int method, irq_code_t *ucode)
     660{
     661        return __SYSCALL4(SYS_IPC_REGISTER_IRQ, inr, devno, method,
     662            (sysarg_t) ucode);
     663}
     664
     665/** Unregister IRQ notification.
     666 *
     667 * @param inr           IRQ number.
     668 * @param devno         Device number of the device generating inr.
     669 *
     670 * @return              Value returned by the kernel.
     671 */
     672int ipc_unregister_irq(int inr, int devno)
     673{
     674        return __SYSCALL2(SYS_IPC_UNREGISTER_IRQ, inr, devno);
     675}
     676
    693677/** Forward a received call to another destination.
    694  *
    695  * For non-system methods, the old method, arg1 and arg2 are rewritten
    696  * by the new values. For system methods, the new method, arg1 and arg2
    697  * are written to the old arg1, arg2 and arg3, respectivelly. Calls with
    698  * immutable methods are forwarded verbatim.
    699678 *
    700679 * @param callid  Hash of the call to forward.
     
    707686 * @return Zero on success or an error code.
    708687 *
    709  */
    710 int ipc_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
    711     sysarg_t arg1, sysarg_t arg2, unsigned int mode)
     688 * For non-system methods, the old method, arg1 and arg2 are rewritten by the
     689 * new values. For system methods, the new method, arg1 and arg2 are written
     690 * to the old arg1, arg2 and arg3, respectivelly. Calls with immutable
     691 * methods are forwarded verbatim.
     692 */
     693int ipc_forward_fast(ipc_callid_t callid, int phoneid, int imethod,
     694    sysarg_t arg1, sysarg_t arg2, int mode)
    712695{
    713696        return __SYSCALL6(SYS_IPC_FORWARD_FAST, callid, phoneid, imethod, arg1,
     
    715698}
    716699
    717 int ipc_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
     700
     701int ipc_forward_slow(ipc_callid_t callid, int phoneid, int imethod,
    718702    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
    719     unsigned int mode)
     703    int mode)
    720704{
    721705        ipc_call_t data;
     
    728712        IPC_SET_ARG5(data, arg5);
    729713       
    730         return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data,
    731             mode);
    732 }
    733 
    734 /** Wrapper for IPC_M_SHARE_IN calls.
    735  *
    736  * @param phoneid Phone that will be used to contact the receiving side.
    737  * @param dst     Destination address space area base.
    738  * @param size    Size of the destination address space area.
    739  * @param arg     User defined argument.
    740  * @param flags   Storage for received flags. Can be NULL.
    741  *
    742  * @return Zero on success or a negative error code from errno.h.
    743  *
     714        return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, mode);
     715}
     716
     717/** Wrapper for making IPC_M_SHARE_IN calls.
     718 *
     719 * @param phoneid       Phone that will be used to contact the receiving side.
     720 * @param dst           Destination address space area base.
     721 * @param size          Size of the destination address space area.
     722 * @param arg           User defined argument.
     723 * @param flags         Storage where the received flags will be stored. Can be
     724 *                      NULL.
     725 *
     726 * @return              Zero on success or a negative error code from errno.h.
    744727 */
    745728int ipc_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
    746     unsigned int *flags)
     729    int *flags)
    747730{
    748731        sysarg_t tmp_flags = 0;
     
    751734       
    752735        if (flags)
    753                 *flags = (unsigned int) tmp_flags;
     736                *flags = tmp_flags;
    754737       
    755738        return res;
     
    758741/** Wrapper for answering the IPC_M_SHARE_IN calls.
    759742 *
    760  * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
    761  * calls so that the user doesn't have to remember the meaning of each
    762  * IPC argument.
    763  *
    764  * @param callid Hash of the IPC_M_DATA_READ call to answer.
    765  * @param src    Source address space base.
    766  * @param flags Flags to be used for sharing. Bits can be only cleared.
    767  *
    768  * @return Zero on success or a value from @ref errno.h on failure.
    769  *
    770  */
    771 int ipc_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
     743 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
     744 * so that the user doesn't have to remember the meaning of each IPC argument.
     745 *
     746 * @param callid        Hash of the IPC_M_DATA_READ call to answer.
     747 * @param src           Source address space base.
     748 * @param flags         Flags to be used for sharing. Bits can be only cleared.
     749 *
     750 * @return              Zero on success or a value from @ref errno.h on failure.
     751 */
     752int ipc_share_in_finalize(ipc_callid_t callid, void *src, int flags)
    772753{
    773754        return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) flags);
    774755}
    775756
    776 /** Wrapper for IPC_M_SHARE_OUT calls.
    777  *
    778  * @param phoneid Phone that will be used to contact the receiving side.
    779  * @param src     Source address space area base address.
    780  * @param flags   Flags to be used for sharing. Bits can be only cleared.
    781  *
    782  * @return Zero on success or a negative error code from errno.h.
    783  *
    784  */
    785 int ipc_share_out_start(int phoneid, void *src, unsigned int flags)
     757/** Wrapper for making IPC_M_SHARE_OUT calls.
     758 *
     759 * @param phoneid       Phone that will be used to contact the receiving side.
     760 * @param src           Source address space area base address.
     761 * @param flags         Flags to be used for sharing. Bits can be only cleared.
     762 *
     763 * @return              Zero on success or a negative error code from errno.h.
     764 */
     765int ipc_share_out_start(int phoneid, void *src, int flags)
    786766{
    787767        return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
     
    791771/** Wrapper for answering the IPC_M_SHARE_OUT calls.
    792772 *
    793  * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT
    794  * calls so that the user doesn't have to remember the meaning of each
    795  * IPC argument.
    796  *
    797  * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
    798  * @param dst    Destination address space area base address.
    799  *
    800  * @return Zero on success or a value from @ref errno.h on failure.
    801  *
     773 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls
     774 * so that the user doesn't have to remember the meaning of each IPC argument.
     775 *
     776 * @param callid        Hash of the IPC_M_DATA_WRITE call to answer.
     777 * @param dst           Destination address space area base address.   
     778 *
     779 * @return              Zero on success or a value from @ref errno.h on failure.
    802780 */
    803781int ipc_share_out_finalize(ipc_callid_t callid, void *dst)
     
    806784}
    807785
    808 /** Wrapper for IPC_M_DATA_READ calls.
    809  *
    810  * @param phoneid Phone that will be used to contact the receiving side.
    811  * @param dst     Address of the beginning of the destination buffer.
    812  * @param size    Size of the destination buffer.
    813  *
    814  * @return Zero on success or a negative error code from errno.h.
    815  *
     786
     787/** Wrapper for making IPC_M_DATA_READ calls.
     788 *
     789 * @param phoneid       Phone that will be used to contact the receiving side.
     790 * @param dst           Address of the beginning of the destination buffer.
     791 * @param size          Size of the destination buffer.
     792 *
     793 * @return              Zero on success or a negative error code from errno.h.
    816794 */
    817795int ipc_data_read_start(int phoneid, void *dst, size_t size)
     
    823801/** Wrapper for answering the IPC_M_DATA_READ calls.
    824802 *
    825  * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
    826  * calls so that the user doesn't have to remember the meaning of each
    827  * IPC argument.
    828  *
    829  * @param callid Hash of the IPC_M_DATA_READ call to answer.
    830  * @param src    Source address for the IPC_M_DATA_READ call.
    831  * @param size   Size for the IPC_M_DATA_READ call. Can be smaller than
    832  *               the maximum size announced by the sender.
    833  *
    834  * @return Zero on success or a value from @ref errno.h on failure.
    835  *
     803 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
     804 * so that the user doesn't have to remember the meaning of each IPC argument.
     805 *
     806 * @param callid        Hash of the IPC_M_DATA_READ call to answer.
     807 * @param src           Source address for the IPC_M_DATA_READ call.
     808 * @param size          Size for the IPC_M_DATA_READ call. Can be smaller than
     809 *                      the maximum size announced by the sender.
     810 *
     811 * @return              Zero on success or a value from @ref errno.h on failure.
    836812 */
    837813int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
     
    840816}
    841817
    842 /** Wrapper for IPC_M_DATA_WRITE calls.
    843  *
    844  * @param phoneid Phone that will be used to contact the receiving side.
    845  * @param src     Address of the beginning of the source buffer.
    846  * @param size    Size of the source buffer.
    847  *
    848  * @return Zero on success or a negative error code from errno.h.
    849  *
     818/** Wrapper for making IPC_M_DATA_WRITE calls.
     819 *
     820 * @param phoneid       Phone that will be used to contact the receiving side.
     821 * @param src           Address of the beginning of the source buffer.
     822 * @param size          Size of the source buffer.
     823 *
     824 * @return              Zero on success or a negative error code from errno.h.
    850825 */
    851826int ipc_data_write_start(int phoneid, const void *src, size_t size)
     
    857832/** Wrapper for answering the IPC_M_DATA_WRITE calls.
    858833 *
    859  * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE
    860  * calls so that the user doesn't have to remember the meaning of each
    861  * IPC argument.
    862  *
    863  * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
    864  * @param dst    Final destination address for the IPC_M_DATA_WRITE call.
    865  * @param size   Final size for the IPC_M_DATA_WRITE call.
    866  *
    867  * @return Zero on success or a value from @ref errno.h on failure.
    868  *
     834 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls
     835 * so that the user doesn't have to remember the meaning of each IPC argument.
     836 *
     837 * @param callid        Hash of the IPC_M_DATA_WRITE call to answer.
     838 * @param dst           Final destination address for the IPC_M_DATA_WRITE call.
     839 * @param size          Final size for the IPC_M_DATA_WRITE call.
     840 *
     841 * @return              Zero on success or a value from @ref errno.h on failure.
    869842 */
    870843int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
Note: See TracChangeset for help on using the changeset viewer.