Ignore:
File:
1 edited

Legend:

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

    r1db6dfd rcff3fb6  
    189189        /** If reply was received. */
    190190        bool done;
    191 
    192         /** If the message / reply should be discarded on arrival. */
    193         bool forget;
    194 
    195         /** If already destroyed. */
    196         bool destroyed;
    197191       
    198192        /** Pointer to where the answer data is stored. */
     
    247241static fibril_local connection_t *fibril_connection;
    248242
    249 static void to_event_initialize(to_event_t *to)
    250 {
    251         struct timeval tv = { 0, 0 };
    252 
    253         to->inlist = false;
    254         to->occurred = false;
    255         link_initialize(&to->link);
    256         to->expires = tv;
    257 }
    258 
    259 static void wu_event_initialize(wu_event_t *wu)
    260 {
    261         wu->inlist = false;
    262         link_initialize(&wu->link);
    263 }
    264 
    265 void awaiter_initialize(awaiter_t *aw)
    266 {
    267         aw->fid = 0;
    268         aw->active = false;
    269         to_event_initialize(&aw->to_event);
    270         wu_event_initialize(&aw->wu_event);
    271 }
    272 
    273 static amsg_t *amsg_create(void)
    274 {
    275         amsg_t *msg;
    276 
    277         msg = malloc(sizeof(amsg_t));
    278         if (msg) {
    279                 msg->done = false;
    280                 msg->forget = false;
    281                 msg->destroyed = false;
    282                 msg->dataptr = NULL;
    283                 msg->retval = (sysarg_t) EINVAL;
    284                 awaiter_initialize(&msg->wdata);
    285         }
    286 
    287         return msg;
    288 }
    289 
    290 static void amsg_destroy(amsg_t *msg)
    291 {
    292         assert(!msg->destroyed);
    293         msg->destroyed = true;
    294         free(msg);
    295 }
    296 
    297243static void *default_client_data_constructor(void)
    298244{
     
    311257void async_set_client_data_constructor(async_client_data_ctor_t ctor)
    312258{
    313         assert(async_client_data_create == default_client_data_constructor);
    314259        async_client_data_create = ctor;
    315260}
     
    317262void async_set_client_data_destructor(async_client_data_dtor_t dtor)
    318263{
    319         assert(async_client_data_destroy == default_client_data_destructor);
    320264        async_client_data_destroy = dtor;
    321265}
     
    359303void async_set_client_connection(async_client_conn_t conn)
    360304{
    361         assert(client_connection == default_client_connection);
    362305        client_connection = conn;
    363306}
     
    1017960               
    1018961                suseconds_t timeout;
    1019                 unsigned int flags = SYNCH_FLAGS_NONE;
    1020962                if (!list_empty(&timeout_list)) {
    1021963                        awaiter_t *waiter = list_get_instance(
     
    1028970                                futex_up(&async_futex);
    1029971                                handle_expired_timeouts();
    1030                                 /*
    1031                                  * Notice that even if the event(s) already
    1032                                  * expired (and thus the other fibril was
    1033                                  * supposed to be running already),
    1034                                  * we check for incoming IPC.
    1035                                  *
    1036                                  * Otherwise, a fibril that continuously
    1037                                  * creates (almost) expired events could
    1038                                  * prevent IPC retrieval from the kernel.
    1039                                  */
    1040                                 timeout = 0;
    1041                                 flags = SYNCH_FLAGS_NON_BLOCKING;
    1042 
    1043                         } else {
     972                                continue;
     973                        } else
    1044974                                timeout = tv_sub(&waiter->to_event.expires, &tv);
    1045                                 futex_up(&async_futex);
    1046                         }
    1047                 } else {
    1048                         futex_up(&async_futex);
     975                } else
    1049976                        timeout = SYNCH_NO_TIMEOUT;
    1050                 }
     977               
     978                futex_up(&async_futex);
    1051979               
    1052980                atomic_inc(&threads_in_ipc_wait);
    1053981               
    1054982                ipc_call_t call;
    1055                 ipc_callid_t callid = ipc_wait_cycle(&call, timeout, flags);
     983                ipc_callid_t callid = ipc_wait_cycle(&call, timeout,
     984                    SYNCH_FLAGS_NONE);
    1056985               
    1057986                atomic_dec(&threads_in_ipc_wait);
     
    11681097       
    11691098        msg->done = true;
    1170 
    1171         if (msg->forget) {
    1172                 assert(msg->wdata.active);
    1173                 amsg_destroy(msg);
    1174         } else if (!msg->wdata.active) {
     1099        if (!msg->wdata.active) {
    11751100                msg->wdata.active = true;
    11761101                fibril_add_ready(msg->wdata.fid);
    11771102        }
    1178 
     1103       
    11791104        futex_up(&async_futex);
    11801105}
     
    12031128                return 0;
    12041129       
    1205         amsg_t *msg = amsg_create();
     1130        amsg_t *msg = malloc(sizeof(amsg_t));
    12061131        if (msg == NULL)
    12071132                return 0;
    12081133       
     1134        msg->done = false;
    12091135        msg->dataptr = dataptr;
     1136       
     1137        msg->wdata.to_event.inlist = false;
     1138       
     1139        /*
     1140         * We may sleep in the next method,
     1141         * but it will use its own means
     1142         */
    12101143        msg->wdata.active = true;
    12111144       
     
    12411174                return 0;
    12421175       
    1243         amsg_t *msg = amsg_create();
     1176        amsg_t *msg = malloc(sizeof(amsg_t));
     1177       
    12441178        if (msg == NULL)
    12451179                return 0;
    12461180       
     1181        msg->done = false;
    12471182        msg->dataptr = dataptr;
     1183       
     1184        msg->wdata.to_event.inlist = false;
     1185       
     1186        /*
     1187         * We may sleep in the next method,
     1188         * but it will use its own means
     1189         */
    12481190        msg->wdata.active = true;
    12491191       
     
    12681210       
    12691211        futex_down(&async_futex);
    1270 
    1271         assert(!msg->forget);
    1272         assert(!msg->destroyed);
    1273 
    12741212        if (msg->done) {
    12751213                futex_up(&async_futex);
     
    12901228                *retval = msg->retval;
    12911229       
    1292         amsg_destroy(msg);
     1230        free(msg);
    12931231}
    12941232
    12951233/** Wait for a message sent by the async framework, timeout variant.
    1296  *
    1297  * If the wait times out, the caller may choose to either wait again by calling
    1298  * async_wait_for() or async_wait_timeout(), or forget the message via
    1299  * async_forget().
    13001234 *
    13011235 * @param amsgid  Hash of the message to wait for.
     
    13121246       
    13131247        amsg_t *msg = (amsg_t *) amsgid;
    1314 
     1248       
     1249        /* TODO: Let it go through the event read at least once */
     1250        if (timeout < 0)
     1251                return ETIMEOUT;
     1252       
    13151253        futex_down(&async_futex);
    1316 
    1317         assert(!msg->forget);
    1318         assert(!msg->destroyed);
    1319 
    13201254        if (msg->done) {
    13211255                futex_up(&async_futex);
     
    13231257        }
    13241258       
    1325         /*
    1326          * Negative timeout is converted to zero timeout to avoid
    1327          * using tv_add with negative augmenter.
    1328          */
    1329         if (timeout < 0)
    1330                 timeout = 0;
    1331 
    13321259        gettimeofday(&msg->wdata.to_event.expires, NULL);
    13331260        tv_add(&msg->wdata.to_event.expires, timeout);
    13341261       
    1335         /*
    1336          * Current fibril is inserted as waiting regardless of the
    1337          * "size" of the timeout.
    1338          *
    1339          * Checking for msg->done and immediately bailing out when
    1340          * timeout == 0 would mean that the manager fibril would never
    1341          * run (consider single threaded program).
    1342          * Thus the IPC answer would be never retrieved from the kernel.
    1343          *
    1344          * Notice that the actual delay would be very small because we
    1345          * - switch to manager fibril
    1346          * - the manager sees expired timeout
    1347          * - and thus adds us back to ready queue
    1348          * - manager switches back to some ready fibril
    1349          *   (prior it, it checks for incoming IPC).
    1350          *
    1351          */
    13521262        msg->wdata.fid = fibril_get_id();
    13531263        msg->wdata.active = false;
     
    13661276                *retval = msg->retval;
    13671277       
    1368         amsg_destroy(msg);
     1278        free(msg);
    13691279       
    13701280        return 0;
    13711281}
    1372  
    1373 /** Discard the message / reply on arrival.
    1374  *
    1375  * The message will be marked to be discarded once the reply arrives in
    1376  * reply_received(). It is not allowed to call async_wait_for() or
    1377  * async_wait_timeout() on this message after a call to this function.
    1378  *
    1379  * @param amsgid  Hash of the message to forget.
    1380  */
    1381 void async_forget(aid_t amsgid)
    1382 {
    1383         amsg_t *msg = (amsg_t *) amsgid;
    1384 
    1385         assert(msg);
    1386         assert(!msg->forget);
    1387         assert(!msg->destroyed);
    1388 
    1389         futex_down(&async_futex);
    1390         if (msg->done)
    1391                 amsg_destroy(msg);
    1392         else
    1393                 msg->forget = true;
    1394         futex_up(&async_futex);
    1395 }
    13961282
    13971283/** Wait for specified time.
     
    14041290void async_usleep(suseconds_t timeout)
    14051291{
    1406         amsg_t *msg = amsg_create();
     1292        amsg_t *msg = malloc(sizeof(amsg_t));
     1293       
    14071294        if (!msg)
    14081295                return;
    14091296       
    14101297        msg->wdata.fid = fibril_get_id();
     1298        msg->wdata.active = false;
    14111299       
    14121300        gettimeofday(&msg->wdata.to_event.expires, NULL);
     
    14221310        /* Futex is up automatically after fibril_switch() */
    14231311       
    1424         amsg_destroy(msg);
     1312        free(msg);
    14251313}
    14261314
     
    16931581        ipc_call_t result;
    16941582       
    1695         amsg_t *msg = amsg_create();
    1696         if (!msg) {
     1583        amsg_t *msg = malloc(sizeof(amsg_t));
     1584        if (msg == NULL) {
    16971585                free(sess);
    16981586                errno = ENOMEM;
     
    17001588        }
    17011589       
     1590        msg->done = false;
    17021591        msg->dataptr = &result;
     1592       
     1593        msg->wdata.to_event.inlist = false;
     1594       
     1595        /*
     1596         * We may sleep in the next method,
     1597         * but it will use its own means
     1598         */
    17031599        msg->wdata.active = true;
    17041600       
     
    17441640        ipc_call_t result;
    17451641       
    1746         amsg_t *msg = amsg_create();
    1747         if (!msg)
     1642        amsg_t *msg = malloc(sizeof(amsg_t));
     1643        if (msg == NULL)
    17481644                return ENOENT;
    17491645       
     1646        msg->done = false;
    17501647        msg->dataptr = &result;
     1648       
     1649        msg->wdata.to_event.inlist = false;
     1650       
     1651        /*
     1652         * We may sleep in the next method,
     1653         * but it will use its own means
     1654         */
    17511655        msg->wdata.active = true;
    17521656       
     
    19421846       
    19431847        fibril_mutex_lock(&async_sess_mutex);
    1944        
     1848
    19451849        int rc = async_hangup_internal(sess->phone);
    19461850       
     
    20941998 *
    20951999 * @param exch  Exchange for sending the message.
     2000 * @param dst   Destination address space area base.
    20962001 * @param size  Size of the destination address space area.
    20972002 * @param arg   User defined argument.
    20982003 * @param flags Storage for the received flags. Can be NULL.
    2099  * @param dst   Destination address space area base. Cannot be NULL.
    21002004 *
    21012005 * @return Zero on success or a negative error code from errno.h.
    21022006 *
    21032007 */
    2104 int async_share_in_start(async_exch_t *exch, size_t size, sysarg_t arg,
    2105     unsigned int *flags, void **dst)
     2008int async_share_in_start(async_exch_t *exch, void *dst, size_t size,
     2009    sysarg_t arg, unsigned int *flags)
    21062010{
    21072011        if (exch == NULL)
    21082012                return ENOENT;
    21092013       
    2110         sysarg_t _flags = 0;
    2111         sysarg_t _dst = (sysarg_t) -1;
    2112         int res = async_req_2_4(exch, IPC_M_SHARE_IN, (sysarg_t) size,
    2113             arg, NULL, &_flags, NULL, &_dst);
     2014        sysarg_t tmp_flags;
     2015        int res = async_req_3_2(exch, IPC_M_SHARE_IN, (sysarg_t) dst,
     2016            (sysarg_t) size, arg, NULL, &tmp_flags);
    21142017       
    21152018        if (flags)
    2116                 *flags = (unsigned int) _flags;
    2117        
    2118         *dst = (void *) _dst;
     2019                *flags = (unsigned int) tmp_flags;
     2020       
    21192021        return res;
    21202022}
     
    21452047                return false;
    21462048       
    2147         *size = (size_t) IPC_GET_ARG1(data);
     2049        *size = (size_t) IPC_GET_ARG2(data);
    21482050        return true;
    21492051}
     
    21512053/** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework.
    21522054 *
    2153  * This wrapper only makes it more comfortable to answer IPC_M_SHARE_IN
     2055 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
    21542056 * calls so that the user doesn't have to remember the meaning of each IPC
    21552057 * argument.
     
    22292131 *
    22302132 */
    2231 int async_share_out_finalize(ipc_callid_t callid, void **dst)
     2133int async_share_out_finalize(ipc_callid_t callid, void *dst)
    22322134{
    22332135        return ipc_share_out_finalize(callid, dst);
     
    23442246            IPC_FF_ROUTE_FROM_ME);
    23452247        if (retval != EOK) {
    2346                 async_forget(msg);
     2248                async_wait_for(msg, NULL);
    23472249                ipc_answer_0(callid, retval);
    23482250                return retval;
     
    25382440            IPC_FF_ROUTE_FROM_ME);
    25392441        if (retval != EOK) {
    2540                 async_forget(msg);
     2442                async_wait_for(msg, NULL);
    25412443                ipc_answer_0(callid, retval);
    25422444                return retval;
Note: See TracChangeset for help on using the changeset viewer.