Changeset 7719958 in mainline for uspace/lib/c/generic
- Timestamp:
- 2012-04-23T22:51:36Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6a3808e
- Parents:
- 3293a94 (diff), 32fef47 (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. - Location:
- uspace/lib/c/generic
- Files:
-
- 5 added
- 3 deleted
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async.c
r3293a94 r7719958 189 189 /** If reply was received. */ 190 190 bool done; 191 192 /** If the message / reply should be discarded on arrival. */ 193 bool forget; 194 195 /** If already destroyed. */ 196 bool destroyed; 191 197 192 198 /** Pointer to where the answer data is stored. */ … … 240 246 /** Identifier of the incoming connection handled by the current fibril. */ 241 247 static 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 } 242 296 243 297 static void *default_client_data_constructor(void) … … 892 946 893 947 switch (IPC_GET_IMETHOD(*call)) { 894 case IPC_M_C ONNECT_ME:948 case IPC_M_CLONE_ESTABLISH: 895 949 case IPC_M_CONNECT_ME_TO: 896 950 /* Open new connection with fibril, etc. */ … … 963 1017 964 1018 suseconds_t timeout; 1019 unsigned int flags = SYNCH_FLAGS_NONE; 965 1020 if (!list_empty(&timeout_list)) { 966 1021 awaiter_t *waiter = list_get_instance( … … 973 1028 futex_up(&async_futex); 974 1029 handle_expired_timeouts(); 975 continue; 976 } else 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 { 977 1044 timeout = tv_sub(&waiter->to_event.expires, &tv); 978 } else 1045 futex_up(&async_futex); 1046 } 1047 } else { 1048 futex_up(&async_futex); 979 1049 timeout = SYNCH_NO_TIMEOUT; 980 981 futex_up(&async_futex); 1050 } 982 1051 983 1052 atomic_inc(&threads_in_ipc_wait); 984 1053 985 1054 ipc_call_t call; 986 ipc_callid_t callid = ipc_wait_cycle(&call, timeout, 987 SYNCH_FLAGS_NONE); 1055 ipc_callid_t callid = ipc_wait_cycle(&call, timeout, flags); 988 1056 989 1057 atomic_dec(&threads_in_ipc_wait); … … 1100 1168 1101 1169 msg->done = true; 1102 if (!msg->wdata.active) { 1170 1171 if (msg->forget) { 1172 assert(msg->wdata.active); 1173 amsg_destroy(msg); 1174 } else if (!msg->wdata.active) { 1103 1175 msg->wdata.active = true; 1104 1176 fibril_add_ready(msg->wdata.fid); 1105 1177 } 1106 1178 1107 1179 futex_up(&async_futex); 1108 1180 } … … 1131 1203 return 0; 1132 1204 1133 amsg_t *msg = malloc(sizeof(amsg_t));1205 amsg_t *msg = amsg_create(); 1134 1206 if (msg == NULL) 1135 1207 return 0; 1136 1208 1137 msg->done = false;1138 1209 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 means1145 */1146 1210 msg->wdata.active = true; 1147 1211 … … 1177 1241 return 0; 1178 1242 1179 amsg_t *msg = malloc(sizeof(amsg_t)); 1180 1243 amsg_t *msg = amsg_create(); 1181 1244 if (msg == NULL) 1182 1245 return 0; 1183 1246 1184 msg->done = false;1185 1247 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 means1192 */1193 1248 msg->wdata.active = true; 1194 1249 … … 1213 1268 1214 1269 futex_down(&async_futex); 1270 1271 assert(!msg->forget); 1272 assert(!msg->destroyed); 1273 1215 1274 if (msg->done) { 1216 1275 futex_up(&async_futex); … … 1231 1290 *retval = msg->retval; 1232 1291 1233 free(msg);1292 amsg_destroy(msg); 1234 1293 } 1235 1294 1236 1295 /** 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(). 1237 1300 * 1238 1301 * @param amsgid Hash of the message to wait for. … … 1249 1312 1250 1313 amsg_t *msg = (amsg_t *) amsgid; 1251 1252 /* TODO: Let it go through the event read at least once */ 1253 if (timeout < 0) 1254 return ETIMEOUT; 1255 1314 1256 1315 futex_down(&async_futex); 1316 1317 assert(!msg->forget); 1318 assert(!msg->destroyed); 1319 1257 1320 if (msg->done) { 1258 1321 futex_up(&async_futex); … … 1260 1323 } 1261 1324 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 1262 1332 gettimeofday(&msg->wdata.to_event.expires, NULL); 1263 1333 tv_add(&msg->wdata.to_event.expires, timeout); 1264 1334 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 */ 1265 1352 msg->wdata.fid = fibril_get_id(); 1266 1353 msg->wdata.active = false; … … 1279 1366 *retval = msg->retval; 1280 1367 1281 free(msg);1368 amsg_destroy(msg); 1282 1369 1283 1370 return 0; 1284 1371 } 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 } 1285 1396 1286 1397 /** Wait for specified time. … … 1293 1404 void async_usleep(suseconds_t timeout) 1294 1405 { 1295 amsg_t *msg = malloc(sizeof(amsg_t)); 1296 1406 amsg_t *msg = amsg_create(); 1297 1407 if (!msg) 1298 1408 return; 1299 1409 1300 1410 msg->wdata.fid = fibril_get_id(); 1301 msg->wdata.active = false;1302 1411 1303 1412 gettimeofday(&msg->wdata.to_event.expires, NULL); … … 1313 1422 /* Futex is up automatically after fibril_switch() */ 1314 1423 1315 free(msg);1424 amsg_destroy(msg); 1316 1425 } 1317 1426 … … 1559 1668 } 1560 1669 1561 /** Wrapper for making IPC_M_C ONNECT_MEcalls using the async framework.1562 * 1563 * Ask throughfor a cloned connection to some service.1670 /** Wrapper for making IPC_M_CLONE_ESTABLISH calls using the async framework. 1671 * 1672 * Ask for a cloned connection to some service. 1564 1673 * 1565 1674 * @param mgmt Exchange management style. … … 1569 1678 * 1570 1679 */ 1571 async_sess_t *async_c onnect_me(exch_mgmt_t mgmt, async_exch_t *exch)1680 async_sess_t *async_clone_establish(exch_mgmt_t mgmt, async_exch_t *exch) 1572 1681 { 1573 1682 if (exch == NULL) { … … 1584 1693 ipc_call_t result; 1585 1694 1586 amsg_t *msg = malloc(sizeof(amsg_t));1587 if ( msg == NULL) {1695 amsg_t *msg = amsg_create(); 1696 if (!msg) { 1588 1697 free(sess); 1589 1698 errno = ENOMEM; … … 1591 1700 } 1592 1701 1593 msg->done = false;1594 1702 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 means1601 */1602 1703 msg->wdata.active = true; 1603 1704 1604 ipc_call_async_0(exch->phone, IPC_M_C ONNECT_ME, msg,1705 ipc_call_async_0(exch->phone, IPC_M_CLONE_ESTABLISH, msg, 1605 1706 reply_received, true); 1606 1707 … … 1643 1744 ipc_call_t result; 1644 1745 1645 amsg_t *msg = malloc(sizeof(amsg_t));1646 if ( msg == NULL)1746 amsg_t *msg = amsg_create(); 1747 if (!msg) 1647 1748 return ENOENT; 1648 1749 1649 msg->done = false;1650 1750 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 means1657 */1658 1751 msg->wdata.active = true; 1659 1752 … … 2251 2344 IPC_FF_ROUTE_FROM_ME); 2252 2345 if (retval != EOK) { 2253 async_ wait_for(msg, NULL);2346 async_forget(msg); 2254 2347 ipc_answer_0(callid, retval); 2255 2348 return retval; … … 2445 2538 IPC_FF_ROUTE_FROM_ME); 2446 2539 if (retval != EOK) { 2447 async_ wait_for(msg, NULL);2540 async_forget(msg); 2448 2541 ipc_answer_0(callid, retval); 2449 2542 return retval; -
uspace/lib/c/generic/device/nic.c
r3293a94 r7719958 65 65 66 66 if (retval != EOK) { 67 async_ wait_for(req, NULL);67 async_forget(req); 68 68 return retval; 69 69 } … … 94 94 rc = async_connect_to_me(exch, 0, 0, 0, cfun, carg); 95 95 if (rc != EOK) { 96 async_ wait_for(req, NULL);96 async_forget(req); 97 97 return rc; 98 98 } -
uspace/lib/c/generic/devman.c
r3293a94 r7719958 188 188 189 189 if (retval != EOK) { 190 async_ wait_for(req, NULL);190 async_forget(req); 191 191 return retval; 192 192 } … … 226 226 if (retval != EOK) { 227 227 devman_exchange_end(exch); 228 async_ wait_for(req, NULL);228 async_forget(req); 229 229 return retval; 230 230 } … … 242 242 if (retval != EOK) { 243 243 devman_exchange_end(exch); 244 async_ wait_for(req2, NULL);245 async_ wait_for(req, NULL);244 async_forget(req2); 245 async_forget(req); 246 246 return retval; 247 247 } … … 250 250 if (retval != EOK) { 251 251 devman_exchange_end(exch); 252 async_ wait_for(req, NULL);252 async_forget(req); 253 253 return retval; 254 254 } … … 283 283 284 284 if (retval != EOK) { 285 async_ wait_for(req, NULL);285 async_forget(req); 286 286 return retval; 287 287 } … … 386 386 387 387 if (retval != EOK) { 388 async_ wait_for(req, NULL);388 async_forget(req); 389 389 return retval; 390 390 } … … 423 423 424 424 if (dretval != EOK) { 425 async_ wait_for(req, NULL);425 async_forget(req); 426 426 return dretval; 427 427 } … … 488 488 489 489 if (rc != EOK) { 490 async_ wait_for(req, NULL);490 async_forget(req); 491 491 return rc; 492 492 } -
uspace/lib/c/generic/fibril_synch.c
r3293a94 r7719958 112 112 awaiter_t wdata; 113 113 114 awaiter_initialize(&wdata); 114 115 wdata.fid = fibril_get_id(); 115 wdata.active = false;116 116 wdata.wu_event.inlist = true; 117 link_initialize(&wdata.wu_event.link);118 117 list_append(&wdata.wu_event.link, &fm->waiters); 119 118 check_for_deadlock(&fm->oi); … … 205 204 awaiter_t wdata; 206 205 206 awaiter_initialize(&wdata); 207 207 wdata.fid = (fid_t) f; 208 wdata.active = false;209 208 wdata.wu_event.inlist = true; 210 link_initialize(&wdata.wu_event.link);211 209 f->flags &= ~FIBRIL_WRITER; 212 210 list_append(&wdata.wu_event.link, &frw->waiters); … … 233 231 awaiter_t wdata; 234 232 233 awaiter_initialize(&wdata); 235 234 wdata.fid = (fid_t) f; 236 wdata.active = false;237 235 wdata.wu_event.inlist = true; 238 link_initialize(&wdata.wu_event.link);239 236 f->flags |= FIBRIL_WRITER; 240 237 list_append(&wdata.wu_event.link, &frw->waiters); … … 375 372 return ETIMEOUT; 376 373 374 awaiter_initialize(&wdata); 377 375 wdata.fid = fibril_get_id(); 378 wdata.active = false;379 380 376 wdata.to_event.inlist = timeout > 0; 381 wdata.to_event.occurred = false;382 link_initialize(&wdata.to_event.link);383 384 377 wdata.wu_event.inlist = true; 385 link_initialize(&wdata.wu_event.link);386 378 387 379 futex_down(&async_futex); -
uspace/lib/c/generic/io/printf_core.c
r3293a94 r7719958 283 283 /* Print leading spaces. */ 284 284 size_t strw = str_length(str); 285 if ( precision == 0)285 if ((precision == 0) || (precision > strw)) 286 286 precision = strw; 287 287 … … 331 331 /* Print leading spaces. */ 332 332 size_t strw = wstr_length(str); 333 if ( precision == 0)333 if ((precision == 0) || (precision > strw)) 334 334 precision = strw; 335 335 -
uspace/lib/c/generic/ipc.c
r3293a94 r7719958 647 647 * 648 648 */ 649 int ipc_c onnect_me(int phoneid)649 int ipc_clone_establish(int phoneid) 650 650 { 651 651 sysarg_t newphid; 652 int res = ipc_call_sync_0_5(phoneid, IPC_M_C ONNECT_ME, NULL, NULL,653 NULL, NULL, &newphid);652 int res = ipc_call_sync_0_5(phoneid, IPC_M_CLONE_ESTABLISH, NULL, 653 NULL, NULL, NULL, &newphid); 654 654 if (res) 655 655 return res; -
uspace/lib/c/generic/loader.c
r3293a94 r7719958 101 101 102 102 if (rc != EOK) { 103 async_ wait_for(req, NULL);103 async_forget(req); 104 104 return (int) rc; 105 105 } … … 139 139 140 140 if (rc != EOK) { 141 async_ wait_for(req, NULL);141 async_forget(req); 142 142 return (int) rc; 143 143 } … … 177 177 178 178 if (rc != EOK) { 179 async_ wait_for(req, NULL);179 async_forget(req); 180 180 return (int) rc; 181 181 } … … 236 236 237 237 if (rc != EOK) { 238 async_ wait_for(req, NULL);238 async_forget(req); 239 239 return (int) rc; 240 240 } … … 281 281 282 282 if (rc != EOK) { 283 async_ wait_for(req, NULL);283 async_forget(req); 284 284 return (int) rc; 285 285 } -
uspace/lib/c/generic/loc.c
r3293a94 r7719958 246 246 247 247 if (retval != EOK) { 248 async_ wait_for(req, NULL);248 async_forget(req); 249 249 return retval; 250 250 } … … 285 285 286 286 if (retval != EOK) { 287 async_ wait_for(req, NULL);287 async_forget(req); 288 288 return retval; 289 289 } … … 352 352 353 353 if (retval != EOK) { 354 async_ wait_for(req, NULL);354 async_forget(req); 355 355 return retval; 356 356 } … … 401 401 402 402 if (dretval != EOK) { 403 async_ wait_for(req, NULL);403 async_forget(req); 404 404 return dretval; 405 405 } … … 471 471 472 472 if (retval != EOK) { 473 async_ wait_for(req, NULL);473 async_forget(req); 474 474 return retval; 475 475 } … … 520 520 521 521 if (retval != EOK) { 522 async_ wait_for(req, NULL);522 async_forget(req); 523 523 return retval; 524 524 } … … 683 683 684 684 if (rc != EOK) { 685 async_ wait_for(req, NULL);685 async_forget(req); 686 686 free(devs); 687 687 return 0; … … 732 732 733 733 if (rc != EOK) { 734 async_ wait_for(req, NULL);734 async_forget(req); 735 735 free(devs); 736 736 return 0; … … 760 760 761 761 if (rc != EOK) { 762 async_ wait_for(req, NULL);762 async_forget(req); 763 763 return rc; 764 764 } -
uspace/lib/c/generic/net/modules.c
r3293a94 r7719958 93 93 } 94 94 95 /** Connect to the needed module. 96 * 97 * @param[in] need Needed module service. 98 * 99 * @return Session to the needed service. 100 * @return NULL if the connection timeouted. 101 * 102 */ 103 static async_sess_t *connect_to_service(services_t need) 104 { 105 return service_connect_blocking(EXCHANGE_SERIALIZE, need, 0, 0); 106 } 107 95 108 /** Create bidirectional connection with the needed module service and register 96 109 * the message receiver. … … 129 142 } 130 143 131 /** Connect to the needed module.132 *133 * @param[in] need Needed module service.134 *135 * @return Session to the needed service.136 * @return NULL if the connection timeouted.137 *138 */139 async_sess_t *connect_to_service(services_t need)140 {141 return service_connect_blocking(EXCHANGE_SERIALIZE, need, 0, 0);142 }143 144 /** Reply the data to the other party.145 *146 * @param[in] data The data buffer to be sent.147 * @param[in] data_length The buffer length.148 *149 * @return EOK on success.150 * @return EINVAL if the client does not expect the data.151 * @return EOVERFLOW if the client does not expect all the data.152 * Only partial data are transfered.153 * @return Other error codes as defined for the154 * async_data_read_finalize() function.155 *156 */157 int data_reply(void *data, size_t data_length)158 {159 size_t length;160 ipc_callid_t callid;161 162 /* Fetch the request */163 if (!async_data_read_receive(&callid, &length))164 return EINVAL;165 166 /* Check the requested data size */167 if (length < data_length) {168 async_data_read_finalize(callid, data, length);169 return EOVERFLOW;170 }171 172 /* Send the data */173 return async_data_read_finalize(callid, data, data_length);174 }175 176 144 /** Refresh answer structure and argument count. 177 145 * -
uspace/lib/c/generic/private/async.h
r3293a94 r7719958 81 81 } awaiter_t; 82 82 83 extern void awaiter_initialize(awaiter_t *); 84 83 85 extern void __async_init(void); 84 86 extern void async_insert_timeout(awaiter_t *);
Note:
See TracChangeset
for help on using the changeset viewer.