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

Changeset 47c9a8c in mainline


Ignore:
Timestamp:
2012-04-13T20:21:32Z (10 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master
Children:
ab9f443
Parents:
87608a5
Message:

Small improvements in the async framework.

  • Provide functions for initialization of amsg_t and awaiter_t.
  • Add async_forget() to mark messages that can be discarded right on their arrival because the recipient is no longer interested in the reply.
  • Add a couple of asserts to make sure that the async_wait_for(), async_wait_timeout() and async_forget() are not used inappropriately.
Location:
uspace/lib/c
Files:
4 edited

Legend:

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

    r87608a5 r47c9a8c  
    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;
    191197       
    192198        /** Pointer to where the answer data is stored. */
     
    240246/** Identifier of the incoming connection handled by the current fibril. */
    241247static fibril_local connection_t *fibril_connection;
     248
     249static void to_event_initialize(to_event_t *to)
     250{
     251        struct timeval tv = { 0 };
     252
     253        to->inlist = false;
     254        to->occurred = false;
     255        link_initialize(&to->link);
     256        to->expires = tv;
     257}
     258
     259static void wu_event_initialize(wu_event_t *wu)
     260{
     261        wu->inlist = false;
     262        link_initialize(&wu->link);
     263}
     264
     265void 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
     273static 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
     290static void amsg_destroy(amsg_t *msg)
     291{
     292        assert(!msg->destroyed);
     293        msg->destroyed = true;
     294        free(msg);
     295}
    242296
    243297static void *default_client_data_constructor(void)
     
    11001154       
    11011155        msg->done = true;
    1102         if (!msg->wdata.active) {
     1156
     1157        if (msg->forget) {
     1158                assert(msg->wdata.active);
     1159                amsg_destroy(msg);
     1160        } else if (!msg->wdata.active) {
    11031161                msg->wdata.active = true;
    11041162                fibril_add_ready(msg->wdata.fid);
    11051163        }
    1106        
     1164
    11071165        futex_up(&async_futex);
    11081166}
     
    11311189                return 0;
    11321190       
    1133         amsg_t *msg = malloc(sizeof(amsg_t));
     1191        amsg_t *msg = amsg_create();
    11341192        if (msg == NULL)
    11351193                return 0;
    11361194       
    1137         msg->done = false;
    11381195        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          */
    11461196        msg->wdata.active = true;
    11471197       
     
    11771227                return 0;
    11781228       
    1179         amsg_t *msg = malloc(sizeof(amsg_t));
    1180        
     1229        amsg_t *msg = amsg_create();
    11811230        if (msg == NULL)
    11821231                return 0;
    11831232       
    1184         msg->done = false;
    11851233        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          */
    11931234        msg->wdata.active = true;
    11941235       
     
    12131254       
    12141255        futex_down(&async_futex);
     1256
     1257        assert(!msg->forget);
     1258        assert(!msg->destroyed);
     1259
    12151260        if (msg->done) {
    12161261                futex_up(&async_futex);
     
    12311276                *retval = msg->retval;
    12321277       
    1233         free(msg);
     1278        amsg_destroy(msg);
    12341279}
    12351280
    12361281/** Wait for a message sent by the async framework, timeout variant.
     1282 *
     1283 * If the wait times out, the caller may choose to either wait again by calling
     1284 * async_wait_for() or async_wait_timeout(), or forget the message via
     1285 * async_forget().
    12371286 *
    12381287 * @param amsgid  Hash of the message to wait for.
     
    12551304       
    12561305        futex_down(&async_futex);
     1306
     1307        assert(!msg->forget);
     1308        assert(!msg->destroyed);
     1309
    12571310        if (msg->done) {
    12581311                futex_up(&async_futex);
     
    12791332                *retval = msg->retval;
    12801333       
    1281         free(msg);
     1334        amsg_destroy(msg);
    12821335       
    12831336        return 0;
    12841337}
     1338 
     1339/** Discard the message / reply on arrival.
     1340 *
     1341 * The message will be marked to be discarded once the reply arrives in
     1342 * reply_received(). It is not allowed to call async_wait_for() or
     1343 * async_wait_timeout() on this message after a call to this function.
     1344 *
     1345 * @param amsgid  Hash of the message to forget.
     1346 */
     1347void async_forget(aid_t amsgid)
     1348{
     1349        amsg_t *msg = (amsg_t *) amsgid;
     1350
     1351        assert(msg);
     1352        assert(!msg->forget);
     1353        assert(!msg->destroyed);
     1354
     1355        futex_down(&async_futex);
     1356        if (msg->done)
     1357                amsg_destroy(msg);
     1358        else
     1359                msg->forget = true;
     1360        futex_up(&async_futex);
     1361}
    12851362
    12861363/** Wait for specified time.
     
    12931370void async_usleep(suseconds_t timeout)
    12941371{
    1295         amsg_t *msg = malloc(sizeof(amsg_t));
    1296        
     1372        amsg_t *msg = amsg_create();
    12971373        if (!msg)
    12981374                return;
    12991375       
    13001376        msg->wdata.fid = fibril_get_id();
    1301         msg->wdata.active = false;
    13021377       
    13031378        gettimeofday(&msg->wdata.to_event.expires, NULL);
     
    13131388        /* Futex is up automatically after fibril_switch() */
    13141389       
    1315         free(msg);
     1390        amsg_destroy(msg);
    13161391}
    13171392
     
    15841659        ipc_call_t result;
    15851660       
    1586         amsg_t *msg = malloc(sizeof(amsg_t));
    1587         if (msg == NULL) {
     1661        amsg_t *msg = amsg_create();
     1662        if (!msg) {
    15881663                free(sess);
    15891664                errno = ENOMEM;
     
    15911666        }
    15921667       
    1593         msg->done = false;
    15941668        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          */
    16021669        msg->wdata.active = true;
    16031670       
     
    16431710        ipc_call_t result;
    16441711       
    1645         amsg_t *msg = malloc(sizeof(amsg_t));
    1646         if (msg == NULL)
     1712        amsg_t *msg = amsg_create();
     1713        if (!msg)
    16471714                return ENOENT;
    16481715       
    1649         msg->done = false;
    16501716        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          */
    16581717        msg->wdata.active = true;
    16591718       
  • uspace/lib/c/generic/fibril_synch.c

    r87608a5 r47c9a8c  
    112112                awaiter_t wdata;
    113113
     114                awaiter_initialize(&wdata);
    114115                wdata.fid = fibril_get_id();
    115                 wdata.active = false;
    116116                wdata.wu_event.inlist = true;
    117                 link_initialize(&wdata.wu_event.link);
    118117                list_append(&wdata.wu_event.link, &fm->waiters);
    119118                check_for_deadlock(&fm->oi);
     
    205204                awaiter_t wdata;
    206205
     206                awaiter_initialize(&wdata);
    207207                wdata.fid = (fid_t) f;
    208                 wdata.active = false;
    209208                wdata.wu_event.inlist = true;
    210                 link_initialize(&wdata.wu_event.link);
    211209                f->flags &= ~FIBRIL_WRITER;
    212210                list_append(&wdata.wu_event.link, &frw->waiters);
     
    233231                awaiter_t wdata;
    234232
     233                awaiter_initialize(&wdata);
    235234                wdata.fid = (fid_t) f;
    236                 wdata.active = false;
    237235                wdata.wu_event.inlist = true;
    238                 link_initialize(&wdata.wu_event.link);
    239236                f->flags |= FIBRIL_WRITER;
    240237                list_append(&wdata.wu_event.link, &frw->waiters);
     
    375372                return ETIMEOUT;
    376373
     374        awaiter_initialize(&wdata);
    377375        wdata.fid = fibril_get_id();
    378         wdata.active = false;
    379        
    380376        wdata.to_event.inlist = timeout > 0;
    381         wdata.to_event.occurred = false;
    382         link_initialize(&wdata.to_event.link);
    383 
    384377        wdata.wu_event.inlist = true;
    385         link_initialize(&wdata.wu_event.link);
    386378
    387379        futex_down(&async_futex);
  • uspace/lib/c/generic/private/async.h

    r87608a5 r47c9a8c  
    8181} awaiter_t;
    8282
     83extern void awaiter_initialize(awaiter_t *);
     84
    8385extern void __async_init(void);
    8486extern void async_insert_timeout(awaiter_t *);
  • uspace/lib/c/include/async.h

    r87608a5 r47c9a8c  
    139139extern void async_wait_for(aid_t, sysarg_t *);
    140140extern int async_wait_timeout(aid_t, sysarg_t *, suseconds_t);
     141extern void async_forget(aid_t);
    141142
    142143extern fid_t async_new_connection(task_id_t, sysarg_t, ipc_callid_t,
Note: See TracChangeset for help on using the changeset viewer.