Changes in / [2a7ba5e:0a981e3] in mainline


Ignore:
Location:
uspace
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/char/i8042/main.c

    r2a7ba5e r0a981e3  
    4343#include <ddf/log.h>
    4444#include <stdio.h>
     45#include <async.h>
    4546#include "i8042.h"
    4647
     
    151152        ddf_log_init(NAME);
    152153       
     154        /*
     155         * Alleviate the virtual memory / page table pressure caused by
     156         * interrupt storms when the default large stacks are used.
     157         */
     158        async_set_notification_handler_stack_size(PAGE_SIZE);
     159
    153160        return ddf_driver_main(&i8042_driver);
    154161}
  • uspace/lib/c/generic/async.c

    r2a7ba5e r0a981e3  
    493493}
    494494
     495static size_t notification_handler_stksz = FIBRIL_DFLT_STK_SIZE;
     496
     497/** Set the stack size for the notification handler notification fibrils.
     498 *
     499 * @param size Stack size in bytes.
     500 */
     501void async_set_notification_handler_stack_size(size_t size)
     502{
     503        notification_handler_stksz = size;
     504}
     505
    495506/** Mutex protecting inactive_exch_list and avail_phone_cv.
    496507 *
     
    987998}
    988999
    989 /** Process notification.
    990  *
    991  * @param callid Hash of the incoming call.
    992  * @param call   Data of the incoming call.
    993  */
    994 static void process_notification(ipc_callid_t callid, ipc_call_t *call)
    995 {
     1000/** Notification fibril.
     1001 *
     1002 * When a notification arrives, a fibril with this implementing function is
     1003 * created. It calls the corresponding notification handler and does the final
     1004 * cleanup.
     1005 *
     1006 * @param arg Message structure pointer.
     1007 *
     1008 * @return Always zero.
     1009 *
     1010 */
     1011static int notification_fibril(void *arg)
     1012{
     1013        assert(arg);
     1014       
     1015        msg_t *msg = (msg_t *) arg;
    9961016        async_notification_handler_t handler = NULL;
    9971017        void *data = NULL;
    998 
    999         assert(call);
    10001018       
    10011019        futex_down(&async_futex);
    10021020       
    10031021        ht_link_t *link = hash_table_find(&notification_hash_table,
    1004             &IPC_GET_IMETHOD(*call));
     1022            &IPC_GET_IMETHOD(msg->call));
    10051023        if (link) {
    10061024                notification_t *notification =
     
    10131031       
    10141032        if (handler)
    1015                 handler(callid, call, data);
     1033                handler(msg->callid, &msg->call, data);
     1034       
     1035        free(msg);
     1036        return 0;
     1037}
     1038
     1039/** Process notification.
     1040 *
     1041 * A new fibril is created which would process the notification.
     1042 *
     1043 * @param callid Hash of the incoming call.
     1044 * @param call   Data of the incoming call.
     1045 *
     1046 * @return False if an error occured.
     1047 *         True if the call was passed to the notification fibril.
     1048 *
     1049 */
     1050static bool process_notification(ipc_callid_t callid, ipc_call_t *call)
     1051{
     1052        assert(call);
     1053       
     1054        futex_down(&async_futex);
     1055       
     1056        msg_t *msg = malloc(sizeof(*msg));
     1057        if (!msg) {
     1058                futex_up(&async_futex);
     1059                return false;
     1060        }
     1061       
     1062        msg->callid = callid;
     1063        msg->call = *call;
     1064       
     1065        fid_t fid = fibril_create_generic(notification_fibril, msg,
     1066            notification_handler_stksz);
     1067        if (fid == 0) {
     1068                free(msg);
     1069                futex_up(&async_futex);
     1070                return false;
     1071        }
     1072       
     1073        fibril_add_ready(fid);
     1074       
     1075        futex_up(&async_futex);
     1076        return true;
    10161077}
    10171078
     
    13141375        /* Kernel notification */
    13151376        if ((callid & IPC_CALLID_NOTIFICATION)) {
    1316                 fibril_t *fibril = (fibril_t *) __tcb_get()->fibril_data;
    1317                 unsigned oldsw = fibril->switches;
    1318 
    13191377                process_notification(callid, call);
    1320 
    1321                 if (oldsw != fibril->switches) {
    1322                         /*
    1323                          * The notification handler did not execute atomically
    1324                          * and so the current manager fibril assumed the role of
    1325                          * a notification fibril. While waiting for its
    1326                          * resources, it switched to another manager fibril that
    1327                          * had already existed or it created a new one. We
    1328                          * therefore know there is at least yet another
    1329                          * manager fibril that can take over. We now kill the
    1330                          * current 'notification' fibril to prevent fibril
    1331                          * population explosion.
    1332                          */
    1333                         futex_down(&async_futex);
    1334                         fibril_switch(FIBRIL_FROM_DEAD);
    1335                 }
    13361378                return;
    13371379        }
     
    15081550void async_create_manager(void)
    15091551{
    1510         fid_t fid = fibril_create_generic(async_manager_fibril, NULL, PAGE_SIZE);
     1552        fid_t fid = fibril_create(async_manager_fibril, NULL);
    15111553        if (fid != 0)
    15121554                fibril_add_manager(fid);
     
    16321674       
    16331675        ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4, msg,
    1634             reply_received);
     1676            reply_received, true);
    16351677       
    16361678        return (aid_t) msg;
     
    16701712       
    16711713        ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4, arg5,
    1672             msg, reply_received);
     1714            msg, reply_received, true);
    16731715       
    16741716        return (aid_t) msg;
     
    19592001{
    19602002        if (exch != NULL)
    1961                 ipc_call_async_0(exch->phone, imethod, NULL, NULL);
     2003                ipc_call_async_0(exch->phone, imethod, NULL, NULL, true);
    19622004}
    19632005
     
    19652007{
    19662008        if (exch != NULL)
    1967                 ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL);
     2009                ipc_call_async_1(exch->phone, imethod, arg1, NULL, NULL, true);
    19682010}
    19692011
     
    19722014{
    19732015        if (exch != NULL)
    1974                 ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL);
     2016                ipc_call_async_2(exch->phone, imethod, arg1, arg2, NULL, NULL,
     2017                    true);
    19752018}
    19762019
     
    19802023        if (exch != NULL)
    19812024                ipc_call_async_3(exch->phone, imethod, arg1, arg2, arg3, NULL,
    1982                     NULL);
     2025                    NULL, true);
    19832026}
    19842027
     
    19882031        if (exch != NULL)
    19892032                ipc_call_async_4(exch->phone, imethod, arg1, arg2, arg3, arg4,
    1990                     NULL, NULL);
     2033                    NULL, NULL, true);
    19912034}
    19922035
     
    19962039        if (exch != NULL)
    19972040                ipc_call_async_5(exch->phone, imethod, arg1, arg2, arg3, arg4,
    1998                     arg5, NULL, NULL);
     2041                    arg5, NULL, NULL, true);
    19992042}
    20002043
     
    21192162       
    21202163        ipc_call_async_0(exch->phone, IPC_M_CLONE_ESTABLISH, msg,
    2121             reply_received);
     2164            reply_received, true);
    21222165       
    21232166        sysarg_t rc;
     
    21682211       
    21692212        ipc_call_async_4(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, arg4,
    2170             msg, reply_received);
     2213            msg, reply_received, true);
    21712214       
    21722215        sysarg_t rc;
  • uspace/lib/c/generic/fibril.c

    r2a7ba5e r0a981e3  
    113113       
    114114        fibril->waits_for = NULL;
    115 
    116         fibril->switches = 0;
    117115
    118116        /*
     
    218216                        assert(stype == FIBRIL_TO_MANAGER);
    219217
    220                         srcf->switches++;
    221 
    222218                        /*
    223219                         * Don't put the current fibril into any list, it should
  • uspace/lib/c/generic/ipc.c

    r2a7ba5e r0a981e3  
    9696}
    9797
    98 /** Prologue for ipc_call_async_*() functions.
     98/** Prolog for ipc_call_async_*() functions.
    9999 *
    100100 * @param private  Argument for the answer/error callback.
     
    122122}
    123123
    124 /** Epilogue for ipc_call_async_*() functions.
     124/** Epilog for ipc_call_async_*() functions.
    125125 *
    126126 * @param callid      Value returned by the SYS_IPC_CALL_ASYNC_* syscall.
    127127 * @param phoneid     Phone handle through which the call was made.
    128128 * @param call        Structure returned by ipc_prepare_async().
     129 * @param can_preempt If true, the current fibril can be preempted
     130 *                    in this call.
     131 *
    129132 */
    130133static inline void ipc_finish_async(ipc_callid_t callid, int phoneid,
    131     async_call_t *call)
     134    async_call_t *call, bool can_preempt)
    132135{
    133136        if (!call) {
     
    156159                list_append(&call->list, &queued_calls);
    157160               
    158                 call->fid = fibril_get_id();
    159                 fibril_switch(FIBRIL_TO_MANAGER);
    160                 /* Async futex unlocked by previous call */
     161                if (can_preempt) {
     162                        call->fid = fibril_get_id();
     163                        fibril_switch(FIBRIL_TO_MANAGER);
     164                        /* Async futex unlocked by previous call */
     165                } else {
     166                        call->fid = 0;
     167                        futex_up(&async_futex);
     168                }
    161169               
    162170                return;
     
    189197 * @param private     Argument to be passed to the answer/error callback.
    190198 * @param callback    Answer or error callback.
     199 * @param can_preempt If true, the current fibril will be preempted in
     200 *                    case the kernel temporarily refuses to accept more
     201 *                    asynchronous calls.
     202 *
    191203 */
    192204void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1,
    193205    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private,
    194     ipc_async_callback_t callback)
     206    ipc_async_callback_t callback, bool can_preempt)
    195207{
    196208        async_call_t *call = NULL;
     
    234246        }
    235247       
    236         ipc_finish_async(callid, phoneid, call);
     248        ipc_finish_async(callid, phoneid, call, can_preempt);
    237249}
    238250
     
    254266 * @param private     Argument to be passed to the answer/error callback.
    255267 * @param callback    Answer or error callback.
     268 * @param can_preempt If true, the current fibril will be preempted in
     269 *                    case the kernel temporarily refuses to accept more
     270 *                    asynchronous calls.
     271 *
    256272 */
    257273void ipc_call_async_slow(int phoneid, sysarg_t imethod, sysarg_t arg1,
    258274    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, void *private,
    259     ipc_async_callback_t callback)
     275    ipc_async_callback_t callback, bool can_preempt)
    260276{
    261277        async_call_t *call = ipc_prepare_async(private, callback);
     
    279295            ipc_call_async_internal(phoneid, &call->u.msg.data);
    280296       
    281         ipc_finish_async(callid, phoneid, call);
     297        ipc_finish_async(callid, phoneid, call, can_preempt);
    282298}
    283299
     
    359375                futex_up(&async_futex);
    360376               
    361                 assert(call->fid);
    362                 fibril_add_ready(call->fid);
     377                if (call->fid)
     378                        fibril_add_ready(call->fid);
    363379               
    364380                if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
  • uspace/lib/c/include/async.h

    r2a7ba5e r0a981e3  
    165165extern int async_create_callback_port(async_exch_t *, iface_t, sysarg_t,
    166166    sysarg_t, async_port_handler_t, void *, port_id_t *);
     167
     168extern void async_set_notification_handler_stack_size(size_t);
    167169
    168170extern int async_irq_subscribe(int, int, async_notification_handler_t, void *,
  • uspace/lib/c/include/fibril.h

    r2a7ba5e r0a981e3  
    7878       
    7979        fibril_owner_info_t *waits_for;
    80 
    81         unsigned switches;
    8280} fibril_t;
    8381
  • uspace/lib/c/include/ipc/ipc.h

    r2a7ba5e r0a981e3  
    8989 */
    9090
    91 #define ipc_call_async_0(phoneid, method, private, callback) \
     91#define ipc_call_async_0(phoneid, method, private, callback, can_preempt) \
    9292        ipc_call_async_fast((phoneid), (method), 0, 0, 0, 0, (private), \
    93             (callback))
    94 #define ipc_call_async_1(phoneid, method, arg1, private, callback) \
     93            (callback), (can_preempt))
     94#define ipc_call_async_1(phoneid, method, arg1, private, callback, \
     95    can_preempt) \
    9596        ipc_call_async_fast((phoneid), (method), (arg1), 0, 0, 0, (private), \
    96             (callback))
    97 #define ipc_call_async_2(phoneid, method, arg1, arg2, private, callback) \
     97            (callback), (can_preempt))
     98#define ipc_call_async_2(phoneid, method, arg1, arg2, private, callback, \
     99    can_preempt) \
    98100        ipc_call_async_fast((phoneid), (method), (arg1), (arg2), 0, 0, \
    99             (private), (callback))
    100 #define ipc_call_async_3(phoneid, method, arg1, arg2, arg3, private, callback) \
     101            (private), (callback), (can_preempt))
     102#define ipc_call_async_3(phoneid, method, arg1, arg2, arg3, private, callback, \
     103    can_preempt) \
    101104        ipc_call_async_fast((phoneid), (method), (arg1), (arg2), (arg3), 0, \
    102             (private), (callback))
     105            (private), (callback), (can_preempt))
    103106#define ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, private, \
    104     callback) \
     107    callback, can_preempt) \
    105108        ipc_call_async_fast((phoneid), (method), (arg1), (arg2), (arg3), \
    106             (arg4), (private), (callback))
     109            (arg4), (private), (callback), (can_preempt))
    107110#define ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, \
    108     private, callback) \
     111    private, callback, can_preempt) \
    109112        ipc_call_async_slow((phoneid), (method), (arg1), (arg2), (arg3), \
    110             (arg4), (arg5), (private), (callback))
     113            (arg4), (arg5), (private), (callback), (can_preempt))
    111114
    112115extern void ipc_call_async_fast(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
    113     sysarg_t, void *, ipc_async_callback_t);
     116    sysarg_t, void *, ipc_async_callback_t, bool);
    114117extern void ipc_call_async_slow(int, sysarg_t, sysarg_t, sysarg_t, sysarg_t,
    115     sysarg_t, sysarg_t, void *, ipc_async_callback_t);
     118    sysarg_t, sysarg_t, void *, ipc_async_callback_t, bool);
    116119
    117120extern int ipc_hangup(int);
  • uspace/srv/hw/bus/cuda_adb/cuda_adb.c

    r2a7ba5e r0a981e3  
    4747#include <errno.h>
    4848#include <ipc/adb.h>
     49#include <async.h>
    4950#include <assert.h>
    5051#include "cuda_adb.h"
     
    157158        printf(NAME ": VIA-CUDA Apple Desktop Bus driver\n");
    158159       
     160        /*
     161         * Alleviate the virtual memory / page table pressure caused by
     162         * interrupt storms when the default large stacks are used.
     163         */
     164        async_set_notification_handler_stack_size(PAGE_SIZE);
     165
    159166        for (i = 0; i < ADB_MAX_ADDR; ++i) {
    160167                adb_dev[i].client_sess = NULL;
Note: See TracChangeset for help on using the changeset viewer.