Changeset f307f12 in mainline for uspace/lib/libc


Ignore:
Timestamp:
2009-10-11T16:26:01Z (16 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c088fd4
Parents:
c123609 (diff), ba8f8cb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge experimental support for timeoutable fibril condition variables.
The merge includes a fix for an IPC/async framework problem caused by the fact
that timeoutable entities in the async framework (and also fibril
synchronization code) often call gettimeofday() when async_futex is held, and
the fact that gettimeofday() had a dependency on async framework.

Location:
uspace/lib/libc
Files:
1 added
9 edited

Legend:

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

    rc123609 rf307f12  
    8383 *
    8484 *     callid = async_get_call(&call);
    85  *     handle_call(callid, call);
     85 *     somehow_handle_the_call(callid, call);
    8686 *     ipc_answer_2(callid, 1, 2, 3);
    8787 *
     
    9494#include <futex.h>
    9595#include <async.h>
     96#include <async_priv.h>
    9697#include <fibril.h>
    9798#include <stdio.h>
     
    110111atomic_t threads_in_ipc_wait = { 0 };
    111112
    112 /** Structures of this type represent a waiting fibril. */
    113 typedef struct {
    114         /** Expiration time. */
    115         struct timeval expires;
    116        
    117         /** If true, this struct is in the timeout list. */
    118         bool inlist;
    119        
    120         /** Timeout list link. */
    121         link_t link;
    122        
    123         /** Identification of and link to the waiting fibril. */
    124         fid_t fid;
    125        
    126         /** If true, this fibril is currently active. */
    127         bool active;
    128        
    129         /** If true, we have timed out. */
    130         bool timedout;
    131 } awaiter_t;
    132 
    133113typedef struct {
    134114        awaiter_t wdata;
     
    253233 *
    254234 */
    255 static void insert_timeout(awaiter_t *wd)
    256 {
    257         wd->timedout = false;
    258         wd->inlist = true;
     235void async_insert_timeout(awaiter_t *wd)
     236{
     237        wd->to_event.occurred = false;
     238        wd->to_event.inlist = true;
    259239       
    260240        link_t *tmp = timeout_list.next;
    261241        while (tmp != &timeout_list) {
    262                 awaiter_t *cur = list_get_instance(tmp, awaiter_t, link);
    263                
    264                 if (tv_gteq(&cur->expires, &wd->expires))
     242                awaiter_t *cur;
     243               
     244                cur = list_get_instance(tmp, awaiter_t, to_event.link);
     245                if (tv_gteq(&cur->to_event.expires, &wd->to_event.expires))
    265246                        break;
    266                
    267247                tmp = tmp->next;
    268248        }
    269249       
    270         list_append(&wd->link, tmp);
     250        list_append(&wd->to_event.link, tmp);
    271251}
    272252
     
    315295               
    316296                /* If in timeout list, remove it */
    317                 if (conn->wdata.inlist) {
    318                         conn->wdata.inlist = false;
    319                         list_remove(&conn->wdata.link);
     297                if (conn->wdata.to_event.inlist) {
     298                        conn->wdata.to_event.inlist = false;
     299                        list_remove(&conn->wdata.to_event.link);
    320300                }
    321301               
     
    405385       
    406386        if (usecs) {
    407                 gettimeofday(&conn->wdata.expires, NULL);
    408                 tv_add(&conn->wdata.expires, usecs);
     387                gettimeofday(&conn->wdata.to_event.expires, NULL);
     388                tv_add(&conn->wdata.to_event.expires, usecs);
    409389        } else
    410                 conn->wdata.inlist = false;
     390                conn->wdata.to_event.inlist = false;
    411391       
    412392        /* If nothing in queue, wait until something arrives */
    413393        while (list_empty(&conn->msg_queue)) {
    414394                if (usecs)
    415                         insert_timeout(&conn->wdata);
     395                        async_insert_timeout(&conn->wdata);
    416396               
    417397                conn->wdata.active = false;
     
    430410                 */
    431411                futex_down(&async_futex);
    432                 if ((usecs) && (conn->wdata.timedout)
     412                if ((usecs) && (conn->wdata.to_event.occurred)
    433413                    && (list_empty(&conn->msg_queue))) {
    434414                        /* If we timed out -> exit */
     
    625605        link_t *cur = timeout_list.next;
    626606        while (cur != &timeout_list) {
    627                 awaiter_t *waiter = list_get_instance(cur, awaiter_t, link);
    628                
    629                 if (tv_gt(&waiter->expires, &tv))
     607                awaiter_t *waiter;
     608               
     609                waiter = list_get_instance(cur, awaiter_t, to_event.link);
     610                if (tv_gt(&waiter->to_event.expires, &tv))
    630611                        break;
    631                
     612
    632613                cur = cur->next;
    633                
    634                 list_remove(&waiter->link);
    635                 waiter->inlist = false;
    636                 waiter->timedout = true;
     614
     615                list_remove(&waiter->to_event.link);
     616                waiter->to_event.inlist = false;
     617                waiter->to_event.occurred = true;
    637618               
    638619                /*
     
    671652                if (!list_empty(&timeout_list)) {
    672653                        awaiter_t *waiter = list_get_instance(timeout_list.next,
    673                             awaiter_t, link);
     654                            awaiter_t, to_event.link);
    674655                       
    675656                        struct timeval tv;
    676657                        gettimeofday(&tv, NULL);
    677658                       
    678                         if (tv_gteq(&tv, &waiter->expires)) {
     659                        if (tv_gteq(&tv, &waiter->to_event.expires)) {
    679660                                futex_up(&async_futex);
    680661                                handle_expired_timeouts();
    681662                                continue;
    682663                        } else
    683                                 timeout = tv_sub(&waiter->expires, &tv);
     664                                timeout = tv_sub(&waiter->to_event.expires,
     665                                    &tv);
    684666                } else
    685667                        timeout = SYNCH_NO_TIMEOUT;
     
    782764       
    783765        /* Remove message from timeout list */
    784         if (msg->wdata.inlist)
    785                 list_remove(&msg->wdata.link);
     766        if (msg->wdata.to_event.inlist)
     767                list_remove(&msg->wdata.to_event.link);
    786768       
    787769        msg->done = true;
     
    822804        msg->dataptr = dataptr;
    823805       
    824         msg->wdata.inlist = false;
     806        msg->wdata.to_event.inlist = false;
    825807        /* We may sleep in the next method, but it will use its own mechanism */
    826808        msg->wdata.active = true;
     
    862844        msg->dataptr = dataptr;
    863845       
    864         msg->wdata.inlist = false;
     846        msg->wdata.to_event.inlist = false;
    865847        /* We may sleep in next method, but it will use its own mechanism */
    866848        msg->wdata.active = true;
     
    891873        msg->wdata.fid = fibril_get_id();
    892874        msg->wdata.active = false;
    893         msg->wdata.inlist = false;
     875        msg->wdata.to_event.inlist = false;
    894876       
    895877        /* Leave the async_futex locked when entering this function */
     
    929911        }
    930912       
    931         gettimeofday(&msg->wdata.expires, NULL);
    932         tv_add(&msg->wdata.expires, timeout);
     913        gettimeofday(&msg->wdata.to_event.expires, NULL);
     914        tv_add(&msg->wdata.to_event.expires, timeout);
    933915       
    934916        msg->wdata.fid = fibril_get_id();
    935917        msg->wdata.active = false;
    936         insert_timeout(&msg->wdata);
     918        async_insert_timeout(&msg->wdata);
    937919       
    938920        /* Leave the async_futex locked when entering this function */
     
    970952        msg->wdata.active = false;
    971953       
    972         gettimeofday(&msg->wdata.expires, NULL);
    973         tv_add(&msg->wdata.expires, timeout);
     954        gettimeofday(&msg->wdata.to_event.expires, NULL);
     955        tv_add(&msg->wdata.to_event.expires, timeout);
    974956       
    975957        futex_down(&async_futex);
    976958       
    977         insert_timeout(&msg->wdata);
     959        async_insert_timeout(&msg->wdata);
    978960       
    979961        /* Leave the async_futex locked when entering this function */
     
    11051087}
    11061088
     1089/** Wrapper for making IPC_M_SHARE_IN calls using the async framework.
     1090 *
     1091 * @param phoneid       Phone that will be used to contact the receiving side.
     1092 * @param dst           Destination address space area base.
     1093 * @param size          Size of the destination address space area.
     1094 * @param arg           User defined argument.
     1095 * @param flags         Storage where the received flags will be stored. Can be
     1096 *                      NULL.
     1097 *
     1098 * @return              Zero on success or a negative error code from errno.h.
     1099 */
     1100int async_share_in_start(int phoneid, void *dst, size_t size, ipcarg_t arg,
     1101    int *flags)
     1102{
     1103        int res;
     1104        sysarg_t tmp_flags;
     1105        res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst,
     1106            (ipcarg_t) size, arg, NULL, &tmp_flags);
     1107        if (flags)
     1108                *flags = tmp_flags;
     1109        return res;
     1110}
     1111
     1112/** Wrapper for receiving the IPC_M_SHARE_IN calls using the async framework.
     1113 *
     1114 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN calls
     1115 * so that the user doesn't have to remember the meaning of each IPC argument.
     1116 *
     1117 * So far, this wrapper is to be used from within a connection fibril.
     1118 *
     1119 * @param callid        Storage where the hash of the IPC_M_SHARE_IN call will
     1120 *                      be stored.
     1121 * @param size          Destination address space area size.   
     1122 *
     1123 * @return              Non-zero on success, zero on failure.
     1124 */
     1125int async_share_in_receive(ipc_callid_t *callid, size_t *size)
     1126{
     1127        ipc_call_t data;
     1128       
     1129        assert(callid);
     1130        assert(size);
     1131
     1132        *callid = async_get_call(&data);
     1133        if (IPC_GET_METHOD(data) != IPC_M_SHARE_IN)
     1134                return 0;
     1135        *size = (size_t) IPC_GET_ARG2(data);
     1136        return 1;
     1137}
     1138
     1139/** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework.
     1140 *
     1141 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
     1142 * so that the user doesn't have to remember the meaning of each IPC argument.
     1143 *
     1144 * @param callid        Hash of the IPC_M_DATA_READ call to answer.
     1145 * @param src           Source address space base.
     1146 * @param flags         Flags to be used for sharing. Bits can be only cleared.
     1147 *
     1148 * @return              Zero on success or a value from @ref errno.h on failure.
     1149 */
     1150int async_share_in_finalize(ipc_callid_t callid, void *src, int flags)
     1151{
     1152        return ipc_share_in_finalize(callid, src, flags);
     1153}
     1154
     1155/** Wrapper for making IPC_M_SHARE_OUT calls using the async framework.
     1156 *
     1157 * @param phoneid       Phone that will be used to contact the receiving side.
     1158 * @param src           Source address space area base address.
     1159 * @param flags         Flags to be used for sharing. Bits can be only cleared.
     1160 *
     1161 * @return              Zero on success or a negative error code from errno.h.
     1162 */
     1163int async_share_out_start(int phoneid, void *src, int flags)
     1164{
     1165        return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0,
     1166            (ipcarg_t) flags);
     1167}
     1168
     1169/** Wrapper for receiving the IPC_M_SHARE_OUT calls using the async framework.
     1170 *
     1171 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT calls
     1172 * so that the user doesn't have to remember the meaning of each IPC argument.
     1173 *
     1174 * So far, this wrapper is to be used from within a connection fibril.
     1175 *
     1176 * @param callid        Storage where the hash of the IPC_M_SHARE_OUT call will
     1177 *                      be stored.
     1178 * @param size          Storage where the source address space area size will be
     1179 *                      stored.
     1180 * @param flags         Storage where the sharing flags will be stored.
     1181 *
     1182 * @return              Non-zero on success, zero on failure.
     1183 */
     1184int async_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags)
     1185{
     1186        ipc_call_t data;
     1187       
     1188        assert(callid);
     1189        assert(size);
     1190        assert(flags);
     1191
     1192        *callid = async_get_call(&data);
     1193        if (IPC_GET_METHOD(data) != IPC_M_SHARE_OUT)
     1194                return 0;
     1195        *size = (size_t) IPC_GET_ARG2(data);
     1196        *flags = (int) IPC_GET_ARG3(data);
     1197        return 1;
     1198}
     1199
     1200/** Wrapper for answering the IPC_M_SHARE_OUT calls using the async framework.
     1201 *
     1202 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls
     1203 * so that the user doesn't have to remember the meaning of each IPC argument.
     1204 *
     1205 * @param callid        Hash of the IPC_M_DATA_WRITE call to answer.
     1206 * @param dst           Destination address space area base address.   
     1207 *
     1208 * @return              Zero on success or a value from @ref errno.h on failure.
     1209 */
     1210int async_share_out_finalize(ipc_callid_t callid, void *dst)
     1211{
     1212        return ipc_share_out_finalize(callid, dst);
     1213}
     1214
     1215
     1216/** Wrapper for making IPC_M_DATA_READ calls using the async framework.
     1217 *
     1218 * @param phoneid       Phone that will be used to contact the receiving side.
     1219 * @param dst           Address of the beginning of the destination buffer.
     1220 * @param size          Size of the destination buffer.
     1221 *
     1222 * @return              Zero on success or a negative error code from errno.h.
     1223 */
     1224int async_data_read_start(int phoneid, void *dst, size_t size)
     1225{
     1226        return async_req_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst,
     1227            (ipcarg_t) size);
     1228}
     1229
     1230/** Wrapper for receiving the IPC_M_DATA_READ calls using the async framework.
     1231 *
     1232 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ calls
     1233 * so that the user doesn't have to remember the meaning of each IPC argument.
     1234 *
     1235 * So far, this wrapper is to be used from within a connection fibril.
     1236 *
     1237 * @param callid        Storage where the hash of the IPC_M_DATA_READ call will
     1238 *                      be stored.
     1239 * @param size          Storage where the maximum size will be stored. Can be
     1240 *                      NULL.
     1241 *
     1242 * @return              Non-zero on success, zero on failure.
     1243 */
     1244int async_data_read_receive(ipc_callid_t *callid, size_t *size)
     1245{
     1246        ipc_call_t data;
     1247       
     1248        assert(callid);
     1249
     1250        *callid = async_get_call(&data);
     1251        if (IPC_GET_METHOD(data) != IPC_M_DATA_READ)
     1252                return 0;
     1253        if (size)
     1254                *size = (size_t) IPC_GET_ARG2(data);
     1255        return 1;
     1256}
     1257
     1258/** Wrapper for answering the IPC_M_DATA_READ calls using the async framework.
     1259 *
     1260 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
     1261 * so that the user doesn't have to remember the meaning of each IPC argument.
     1262 *
     1263 * @param callid        Hash of the IPC_M_DATA_READ call to answer.
     1264 * @param src           Source address for the IPC_M_DATA_READ call.
     1265 * @param size          Size for the IPC_M_DATA_READ call. Can be smaller than
     1266 *                      the maximum size announced by the sender.
     1267 *
     1268 * @return              Zero on success or a value from @ref errno.h on failure.
     1269 */
     1270int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
     1271{
     1272        return ipc_data_read_finalize(callid, src, size);
     1273}
     1274
     1275/** Wrapper for making IPC_M_DATA_WRITE calls using the async framework.
     1276 *
     1277 * @param phoneid       Phone that will be used to contact the receiving side.
     1278 * @param src           Address of the beginning of the source buffer.
     1279 * @param size          Size of the source buffer.
     1280 *
     1281 * @return              Zero on success or a negative error code from errno.h.
     1282 */
     1283int async_data_write_start(int phoneid, const void *src, size_t size)
     1284{
     1285        return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
     1286            (ipcarg_t) size);
     1287}
     1288
     1289/** Wrapper for receiving the IPC_M_DATA_WRITE calls using the async framework.
     1290 *
     1291 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE calls
     1292 * so that the user doesn't have to remember the meaning of each IPC argument.
     1293 *
     1294 * So far, this wrapper is to be used from within a connection fibril.
     1295 *
     1296 * @param callid        Storage where the hash of the IPC_M_DATA_WRITE call will
     1297 *                      be stored.
     1298 * @param size          Storage where the suggested size will be stored. May be
     1299 *                      NULL
     1300 *
     1301 * @return              Non-zero on success, zero on failure.
     1302 */
     1303int async_data_write_receive(ipc_callid_t *callid, size_t *size)
     1304{
     1305        ipc_call_t data;
     1306       
     1307        assert(callid);
     1308
     1309        *callid = async_get_call(&data);
     1310        if (IPC_GET_METHOD(data) != IPC_M_DATA_WRITE)
     1311                return 0;
     1312        if (size)
     1313                *size = (size_t) IPC_GET_ARG2(data);
     1314        return 1;
     1315}
     1316
     1317/** Wrapper for answering the IPC_M_DATA_WRITE calls using the async framework.
     1318 *
     1319 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls
     1320 * so that the user doesn't have to remember the meaning of each IPC argument.
     1321 *
     1322 * @param callid        Hash of the IPC_M_DATA_WRITE call to answer.
     1323 * @param dst           Final destination address for the IPC_M_DATA_WRITE call.
     1324 * @param size          Final size for the IPC_M_DATA_WRITE call.
     1325 *
     1326 * @return              Zero on success or a value from @ref errno.h on failure.
     1327 */
     1328int async_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
     1329{
     1330        return ipc_data_write_finalize(callid, dst, size);
     1331}
     1332
    11071333/** @}
    11081334 */
  • uspace/lib/libc/generic/devmap.c

    rc123609 rf307f12  
    105105        aid_t req = async_send_2(phone, DEVMAP_DRIVER_REGISTER, 0, 0, &answer);
    106106       
    107         ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
     107        ipcarg_t retval = async_data_write_start(phone, name, str_size(name) + 1);
    108108       
    109109        if (retval != EOK) {
     
    143143            &answer);
    144144       
    145         ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
     145        ipcarg_t retval = async_data_write_start(phone, name, str_size(name) + 1);
    146146       
    147147        if (retval != EOK) {
     
    180180            &answer);
    181181       
    182         ipcarg_t retval = ipc_data_write_start(phone, name, str_size(name) + 1);
     182        ipcarg_t retval = async_data_write_start(phone, name, str_size(name) + 1);
    183183       
    184184        if (retval != EOK) {
     
    271271        aid_t req = async_send_0(phone, DEVMAP_DEVICE_GET_DEVICES, &answer);
    272272       
    273         ipcarg_t retval = ipc_data_read_start(phone, data, count * sizeof(dev_desc_t));
     273        ipcarg_t retval = async_data_read_start(phone, data, count * sizeof(dev_desc_t));
    274274       
    275275        if (retval != EOK) {
  • uspace/lib/libc/generic/fibril_sync.c

    rc123609 rf307f12  
    3636#include <fibril.h>
    3737#include <async.h>
     38#include <async_priv.h>
    3839#include <adt/list.h>
    3940#include <futex.h>
     41#include <sys/time.h>
     42#include <errno.h>
    4043#include <assert.h>
    4144
     
    6366        futex_down(&async_futex);
    6467        if (fm->counter-- <= 0) {
    65                 fibril_t *f = (fibril_t *) fibril_get_id();
    66                 list_append(&f->link, &fm->waiters);
     68                awaiter_t wdata;
     69
     70                wdata.fid = fibril_get_id();
     71                wdata.active = false;
     72                wdata.wu_event.inlist = true;
     73                link_initialize(&wdata.wu_event.link);
     74                list_append(&wdata.wu_event.link, &fm->waiters);
    6775                fibril_switch(FIBRIL_TO_MANAGER);
    6876        } else {
     
    9098        if (fm->counter++ < 0) {
    9199                link_t *tmp;
    92                 fibril_t *f;
     100                awaiter_t *wdp;
    93101       
    94102                assert(!list_empty(&fm->waiters));
    95103                tmp = fm->waiters.next;
    96                 f = list_get_instance(tmp, fibril_t, link);
    97                 list_remove(&f->link);
    98                 fibril_add_ready((fid_t) f);
     104                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     105                wdp->active = true;
     106                wdp->wu_event.inlist = false;
     107                list_remove(&wdp->wu_event.link);
     108                fibril_add_ready(wdp->fid);
    99109                optimize_execution_power();
    100110        }
     
    120130        if (frw->writers) {
    121131                fibril_t *f = (fibril_t *) fibril_get_id();
     132                awaiter_t wdata;
     133
     134                wdata.fid = (fid_t) f;
     135                wdata.active = false;
     136                wdata.wu_event.inlist = true;
     137                link_initialize(&wdata.wu_event.link);
    122138                f->flags &= ~FIBRIL_WRITER;
    123                 list_append(&f->link, &frw->waiters);
     139                list_append(&wdata.wu_event.link, &frw->waiters);
    124140                fibril_switch(FIBRIL_TO_MANAGER);
    125141        } else {
     
    134150        if (frw->writers || frw->readers) {
    135151                fibril_t *f = (fibril_t *) fibril_get_id();
     152                awaiter_t wdata;
     153
     154                wdata.fid = (fid_t) f;
     155                wdata.active = false;
     156                wdata.wu_event.inlist = true;
     157                link_initialize(&wdata.wu_event.link);
    136158                f->flags |= FIBRIL_WRITER;
    137                 list_append(&f->link, &frw->waiters);
     159                list_append(&wdata.wu_event.link, &frw->waiters);
    138160                fibril_switch(FIBRIL_TO_MANAGER);
    139161        } else {
     
    158180        while (!list_empty(&frw->waiters)) {
    159181                link_t *tmp = frw->waiters.next;
    160                 fibril_t *f = list_get_instance(tmp, fibril_t, link);
     182                awaiter_t *wdp;
     183                fibril_t *f;
     184               
     185                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     186                f = (fibril_t *) wdp->fid;
    161187               
    162188                if (f->flags & FIBRIL_WRITER) {
    163189                        if (frw->readers)
    164190                                break;
    165                         list_remove(&f->link);
    166                         fibril_add_ready((fid_t) f);
     191                        wdp->active = true;
     192                        wdp->wu_event.inlist = false;
     193                        list_remove(&wdp->wu_event.link);
     194                        fibril_add_ready(wdp->fid);
    167195                        frw->writers++;
    168196                        optimize_execution_power();
    169197                        break;
    170198                } else {
    171                         list_remove(&f->link);
    172                         fibril_add_ready((fid_t) f);
     199                        wdp->active = true;
     200                        wdp->wu_event.inlist = false;
     201                        list_remove(&wdp->wu_event.link);
     202                        fibril_add_ready(wdp->fid);
    173203                        frw->readers++;
    174204                        optimize_execution_power();
     
    194224}
    195225
    196 void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
    197 {
    198         fibril_t *f = (fibril_t *) fibril_get_id();
    199 
    200         futex_down(&async_futex);
    201         list_append(&f->link, &fcv->waiters);
     226int
     227fibril_condvar_wait_timeout(fibril_condvar_t *fcv, fibril_mutex_t *fm,
     228    suseconds_t timeout)
     229{
     230        awaiter_t wdata;
     231
     232        if (timeout < 0)
     233                return ETIMEOUT;
     234
     235        wdata.fid = fibril_get_id();
     236        wdata.active = false;
     237       
     238        wdata.to_event.inlist = timeout > 0;
     239        wdata.to_event.occurred = false;
     240        link_initialize(&wdata.to_event.link);
     241
     242        wdata.wu_event.inlist = true;
     243        link_initialize(&wdata.wu_event.link);
     244
     245        futex_down(&async_futex);
     246        if (timeout) {
     247                gettimeofday(&wdata.to_event.expires, NULL);
     248                tv_add(&wdata.to_event.expires, timeout);
     249                async_insert_timeout(&wdata);
     250        }
     251        list_append(&wdata.wu_event.link, &fcv->waiters);
    202252        _fibril_mutex_unlock_unsafe(fm);
    203253        fibril_switch(FIBRIL_TO_MANAGER);
    204254        fibril_mutex_lock(fm);
     255
     256        /* async_futex not held after fibril_switch() */
     257        futex_down(&async_futex);
     258        if (wdata.to_event.inlist)
     259                list_remove(&wdata.to_event.link);
     260        if (wdata.wu_event.inlist)
     261                list_remove(&wdata.wu_event.link);
     262        futex_up(&async_futex);
     263       
     264        return wdata.to_event.occurred ? ETIMEOUT : EOK;
     265}
     266
     267void fibril_condvar_wait(fibril_condvar_t *fcv, fibril_mutex_t *fm)
     268{
     269        int rc;
     270
     271        rc = fibril_condvar_wait_timeout(fcv, fm, 0);
     272        assert(rc == EOK);
    205273}
    206274
     
    208276{
    209277        link_t *tmp;
    210         fibril_t *f;
     278        awaiter_t *wdp;
    211279
    212280        futex_down(&async_futex);
    213281        while (!list_empty(&fcv->waiters)) {
    214282                tmp = fcv->waiters.next;
    215                 f = list_get_instance(tmp, fibril_t, link);
    216                 list_remove(&f->link);
    217                 fibril_add_ready((fid_t) f);
    218                 optimize_execution_power();
    219                 if (once)
    220                         break;
     283                wdp = list_get_instance(tmp, awaiter_t, wu_event.link);
     284                list_remove(&wdp->wu_event.link);
     285                wdp->wu_event.inlist = false;
     286                if (!wdp->active) {
     287                        wdp->active = true;
     288                        fibril_add_ready(wdp->fid);
     289                        optimize_execution_power();
     290                        if (once)
     291                                break;
     292                }
    221293        }
    222294        futex_up(&async_futex);
  • uspace/lib/libc/generic/ipc.c

    rc123609 rf307f12  
    730730        int res;
    731731        sysarg_t tmp_flags;
    732         res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst,
     732        res = ipc_call_sync_3_2(phoneid, IPC_M_SHARE_IN, (ipcarg_t) dst,
    733733            (ipcarg_t) size, arg, NULL, &tmp_flags);
    734734        if (flags)
     
    737737}
    738738
    739 /** Wrapper for receiving the IPC_M_SHARE_IN calls.
    740  *
    741  * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN calls
    742  * so that the user doesn't have to remember the meaning of each IPC argument.
    743  *
    744  * So far, this wrapper is to be used from within a connection fibril.
    745  *
    746  * @param callid        Storage where the hash of the IPC_M_SHARE_IN call will
    747  *                      be stored.
    748  * @param size          Destination address space area size.   
    749  *
    750  * @return              Non-zero on success, zero on failure.
    751  */
    752 int ipc_share_in_receive(ipc_callid_t *callid, size_t *size)
    753 {
    754         ipc_call_t data;
    755        
    756         assert(callid);
    757         assert(size);
    758 
    759         *callid = async_get_call(&data);
    760         if (IPC_GET_METHOD(data) != IPC_M_SHARE_IN)
    761                 return 0;
    762         *size = (size_t) IPC_GET_ARG2(data);
    763         return 1;
    764 }
    765 
    766739/** Wrapper for answering the IPC_M_SHARE_IN calls.
    767740 *
     
    790763int ipc_share_out_start(int phoneid, void *src, int flags)
    791764{
    792         return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0,
     765        return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (ipcarg_t) src, 0,
    793766            (ipcarg_t) flags);
    794 }
    795 
    796 /** Wrapper for receiving the IPC_M_SHARE_OUT calls.
    797  *
    798  * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT calls
    799  * so that the user doesn't have to remember the meaning of each IPC argument.
    800  *
    801  * So far, this wrapper is to be used from within a connection fibril.
    802  *
    803  * @param callid        Storage where the hash of the IPC_M_SHARE_OUT call will
    804  *                      be stored.
    805  * @param size          Storage where the source address space area size will be
    806  *                      stored.
    807  * @param flags         Storage where the sharing flags will be stored.
    808  *
    809  * @return              Non-zero on success, zero on failure.
    810  */
    811 int ipc_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags)
    812 {
    813         ipc_call_t data;
    814        
    815         assert(callid);
    816         assert(size);
    817         assert(flags);
    818 
    819         *callid = async_get_call(&data);
    820         if (IPC_GET_METHOD(data) != IPC_M_SHARE_OUT)
    821                 return 0;
    822         *size = (size_t) IPC_GET_ARG2(data);
    823         *flags = (int) IPC_GET_ARG3(data);
    824         return 1;
    825767}
    826768
     
    851793int ipc_data_read_start(int phoneid, void *dst, size_t size)
    852794{
    853         return async_req_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst,
     795        return ipc_call_sync_2_0(phoneid, IPC_M_DATA_READ, (ipcarg_t) dst,
    854796            (ipcarg_t) size);
    855 }
    856 
    857 /** Wrapper for receiving the IPC_M_DATA_READ calls.
    858  *
    859  * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ calls
    860  * so that the user doesn't have to remember the meaning of each IPC argument.
    861  *
    862  * So far, this wrapper is to be used from within a connection fibril.
    863  *
    864  * @param callid        Storage where the hash of the IPC_M_DATA_READ call will
    865  *                      be stored.
    866  * @param size          Storage where the maximum size will be stored. Can be
    867  *                      NULL.
    868  *
    869  * @return              Non-zero on success, zero on failure.
    870  */
    871 int ipc_data_read_receive(ipc_callid_t *callid, size_t *size)
    872 {
    873         ipc_call_t data;
    874        
    875         assert(callid);
    876 
    877         *callid = async_get_call(&data);
    878         if (IPC_GET_METHOD(data) != IPC_M_DATA_READ)
    879                 return 0;
    880         if (size)
    881                 *size = (size_t) IPC_GET_ARG2(data);
    882         return 1;
    883797}
    884798
     
    910824int ipc_data_write_start(int phoneid, const void *src, size_t size)
    911825{
    912         return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
     826        return ipc_call_sync_2_0(phoneid, IPC_M_DATA_WRITE, (ipcarg_t) src,
    913827            (ipcarg_t) size);
    914 }
    915 
    916 /** Wrapper for receiving the IPC_M_DATA_WRITE calls.
    917  *
    918  * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE calls
    919  * so that the user doesn't have to remember the meaning of each IPC argument.
    920  *
    921  * So far, this wrapper is to be used from within a connection fibril.
    922  *
    923  * @param callid        Storage where the hash of the IPC_M_DATA_WRITE call will
    924  *                      be stored.
    925  * @param size          Storage where the suggested size will be stored. May be
    926  *                      NULL
    927  *
    928  * @return              Non-zero on success, zero on failure.
    929  */
    930 int ipc_data_write_receive(ipc_callid_t *callid, size_t *size)
    931 {
    932         ipc_call_t data;
    933        
    934         assert(callid);
    935 
    936         *callid = async_get_call(&data);
    937         if (IPC_GET_METHOD(data) != IPC_M_DATA_WRITE)
    938                 return 0;
    939         if (size)
    940                 *size = (size_t) IPC_GET_ARG2(data);
    941         return 1;
    942828}
    943829
  • uspace/lib/libc/generic/loader.c

    rc123609 rf307f12  
    9090        ipc_call_t answer;
    9191        aid_t req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
    92         int rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
     92        int rc = async_data_read_start(ldr->phone_id, task_id, sizeof(task_id_t));
    9393        if (rc != EOK) {
    9494                async_wait_for(req, NULL);
     
    123123        ipc_call_t answer;
    124124        aid_t req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
    125         int rc = ipc_data_write_start(ldr->phone_id, (void *) pa, pa_len);
     125        int rc = async_data_write_start(ldr->phone_id, (void *) pa, pa_len);
    126126        if (rc != EOK) {
    127127                async_wait_for(req, NULL);
     
    178178        ipc_call_t answer;
    179179        aid_t req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
    180         ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
     180        ipcarg_t rc = async_data_write_start(ldr->phone_id, (void *) arg_buf, buffer_size);
    181181        if (rc != EOK) {
    182182                async_wait_for(req, NULL);
     
    232232        ipc_call_t answer;
    233233        aid_t req = async_send_0(ldr->phone_id, LOADER_SET_FILES, &answer);
    234         ipcarg_t rc = ipc_data_write_start(ldr->phone_id, (void *) files_buf,
     234        ipcarg_t rc = async_data_write_start(ldr->phone_id, (void *) files_buf,
    235235            count * sizeof(fdi_node_t));
    236236        if (rc != EOK) {
  • uspace/lib/libc/generic/vfs/vfs.c

    rc123609 rf307f12  
    140140       
    141141        req = async_send_2(vfs_phone, VFS_IN_MOUNT, dev_handle, flags, NULL);
    142         rc = ipc_data_write_start(vfs_phone, (void *) mpa, mpa_size);
     142        rc = async_data_write_start(vfs_phone, (void *) mpa, mpa_size);
    143143        if (rc != EOK) {
    144144                async_wait_for(req, &rc_orig);
     
    152152        }
    153153       
    154         rc = ipc_data_write_start(vfs_phone, (void *) opts, str_size(opts));
     154        rc = async_data_write_start(vfs_phone, (void *) opts, str_size(opts));
    155155        if (rc != EOK) {
    156156                async_wait_for(req, &rc_orig);
     
    164164        }
    165165
    166         rc = ipc_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
     166        rc = async_data_write_start(vfs_phone, (void *) fs_name, str_size(fs_name));
    167167        if (rc != EOK) {
    168168                async_wait_for(req, &rc_orig);
     
    213213       
    214214        req = async_send_3(vfs_phone, VFS_IN_OPEN, lflag, oflag, 0, &answer);
    215         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
     215        rc = async_data_write_start(vfs_phone, pa, pa_size);
    216216        if (rc != EOK) {
    217217                ipcarg_t rc_orig;
     
    290290       
    291291        req = async_send_1(vfs_phone, VFS_IN_READ, fildes, &answer);
    292         rc = ipc_data_read_start(vfs_phone, (void *)buf, nbyte);
     292        rc = async_data_read_start(vfs_phone, (void *)buf, nbyte);
    293293        if (rc != EOK) {
    294294                ipcarg_t rc_orig;
     
    322322       
    323323        req = async_send_1(vfs_phone, VFS_IN_WRITE, fildes, &answer);
    324         rc = ipc_data_write_start(vfs_phone, (void *)buf, nbyte);
     324        rc = async_data_write_start(vfs_phone, (void *)buf, nbyte);
    325325        if (rc != EOK) {
    326326                ipcarg_t rc_orig;
     
    402402       
    403403        req = async_send_1(vfs_phone, VFS_IN_FSTAT, fildes, NULL);
    404         rc = ipc_data_read_start(vfs_phone, (void *)stat, sizeof(struct stat));
     404        rc = async_data_read_start(vfs_phone, (void *)stat, sizeof(struct stat));
    405405        if (rc != EOK) {
    406406                ipcarg_t rc_orig;
     
    437437       
    438438        req = async_send_0(vfs_phone, VFS_IN_STAT, NULL);
    439         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
     439        rc = async_data_write_start(vfs_phone, pa, pa_size);
    440440        if (rc != EOK) {
    441441                async_wait_for(req, &rc_orig);
     
    448448                        return (int) rc_orig;
    449449        }
    450         rc = ipc_data_read_start(vfs_phone, stat, sizeof(struct stat));
     450        rc = async_data_read_start(vfs_phone, stat, sizeof(struct stat));
    451451        if (rc != EOK) {
    452452                async_wait_for(req, &rc_orig);
     
    514514       
    515515        req = async_send_1(vfs_phone, VFS_IN_MKDIR, mode, NULL);
    516         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
     516        rc = async_data_write_start(vfs_phone, pa, pa_size);
    517517        if (rc != EOK) {
    518518                ipcarg_t rc_orig;
     
    549549       
    550550        req = async_send_0(vfs_phone, VFS_IN_UNLINK, NULL);
    551         rc = ipc_data_write_start(vfs_phone, pa, pa_size);
     551        rc = async_data_write_start(vfs_phone, pa, pa_size);
    552552        if (rc != EOK) {
    553553                ipcarg_t rc_orig;
     
    602602       
    603603        req = async_send_0(vfs_phone, VFS_IN_RENAME, NULL);
    604         rc = ipc_data_write_start(vfs_phone, olda, olda_size);
     604        rc = async_data_write_start(vfs_phone, olda, olda_size);
    605605        if (rc != EOK) {
    606606                async_wait_for(req, &rc_orig);
     
    614614                        return (int) rc_orig;
    615615        }
    616         rc = ipc_data_write_start(vfs_phone, newa, newa_size);
     616        rc = async_data_write_start(vfs_phone, newa, newa_size);
    617617        if (rc != EOK) {
    618618                async_wait_for(req, &rc_orig);
  • uspace/lib/libc/include/async.h

    rc123609 rf307f12  
    259259}
    260260
     261/*
     262 * User-friendly wrappers for async_share_in_start().
     263 */
     264#define async_share_in_start_0_0(phoneid, dst, size) \
     265        async_share_in_start((phoneid), (dst), (size), 0, NULL)
     266#define async_share_in_start_0_1(phoneid, dst, size, flags) \
     267        async_share_in_start((phoneid), (dst), (size), 0, (flags))
     268#define async_share_in_start_1_0(phoneid, dst, size, arg) \
     269        async_share_in_start((phoneid), (dst), (size), (arg), NULL)
     270#define async_share_in_start_1_1(phoneid, dst, size, arg, flags) \
     271        async_share_in_start((phoneid), (dst), (size), (arg), (flags))
     272
     273extern int async_share_in_start(int, void *, size_t, ipcarg_t, int *);
     274extern int async_share_in_receive(ipc_callid_t *, size_t *);
     275extern int async_share_in_finalize(ipc_callid_t, void *, int );
     276extern int async_share_out_start(int, void *, int);
     277extern int async_share_out_receive(ipc_callid_t *, size_t *, int *);
     278extern int async_share_out_finalize(ipc_callid_t, void *);
     279extern int async_data_read_start(int, void *, size_t);
     280extern int async_data_read_receive(ipc_callid_t *, size_t *);
     281extern int async_data_read_finalize(ipc_callid_t, const void *, size_t);
     282extern int async_data_write_start(int, const void *, size_t);
     283extern int async_data_write_receive(ipc_callid_t *, size_t *);
     284extern int async_data_write_finalize(ipc_callid_t, void *, size_t);
     285
    261286#endif
    262287
  • uspace/lib/libc/include/fibril_sync.h

    rc123609 rf307f12  
    4040#include <adt/list.h>
    4141#include <libarch/tls.h>
     42#include <sys/time.h>
    4243
    4344typedef struct {
     
    9596
    9697extern void fibril_condvar_initialize(fibril_condvar_t *);
     98extern int fibril_condvar_wait_timeout(fibril_condvar_t *, fibril_mutex_t *,
     99    suseconds_t);
    97100extern void fibril_condvar_wait(fibril_condvar_t *, fibril_mutex_t *);
    98101extern void fibril_condvar_signal(fibril_condvar_t *);
  • uspace/lib/libc/include/ipc/ipc.h

    rc123609 rf307f12  
    283283
    284284extern int ipc_share_in_start(int, void *, size_t, ipcarg_t, int *);
    285 extern int ipc_share_in_receive(ipc_callid_t *, size_t *);
    286285extern int ipc_share_in_finalize(ipc_callid_t, void *, int );
    287286extern int ipc_share_out_start(int, void *, int);
    288 extern int ipc_share_out_receive(ipc_callid_t *, size_t *, int *);
    289287extern int ipc_share_out_finalize(ipc_callid_t, void *);
    290288extern int ipc_data_read_start(int, void *, size_t);
    291 extern int ipc_data_read_receive(ipc_callid_t *, size_t *);
    292289extern int ipc_data_read_finalize(ipc_callid_t, const void *, size_t);
    293290extern int ipc_data_write_start(int, const void *, size_t);
    294 extern int ipc_data_write_receive(ipc_callid_t *, size_t *);
    295291extern int ipc_data_write_finalize(ipc_callid_t, void *, size_t);
    296292
Note: See TracChangeset for help on using the changeset viewer.