Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 7c0e1f5 in mainline for uspace/lib/c/generic/ipc.c


Ignore:
Timestamp:
2017-11-23T22:20:17Z (4 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
b1f36e3
Parents:
40e5d66
Message:

Rework userspace call tracking

Setting the address of the userspace call structure in the kernel
call_t structure on send allows us to remove lots of userspace
scaffolding. More importantly, it also opens the door for not needing
the callid (later capability) on answer receive.

File:
1 edited

Legend:

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

    r40e5d66 r7c0e1f5  
    11/*
    22 * Copyright (c) 2006 Ondrej Palkovsky
     3 * Copyright (c) 2017 Jakub Jermar
    34 * All rights reserved.
    45 *
     
    5253 * Structures of this type are used for keeping track of sent asynchronous calls.
    5354 */
    54 typedef struct {
    55         link_t list;
    56        
     55typedef struct async_call {
    5756        ipc_async_callback_t callback;
    5857        void *private;
    5958       
    60         union {
    61                 ipc_callid_t callid;
    62                 struct {
    63                         ipc_call_t data;
    64                         int phoneid;
    65                 } msg;
    66         } u;
     59        struct {
     60                ipc_call_t data;
     61                int phoneid;
     62        } msg;
    6763} async_call_t;
    68 
    69 LIST_INITIALIZE(dispatched_calls);
    70 
    71 static futex_t ipc_futex = FUTEX_INITIALIZER;
    72 
    73 /** Send asynchronous message via syscall.
    74  *
    75  * @param phoneid Phone handle for the call.
    76  * @param data    Call data with the request.
    77  *
    78  * @return Hash of the call or an error code.
    79  *
    80  */
    81 static ipc_callid_t ipc_call_async_internal(int phoneid, ipc_call_t *data)
    82 {
    83         return __SYSCALL2(SYS_IPC_CALL_ASYNC_SLOW, phoneid, (sysarg_t) data);
    84 }
    8564
    8665/** Prologue for ipc_call_async_*() functions.
     
    121100        if (!call) {
    122101                /* Nothing to do regardless if failed or not */
    123                 futex_unlock(&ipc_futex);
    124102                return;
    125103        }
    126104       
    127105        if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
    128                 futex_unlock(&ipc_futex);
    129                
    130106                /* Call asynchronous handler with error code */
    131107                if (call->callback)
     
    135111                return;
    136112        }
    137        
    138         call->u.callid = callid;
    139        
    140         /* Add call to the list of dispatched calls */
    141         list_append(&call->list, &dispatched_calls);
    142         futex_unlock(&ipc_futex);
    143113}
    144114
    145115/** Fast asynchronous call.
    146116 *
    147  * This function can only handle four arguments of payload. It is, however,
     117 * This function can only handle three arguments of payload. It is, however,
    148118 * faster than the more generic ipc_call_async_slow().
    149119 *
     
    159129 * @param arg2        Service-defined payload argument.
    160130 * @param arg3        Service-defined payload argument.
    161  * @param arg4        Service-defined payload argument.
    162131 * @param private     Argument to be passed to the answer/error callback.
    163132 * @param callback    Answer or error callback.
    164133 */
    165134void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1,
    166     sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private,
    167     ipc_async_callback_t callback)
     135    sysarg_t arg2, sysarg_t arg3, void *private, ipc_async_callback_t callback)
    168136{
    169137        async_call_t *call = NULL;
     
    175143        }
    176144       
    177         /*
    178          * We need to make sure that we get callid
    179          * before another thread accesses the queue again.
    180          */
    181        
    182         futex_lock(&ipc_futex);
    183145        ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid,
    184             imethod, arg1, arg2, arg3, arg4);
     146            imethod, arg1, arg2, arg3, (sysarg_t) call);
    185147       
    186148        ipc_finish_async(callid, phoneid, call);
     
    213175                return;
    214176       
    215         IPC_SET_IMETHOD(call->u.msg.data, imethod);
    216         IPC_SET_ARG1(call->u.msg.data, arg1);
    217         IPC_SET_ARG2(call->u.msg.data, arg2);
    218         IPC_SET_ARG3(call->u.msg.data, arg3);
    219         IPC_SET_ARG4(call->u.msg.data, arg4);
    220         IPC_SET_ARG5(call->u.msg.data, arg5);
    221        
    222         /*
    223          * We need to make sure that we get callid
    224          * before another threadaccesses the queue again.
    225          */
    226        
    227         futex_lock(&ipc_futex);
    228         ipc_callid_t callid =
    229             ipc_call_async_internal(phoneid, &call->u.msg.data);
     177        IPC_SET_IMETHOD(call->msg.data, imethod);
     178        IPC_SET_ARG1(call->msg.data, arg1);
     179        IPC_SET_ARG2(call->msg.data, arg2);
     180        IPC_SET_ARG3(call->msg.data, arg3);
     181        IPC_SET_ARG4(call->msg.data, arg4);
     182        IPC_SET_ARG5(call->msg.data, arg5);
     183       
     184        ipc_callid_t callid = __SYSCALL3(SYS_IPC_CALL_ASYNC_SLOW, phoneid,
     185            (sysarg_t) &call->msg.data, (sysarg_t) call);
    230186       
    231187        ipc_finish_async(callid, phoneid, call);
     
    286242/** Handle received answer.
    287243 *
    288  * Find the hash of the answer and call the answer callback.
    289  *
    290  * The answer has the same hash as the request OR'ed with
    291  * the IPC_CALLID_ANSWERED bit.
    292  *
    293  * @todo Use hash table.
    294  *
    295244 * @param callid Hash of the received answer.
    296245 * @param data   Call data of the answer.
    297  *
    298246 */
    299247static void handle_answer(ipc_callid_t callid, ipc_call_t *data)
    300248{
    301         callid &= ~IPC_CALLID_ANSWERED;
    302        
    303         futex_lock(&ipc_futex);
    304        
    305         link_t *item;
    306         for (item = dispatched_calls.head.next; item != &dispatched_calls.head;
    307             item = item->next) {
    308                 async_call_t *call =
    309                     list_get_instance(item, async_call_t, list);
    310                
    311                 if (call->u.callid == callid) {
    312                         list_remove(&call->list);
    313                        
    314                         futex_unlock(&ipc_futex);
    315                        
    316                         if (call->callback)
    317                                 call->callback(call->private,
    318                                     IPC_GET_RETVAL(*data), data);
    319                        
    320                         free(call);
    321                         return;
    322                 }
    323         }
    324        
    325         futex_unlock(&ipc_futex);
     249        async_call_t *call = data->label;
     250
     251        if (!call)
     252                return;
     253
     254        if (call->callback)
     255                call->callback(call->private, IPC_GET_RETVAL(*data), data);
     256        free(call);
    326257}
    327258
Note: See TracChangeset for help on using the changeset viewer.