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

Changeset 7c0e1f5 in mainline


Ignore:
Timestamp:
2017-11-23T22:20:17Z (3 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
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.

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/ipc/ipc.h

    r40e5d66 r7c0e1f5  
    106106        /** Phone which made or last masqueraded this call. */
    107107        phone_t *phone;
     108        /** User-defined label */
     109        sysarg_t label;
    108110} ipc_data_t;
    109111
  • kernel/generic/include/ipc/sysipc.h

    r40e5d66 r7c0e1f5  
    4444extern sysarg_t sys_ipc_call_async_fast(sysarg_t, sysarg_t, sysarg_t,
    4545    sysarg_t, sysarg_t, sysarg_t);
    46 extern sysarg_t sys_ipc_call_async_slow(sysarg_t, ipc_data_t *);
     46extern sysarg_t sys_ipc_call_async_slow(sysarg_t, ipc_data_t *, sysarg_t);
    4747extern sysarg_t sys_ipc_answer_fast(sysarg_t, sysarg_t, sysarg_t, sysarg_t,
    4848    sysarg_t, sysarg_t);
  • kernel/generic/src/ipc/sysipc.c

    r40e5d66 r7c0e1f5  
    347347/** Make a fast asynchronous call over IPC.
    348348 *
    349  * This function can only handle four arguments of payload, but is faster than
     349 * This function can only handle three arguments of payload, but is faster than
    350350 * the generic function sys_ipc_call_async_slow().
    351351 *
     
    355355 * @param arg2     Service-defined payload argument.
    356356 * @param arg3     Service-defined payload argument.
    357  * @param arg4     Service-defined payload argument.
     357 * @param label    User-defined label.
    358358 *
    359359 * @return Call hash on success.
     
    362362 */
    363363sysarg_t sys_ipc_call_async_fast(sysarg_t handle, sysarg_t imethod,
    364     sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
     364    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t label)
    365365{
    366366        kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
     
    378378        IPC_SET_ARG2(call->data, arg2);
    379379        IPC_SET_ARG3(call->data, arg3);
    380         IPC_SET_ARG4(call->data, arg4);
    381380       
    382381        /*
     
    385384         */
    386385        IPC_SET_ARG5(call->data, 0);
     386
     387        /* Set the user-defined label */
     388        call->data.label = label;
    387389       
    388390        int res = request_preprocess(call, kobj->phone);
     
    401403 * @param handle  Phone capability for the call.
    402404 * @param data    Userspace address of call data with the request.
     405 * @param label   User-defined label.
    403406 *
    404407 * @return See sys_ipc_call_async_fast().
    405408 *
    406409 */
    407 sysarg_t sys_ipc_call_async_slow(sysarg_t handle, ipc_data_t *data)
     410sysarg_t sys_ipc_call_async_slow(sysarg_t handle, ipc_data_t *data,
     411    sysarg_t label)
    408412{
    409413        kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE);
     
    424428                return (sysarg_t) rc;
    425429        }
     430
     431        /* Set the user-defined label */
     432        call->data.label = label;
    426433       
    427434        int res = request_preprocess(call, kobj->phone);
  • uspace/app/trace/syscalls.c

    r40e5d66 r7c0e1f5  
    5454
    5555    [SYS_IPC_CALL_ASYNC_FAST] = { "ipc_call_async_fast", 6,     V_HASH },
    56     [SYS_IPC_CALL_ASYNC_SLOW] = { "ipc_call_async_slow", 2,     V_HASH },
     56    [SYS_IPC_CALL_ASYNC_SLOW] = { "ipc_call_async_slow", 3,     V_HASH },
    5757
    5858    [SYS_IPC_ANSWER_FAST] = { "ipc_answer_fast",        6,      V_ERRNO },
  • 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
  • uspace/lib/c/include/ipc/common.h

    r40e5d66 r7c0e1f5  
    4343#define IPC_FLAG_BLOCKING  0x01
    4444
     45struct async_call;
     46
    4547typedef struct {
    4648        sysarg_t args[IPC_CALL_LEN];
    4749        task_id_t in_task_id;
    4850        sysarg_t in_phone_hash;
     51        struct async_call *label;
    4952} ipc_call_t;
    5053
  • uspace/lib/c/include/ipc/ipc.h

    r40e5d66 r7c0e1f5  
    8989
    9090#define ipc_call_async_0(phoneid, method, private, callback) \
    91         ipc_call_async_fast((phoneid), (method), 0, 0, 0, 0, (private), \
    92             (callback))
     91        ipc_call_async_fast((phoneid), (method), 0, 0, 0, (private), (callback))
    9392#define ipc_call_async_1(phoneid, method, arg1, private, callback) \
    94         ipc_call_async_fast((phoneid), (method), (arg1), 0, 0, 0, (private), \
     93        ipc_call_async_fast((phoneid), (method), (arg1), 0, 0, (private), \
    9594            (callback))
    9695#define ipc_call_async_2(phoneid, method, arg1, arg2, private, callback) \
    97         ipc_call_async_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
     96        ipc_call_async_fast((phoneid), (method), (arg1), (arg2), 0, \
    9897            (private), (callback))
    9998#define ipc_call_async_3(phoneid, method, arg1, arg2, arg3, private, callback) \
    100         ipc_call_async_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, \
     99        ipc_call_async_fast((phoneid), (method), (arg1), (arg2), (arg3), \
    101100            (private), (callback))
    102101#define ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, private, \
    103102    callback) \
    104         ipc_call_async_fast((phoneid), (method), (arg1), (arg2), (arg3), \
    105             (arg4), (private), (callback))
     103        ipc_call_async_slow((phoneid), (method), (arg1), (arg2), (arg3), \
     104            (arg4), 0, (private), (callback))
    106105#define ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, \
    107106    private, callback) \
     
    110109
    111110extern void ipc_call_async_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
    112     sysarg_t, void *, ipc_async_callback_t);
     111    void *, ipc_async_callback_t);
    113112extern void ipc_call_async_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
    114113    sysarg_t, sysarg_t, void *, ipc_async_callback_t);
Note: See TracChangeset for help on using the changeset viewer.