Ignore:
File:
1 edited

Legend:

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

    r1db6dfd rf302586  
    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. */
     
    246240/** Identifier of the incoming connection handled by the current fibril. */
    247241static fibril_local connection_t *fibril_connection;
    248 
    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 }
    296242
    297243static void *default_client_data_constructor(void)
     
    1017963               
    1018964                suseconds_t timeout;
    1019                 unsigned int flags = SYNCH_FLAGS_NONE;
    1020965                if (!list_empty(&timeout_list)) {
    1021966                        awaiter_t *waiter = list_get_instance(
     
    1028973                                futex_up(&async_futex);
    1029974                                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 {
     975                                continue;
     976                        } else
    1044977                                timeout = tv_sub(&waiter->to_event.expires, &tv);
    1045                                 futex_up(&async_futex);
    1046                         }
    1047                 } else {
    1048                         futex_up(&async_futex);
     978                } else
    1049979                        timeout = SYNCH_NO_TIMEOUT;
    1050                 }
     980               
     981                futex_up(&async_futex);
    1051982               
    1052983                atomic_inc(&threads_in_ipc_wait);
    1053984               
    1054985                ipc_call_t call;
    1055                 ipc_callid_t callid = ipc_wait_cycle(&call, timeout, flags);
     986                ipc_callid_t callid = ipc_wait_cycle(&call, timeout,
     987                    SYNCH_FLAGS_NONE);
    1056988               
    1057989                atomic_dec(&threads_in_ipc_wait);
     
    11681100       
    11691101        msg->done = true;
    1170 
    1171         if (msg->forget) {
    1172                 assert(msg->wdata.active);
    1173                 amsg_destroy(msg);
    1174         } else if (!msg->wdata.active) {
     1102        if (!msg->wdata.active) {
    11751103                msg->wdata.active = true;
    11761104                fibril_add_ready(msg->wdata.fid);
    11771105        }
    1178 
     1106       
    11791107        futex_up(&async_futex);
    11801108}
     
    12031131                return 0;
    12041132       
    1205         amsg_t *msg = amsg_create();
     1133        amsg_t *msg = malloc(sizeof(amsg_t));
    12061134        if (msg == NULL)
    12071135                return 0;
    12081136       
     1137        msg->done = false;
    12091138        msg->dataptr = dataptr;
     1139       
     1140        msg->wdata.to_event.inlist = false;
     1141       
     1142        /*
     1143         * We may sleep in the next method,
     1144         * but it will use its own means
     1145         */
    12101146        msg->wdata.active = true;
    12111147       
     
    12411177                return 0;
    12421178       
    1243         amsg_t *msg = amsg_create();
     1179        amsg_t *msg = malloc(sizeof(amsg_t));
     1180       
    12441181        if (msg == NULL)
    12451182                return 0;
    12461183       
     1184        msg->done = false;
    12471185        msg->dataptr = dataptr;
     1186       
     1187        msg->wdata.to_event.inlist = false;
     1188       
     1189        /*
     1190         * We may sleep in the next method,
     1191         * but it will use its own means
     1192         */
    12481193        msg->wdata.active = true;
    12491194       
     
    12681213       
    12691214        futex_down(&async_futex);
    1270 
    1271         assert(!msg->forget);
    1272         assert(!msg->destroyed);
    1273 
    12741215        if (msg->done) {
    12751216                futex_up(&async_futex);
     
    12901231                *retval = msg->retval;
    12911232       
    1292         amsg_destroy(msg);
     1233        free(msg);
    12931234}
    12941235
    12951236/** 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().
    13001237 *
    13011238 * @param amsgid  Hash of the message to wait for.
     
    13121249       
    13131250        amsg_t *msg = (amsg_t *) amsgid;
    1314 
     1251       
     1252        /* TODO: Let it go through the event read at least once */
     1253        if (timeout < 0)
     1254                return ETIMEOUT;
     1255       
    13151256        futex_down(&async_futex);
    1316 
    1317         assert(!msg->forget);
    1318         assert(!msg->destroyed);
    1319 
    13201257        if (msg->done) {
    13211258                futex_up(&async_futex);
     
    13231260        }
    13241261       
    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 
    13321262        gettimeofday(&msg->wdata.to_event.expires, NULL);
    13331263        tv_add(&msg->wdata.to_event.expires, timeout);
    13341264       
    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          */
    13521265        msg->wdata.fid = fibril_get_id();
    13531266        msg->wdata.active = false;
     
    13661279                *retval = msg->retval;
    13671280       
    1368         amsg_destroy(msg);
     1281        free(msg);
    13691282       
    13701283        return 0;
    13711284}
    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 }
    13961285
    13971286/** Wait for specified time.
     
    14041293void async_usleep(suseconds_t timeout)
    14051294{
    1406         amsg_t *msg = amsg_create();
     1295        amsg_t *msg = malloc(sizeof(amsg_t));
     1296       
    14071297        if (!msg)
    14081298                return;
    14091299       
    14101300        msg->wdata.fid = fibril_get_id();
     1301        msg->wdata.active = false;
    14111302       
    14121303        gettimeofday(&msg->wdata.to_event.expires, NULL);
     
    14221313        /* Futex is up automatically after fibril_switch() */
    14231314       
    1424         amsg_destroy(msg);
     1315        free(msg);
    14251316}
    14261317
     
    16931584        ipc_call_t result;
    16941585       
    1695         amsg_t *msg = amsg_create();
    1696         if (!msg) {
     1586        amsg_t *msg = malloc(sizeof(amsg_t));
     1587        if (msg == NULL) {
    16971588                free(sess);
    16981589                errno = ENOMEM;
     
    17001591        }
    17011592       
     1593        msg->done = false;
    17021594        msg->dataptr = &result;
     1595       
     1596        msg->wdata.to_event.inlist = false;
     1597       
     1598        /*
     1599         * We may sleep in the next method,
     1600         * but it will use its own means
     1601         */
    17031602        msg->wdata.active = true;
    17041603       
     
    17441643        ipc_call_t result;
    17451644       
    1746         amsg_t *msg = amsg_create();
    1747         if (!msg)
     1645        amsg_t *msg = malloc(sizeof(amsg_t));
     1646        if (msg == NULL)
    17481647                return ENOENT;
    17491648       
     1649        msg->done = false;
    17501650        msg->dataptr = &result;
     1651       
     1652        msg->wdata.to_event.inlist = false;
     1653       
     1654        /*
     1655         * We may sleep in the next method,
     1656         * but it will use its own means
     1657         */
    17511658        msg->wdata.active = true;
    17521659       
     
    23442251            IPC_FF_ROUTE_FROM_ME);
    23452252        if (retval != EOK) {
    2346                 async_forget(msg);
     2253                async_wait_for(msg, NULL);
    23472254                ipc_answer_0(callid, retval);
    23482255                return retval;
     
    25382445            IPC_FF_ROUTE_FROM_ME);
    25392446        if (retval != EOK) {
    2540                 async_forget(msg);
     2447                async_wait_for(msg, NULL);
    25412448                ipc_answer_0(callid, retval);
    25422449                return retval;
Note: See TracChangeset for help on using the changeset viewer.