Changeset 474afc9 in mainline for uspace/lib/c/generic
- Timestamp:
- 2011-02-04T22:40:13Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4d73d71
- Parents:
- 89acf204 (diff), e29e09cf (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
- 21 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/as.c
r89acf204 r474afc9 41 41 #include <bitops.h> 42 42 #include <malloc.h> 43 44 /** Last position allocated by as_get_mappable_page */ 45 static uintptr_t last_allocated = 0; 43 #include "private/libc.h" 46 44 47 45 /** Create address space area. … … 104 102 } 105 103 106 /** Return pointer to some unmapped area, where fits new as_area104 /** Return pointer to unmapped address space area 107 105 * 108 106 * @param size Requested size of the allocation. 109 107 * 110 * @return pointer to the beginning108 * @return Pointer to the beginning of unmapped address space area. 111 109 * 112 110 */ 113 111 void *as_get_mappable_page(size_t size) 114 112 { 115 if (size == 0) 116 return NULL; 117 118 size_t sz = 1 << (fnzb(size - 1) + 1); 119 if (last_allocated == 0) 120 last_allocated = get_max_heap_addr(); 121 122 /* 123 * Make sure we allocate from naturally aligned address. 124 */ 125 uintptr_t res = ALIGN_UP(last_allocated, sz); 126 last_allocated = res + ALIGN_UP(size, PAGE_SIZE); 127 128 return ((void *) res); 113 return (void *) __SYSCALL2(SYS_AS_GET_UNMAPPED_AREA, 114 (sysarg_t) __entry, (sysarg_t) size); 129 115 } 130 116 -
uspace/lib/c/generic/async.c
r89acf204 r474afc9 43 43 * framework will automatically take care of most synchronization problems. 44 44 * 45 * Default semantics:46 * - async_send_*(): Send asynchronously. If the kernel refuses to send47 * more messages, [ try to get responses from kernel, if48 * nothing found, might try synchronous ]49 *50 45 * Example of use (pseudo C): 51 46 * … … 58 53 * int fibril1(void *arg) 59 54 * { 60 * conn = ipc_connect_me_to();55 * conn = async_connect_me_to(); 61 56 * c1 = async_send(conn); 62 57 * c2 = async_send(conn); … … 77 72 * { 78 73 * if (want_refuse) { 79 * ipc_answer_0(icallid, ELIMIT);74 * async_answer_0(icallid, ELIMIT); 80 75 * return; 81 76 * } 82 * ipc_answer_0(icallid, EOK);77 * async_answer_0(icallid, EOK); 83 78 * 84 79 * callid = async_get_call(&call); 85 80 * somehow_handle_the_call(callid, call); 86 * ipc_answer_2(callid, 1, 2, 3);81 * async_answer_2(callid, 1, 2, 3); 87 82 * 88 83 * callid = async_get_call(&call); … … 92 87 */ 93 88 89 #define LIBC_ASYNC_C_ 90 #include <ipc/ipc.h> 91 #include <async.h> 92 #undef LIBC_ASYNC_C_ 93 94 94 #include <futex.h> 95 #include <async.h>96 #include <async_priv.h>97 95 #include <fibril.h> 98 96 #include <stdio.h> 99 97 #include <adt/hash_table.h> 100 98 #include <adt/list.h> 101 #include <ipc/ipc.h>102 99 #include <assert.h> 103 100 #include <errno.h> … … 105 102 #include <arch/barrier.h> 106 103 #include <bool.h> 104 #include "private/async.h" 107 105 108 106 atomic_t async_futex = FUTEX_INITIALIZER; … … 124 122 125 123 /** 126 * Structures of this type are used to group information about a call and a127 * message queue link.124 * Structures of this type are used to group information about 125 * a call and about a message queue link. 128 126 */ 129 127 typedef struct { … … 153 151 /** Link to the client tracking structure. */ 154 152 client_t *client; 155 153 156 154 /** Messages that should be delivered to this fibril. */ 157 155 link_t msg_queue; … … 170 168 171 169 /** Identifier of the incoming connection handled by the current fibril. */ 172 fibril_local connection_t *FIBRIL_connection;170 static fibril_local connection_t *FIBRIL_connection; 173 171 174 172 static void *default_client_data_constructor(void) … … 199 197 { 200 198 assert(FIBRIL_connection); 201 202 199 return FIBRIL_connection->client->data; 203 200 } 204 201 205 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); 206 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call); 202 /** Default fibril function that gets called to handle new connection. 203 * 204 * This function is defined as a weak symbol - to be redefined in user code. 205 * 206 * @param callid Hash of the incoming call. 207 * @param call Data of the incoming call. 208 * 209 */ 210 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call) 211 { 212 ipc_answer_0(callid, ENOENT); 213 } 207 214 208 215 /** … … 210 217 */ 211 218 static async_client_conn_t client_connection = default_client_connection; 219 220 /** Default fibril function that gets called to handle interrupt notifications. 221 * 222 * This function is defined as a weak symbol - to be redefined in user code. 223 * 224 * @param callid Hash of the incoming call. 225 * @param call Data of the incoming call. 226 * 227 */ 228 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call) 229 { 230 } 212 231 213 232 /** … … 221 240 static LIST_INITIALIZE(timeout_list); 222 241 223 #define CLIENT_HASH_TABLE_BUCKETS 224 #define CONN_HASH_TABLE_BUCKETS 225 226 static hash_index_t client_hash(unsigned long *key)242 #define CLIENT_HASH_TABLE_BUCKETS 32 243 #define CONN_HASH_TABLE_BUCKETS 32 244 245 static hash_index_t client_hash(unsigned long key[]) 227 246 { 228 247 assert(key); 229 return ((( *key) >> 4) % CLIENT_HASH_TABLE_BUCKETS);248 return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS); 230 249 } 231 250 232 251 static int client_compare(unsigned long key[], hash_count_t keys, link_t *item) 233 252 { 234 client_t *cl = hash_table_get_instance(item, client_t, link);235 return (key[0] == cl ->in_task_hash);253 client_t *client = hash_table_get_instance(item, client_t, link); 254 return (key[0] == client->in_task_hash); 236 255 } 237 256 … … 254 273 * 255 274 */ 256 static hash_index_t conn_hash(unsigned long *key)275 static hash_index_t conn_hash(unsigned long key[]) 257 276 { 258 277 assert(key); 259 return ((( *key) >> 4) % CONN_HASH_TABLE_BUCKETS);278 return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS); 260 279 } 261 280 … … 271 290 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) 272 291 { 273 connection_t *hs = hash_table_get_instance(item, connection_t, link); 274 return (key[0] == hs->in_phone_hash); 275 } 276 277 /** Connection hash table removal callback function. 278 * 279 * This function is called whenever a connection is removed from the connection 280 * hash table. 281 * 282 * @param item Connection hash table item being removed. 283 * 284 */ 292 connection_t *conn = hash_table_get_instance(item, connection_t, link); 293 return (key[0] == conn->in_phone_hash); 294 } 295 285 296 static void conn_remove(link_t *item) 286 297 { 287 free(hash_table_get_instance(item, connection_t, link)); 288 } 289 298 } 290 299 291 300 /** Operations for the connection hash table. */ … … 308 317 link_t *tmp = timeout_list.next; 309 318 while (tmp != &timeout_list) { 310 awaiter_t *cur ;311 312 cur = list_get_instance(tmp, awaiter_t, to_event.link);319 awaiter_t *cur 320 = list_get_instance(tmp, awaiter_t, to_event.link); 321 313 322 if (tv_gteq(&cur->to_event.expires, &wd->to_event.expires)) 314 323 break; 324 315 325 tmp = tmp->next; 316 326 } … … 329 339 * 330 340 * @return False if the call doesn't match any connection. 331 * 341 * @return True if the call was passed to the respective connection fibril. 332 342 * 333 343 */ … … 420 430 421 431 fid_t fid = fibril_create(notification_fibril, msg); 432 if (fid == 0) { 433 free(msg); 434 futex_up(&async_futex); 435 return false; 436 } 437 422 438 fibril_add_ready(fid); 423 439 … … 466 482 * the first IPC_M_PHONE_HUNGUP call and continues to 467 483 * call async_get_call_timeout(). Repeat 468 * IPC_M_PHONE_HUNGUP until the caller notices. 484 * IPC_M_PHONE_HUNGUP until the caller notices. 469 485 */ 470 486 memset(call, 0, sizeof(ipc_call_t)); … … 473 489 return conn->close_callid; 474 490 } 475 491 476 492 if (usecs) 477 493 async_insert_timeout(&conn->wdata); … … 511 527 } 512 528 513 /** Default fibril function that gets called to handle new connection.514 *515 * This function is defined as a weak symbol - to be redefined in user code.516 *517 * @param callid Hash of the incoming call.518 * @param call Data of the incoming call.519 *520 */521 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)522 {523 ipc_answer_0(callid, ENOENT);524 }525 526 /** Default fibril function that gets called to handle interrupt notifications.527 *528 * This function is defined as a weak symbol - to be redefined in user code.529 *530 * @param callid Hash of the incoming call.531 * @param call Data of the incoming call.532 *533 */534 static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)535 {536 }537 538 529 /** Wrapper for client connection fibril. 539 530 * … … 548 539 static int connection_fibril(void *arg) 549 540 { 550 unsigned long key;551 client_t *cl;552 link_t *lnk;553 bool destroy = false;554 555 541 /* 556 542 * Setup fibril-local connection pointer. 557 543 */ 558 544 FIBRIL_connection = (connection_t *) arg; 559 545 546 futex_down(&async_futex); 547 560 548 /* 561 549 * Add our reference for the current connection in the client task … … 563 551 * hash in a new tracking structure. 564 552 */ 565 futex_down(&async_futex); 566 key = FIBRIL_connection->in_task_hash; 567 lnk = hash_table_find(&client_hash_table, &key); 553 554 unsigned long key = FIBRIL_connection->in_task_hash; 555 link_t *lnk = hash_table_find(&client_hash_table, &key); 556 557 client_t *client; 558 568 559 if (lnk) { 569 cl = hash_table_get_instance(lnk, client_t, link);570 cl ->refcnt++;560 client = hash_table_get_instance(lnk, client_t, link); 561 client->refcnt++; 571 562 } else { 572 cl = malloc(sizeof(client_t));573 if (!cl ) {563 client = malloc(sizeof(client_t)); 564 if (!client) { 574 565 ipc_answer_0(FIBRIL_connection->callid, ENOMEM); 575 566 futex_up(&async_futex); 576 567 return 0; 577 568 } 578 cl->in_task_hash = FIBRIL_connection->in_task_hash; 569 570 client->in_task_hash = FIBRIL_connection->in_task_hash; 571 579 572 async_serialize_start(); 580 cl ->data = async_client_data_create();573 client->data = async_client_data_create(); 581 574 async_serialize_end(); 582 cl->refcnt = 1; 583 hash_table_insert(&client_hash_table, &key, &cl->link); 584 } 575 576 client->refcnt = 1; 577 hash_table_insert(&client_hash_table, &key, &client->link); 578 } 579 585 580 futex_up(&async_futex); 586 587 FIBRIL_connection->client = cl ;588 581 582 FIBRIL_connection->client = client; 583 589 584 /* 590 585 * Call the connection handler function. … … 596 591 * Remove the reference for this client task connection. 597 592 */ 593 bool destroy; 594 598 595 futex_down(&async_futex); 599 if (--cl->refcnt == 0) { 596 597 if (--client->refcnt == 0) { 600 598 hash_table_remove(&client_hash_table, &key, 1); 601 599 destroy = true; 602 } 600 } else 601 destroy = false; 602 603 603 futex_up(&async_futex); 604 604 605 605 if (destroy) { 606 if (cl->data) 607 async_client_data_destroy(cl->data); 608 free(cl); 609 } 610 606 if (client->data) 607 async_client_data_destroy(client->data); 608 609 free(client); 610 } 611 611 612 /* 612 613 * Remove myself from the connection hash table. … … 621 622 */ 622 623 while (!list_empty(&FIBRIL_connection->msg_queue)) { 623 msg_t *msg ;624 625 msg = list_get_instance(FIBRIL_connection->msg_queue.next,626 msg_t, link);624 msg_t *msg = 625 list_get_instance(FIBRIL_connection->msg_queue.next, msg_t, 626 link); 627 627 628 list_remove(&msg->link); 628 629 ipc_answer_0(msg->callid, EHANGUP); … … 637 638 ipc_answer_0(FIBRIL_connection->close_callid, EOK); 638 639 640 free(FIBRIL_connection); 639 641 return 0; 640 642 } … … 667 669 if (callid) 668 670 ipc_answer_0(callid, ENOMEM); 671 669 672 return (uintptr_t) NULL; 670 673 } … … 684 687 conn->wdata.fid = fibril_create(connection_fibril, conn); 685 688 686 if ( !conn->wdata.fid) {689 if (conn->wdata.fid == 0) { 687 690 free(conn); 691 688 692 if (callid) 689 693 ipc_answer_0(callid, ENOMEM); 694 690 695 return (uintptr_t) NULL; 691 696 } … … 714 719 static void handle_call(ipc_callid_t callid, ipc_call_t *call) 715 720 { 716 /* Unrouted call - do some default behaviour*/721 /* Unrouted call - take some default action */ 717 722 if ((callid & IPC_CALLID_NOTIFICATION)) { 718 723 process_notification(callid, call); 719 goto out;724 return; 720 725 } 721 726 … … 723 728 case IPC_M_CONNECT_ME: 724 729 case IPC_M_CONNECT_ME_TO: 725 /* Open new connection with fibril etc. */730 /* Open new connection with fibril, etc. */ 726 731 async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call), 727 732 callid, call, client_connection); 728 goto out;733 return; 729 734 } 730 735 731 736 /* Try to route the call through the connection hash table */ 732 737 if (route_call(callid, call)) 733 goto out;738 return; 734 739 735 740 /* Unknown call from unknown phone - hang it up */ 736 741 ipc_answer_0(callid, EHANGUP); 737 return;738 739 out:740 ;741 742 } 742 743 … … 751 752 link_t *cur = timeout_list.next; 752 753 while (cur != &timeout_list) { 753 awaiter_t *waiter ;754 755 waiter = list_get_instance(cur, awaiter_t, to_event.link);754 awaiter_t *waiter = 755 list_get_instance(cur, awaiter_t, to_event.link); 756 756 757 if (tv_gt(&waiter->to_event.expires, &tv)) 757 758 break; 758 759 759 760 cur = cur->next; 760 761 761 762 list_remove(&waiter->to_event.link); 762 763 waiter->to_event.inlist = false; … … 785 786 while (true) { 786 787 if (fibril_switch(FIBRIL_FROM_MANAGER)) { 787 futex_up(&async_futex); 788 futex_up(&async_futex); 788 789 /* 789 790 * async_futex is always held when entering a manager … … 808 809 continue; 809 810 } else 810 timeout = tv_sub(&waiter->to_event.expires, 811 &tv); 811 timeout = tv_sub(&waiter->to_event.expires, &tv); 812 812 } else 813 813 timeout = SYNCH_NO_TIMEOUT; 814 814 815 815 futex_up(&async_futex); 816 816 817 817 atomic_inc(&threads_in_ipc_wait); 818 818 … … 822 822 823 823 atomic_dec(&threads_in_ipc_wait); 824 824 825 825 if (!callid) { 826 826 handle_expired_timeouts(); … … 861 861 { 862 862 fid_t fid = fibril_create(async_manager_fibril, NULL); 863 fibril_add_manager(fid); 863 if (fid != 0) 864 fibril_add_manager(fid); 864 865 } 865 866 … … 872 873 /** Initialize the async framework. 873 874 * 874 * @return Zero on success or an error code. 875 */ 876 int __async_init(void) 875 */ 876 void __async_init(void) 877 877 { 878 878 if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1, 879 &client_hash_table_ops) || !hash_table_create(&conn_hash_table, 880 CONN_HASH_TABLE_BUCKETS, 1, &conn_hash_table_ops)) { 881 return ENOMEM; 882 } 883 884 _async_sess_init(); 885 886 return 0; 879 &client_hash_table_ops)) 880 abort(); 881 882 if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1, 883 &conn_hash_table_ops)) 884 abort(); 887 885 } 888 886 … … 897 895 * @param retval Value returned in the answer. 898 896 * @param data Call data of the answer. 897 * 899 898 */ 900 899 static void reply_received(void *arg, int retval, ipc_call_t *data) … … 944 943 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr) 945 944 { 946 amsg_t *msg = malloc(sizeof( *msg));945 amsg_t *msg = malloc(sizeof(amsg_t)); 947 946 948 947 if (!msg) … … 953 952 954 953 msg->wdata.to_event.inlist = false; 955 /* We may sleep in the next method, but it will use its own mechanism */ 954 955 /* 956 * We may sleep in the next method, 957 * but it will use its own means 958 */ 956 959 msg->wdata.active = true; 957 960 … … 984 987 ipc_call_t *dataptr) 985 988 { 986 amsg_t *msg = malloc(sizeof( *msg));989 amsg_t *msg = malloc(sizeof(amsg_t)); 987 990 988 991 if (!msg) … … 993 996 994 997 msg->wdata.to_event.inlist = false; 995 /* We may sleep in next method, but it will use its own mechanism */ 998 999 /* 1000 * We may sleep in the next method, 1001 * but it will use its own means 1002 */ 996 1003 msg->wdata.active = true; 997 1004 … … 1092 1099 void async_usleep(suseconds_t timeout) 1093 1100 { 1094 amsg_t *msg = malloc(sizeof( *msg));1101 amsg_t *msg = malloc(sizeof(amsg_t)); 1095 1102 1096 1103 if (!msg) … … 1235 1242 } 1236 1243 1244 void async_msg_0(int phone, sysarg_t imethod) 1245 { 1246 ipc_call_async_0(phone, imethod, NULL, NULL, true); 1247 } 1248 1249 void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1) 1250 { 1251 ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true); 1252 } 1253 1254 void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2) 1255 { 1256 ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true); 1257 } 1258 1259 void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1260 sysarg_t arg3) 1261 { 1262 ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true); 1263 } 1264 1265 void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1266 sysarg_t arg3, sysarg_t arg4) 1267 { 1268 ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL, 1269 true); 1270 } 1271 1272 void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, 1273 sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 1274 { 1275 ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL, 1276 NULL, true); 1277 } 1278 1279 sysarg_t async_answer_0(ipc_callid_t callid, sysarg_t retval) 1280 { 1281 return ipc_answer_0(callid, retval); 1282 } 1283 1284 sysarg_t async_answer_1(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1) 1285 { 1286 return ipc_answer_1(callid, retval, arg1); 1287 } 1288 1289 sysarg_t async_answer_2(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1290 sysarg_t arg2) 1291 { 1292 return ipc_answer_2(callid, retval, arg1, arg2); 1293 } 1294 1295 sysarg_t async_answer_3(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1296 sysarg_t arg2, sysarg_t arg3) 1297 { 1298 return ipc_answer_3(callid, retval, arg1, arg2, arg3); 1299 } 1300 1301 sysarg_t async_answer_4(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1302 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4) 1303 { 1304 return ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4); 1305 } 1306 1307 sysarg_t async_answer_5(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, 1308 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5) 1309 { 1310 return ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5); 1311 } 1312 1313 int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod, 1314 sysarg_t arg1, sysarg_t arg2, unsigned int mode) 1315 { 1316 return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode); 1317 } 1318 1319 int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod, 1320 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 1321 unsigned int mode) 1322 { 1323 return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4, 1324 arg5, mode); 1325 } 1326 1327 /** Wrapper for making IPC_M_CONNECT_TO_ME calls using the async framework. 1328 * 1329 * Ask through phone for a new connection to some service. 1330 * 1331 * @param phone Phone handle used for contacting the other side. 1332 * @param arg1 User defined argument. 1333 * @param arg2 User defined argument. 1334 * @param arg3 User defined argument. 1335 * @param client_receiver Connection handing routine. 1336 * 1337 * @return New phone handle on success or a negative error code. 1338 * 1339 */ 1340 int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2, 1341 sysarg_t arg3, async_client_conn_t client_receiver) 1342 { 1343 sysarg_t task_hash; 1344 sysarg_t phone_hash; 1345 int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3, 1346 NULL, NULL, NULL, &task_hash, &phone_hash); 1347 if (rc != EOK) 1348 return rc; 1349 1350 if (client_receiver != NULL) 1351 async_new_connection(task_hash, phone_hash, 0, NULL, 1352 client_receiver); 1353 1354 return EOK; 1355 } 1356 1237 1357 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1238 * 1358 * 1239 1359 * Ask through phone for a new connection to some service. 1240 1360 * 1241 * @param phone idPhone handle used for contacting the other side.1242 * @param arg1 1243 * @param arg2 1244 * @param arg3 1245 * 1246 * @return 1247 * /1248 int 1249 async_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) 1250 { 1251 int rc; 1361 * @param phone Phone handle used for contacting the other side. 1362 * @param arg1 User defined argument. 1363 * @param arg2 User defined argument. 1364 * @param arg3 User defined argument. 1365 * 1366 * @return New phone handle on success or a negative error code. 1367 * 1368 */ 1369 int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2, 1370 sysarg_t arg3) 1371 { 1252 1372 sysarg_t newphid; 1253 1254 rc = async_req_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, NULL, 1255 NULL, NULL, NULL, &newphid); 1256 1257 if (rc != EOK) 1373 int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1374 NULL, NULL, NULL, NULL, &newphid); 1375 1376 if (rc != EOK) 1258 1377 return rc; 1259 1378 1260 1379 return newphid; 1261 1380 } 1262 1381 1263 1382 /** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework. 1264 * 1383 * 1265 1384 * Ask through phone for a new connection to some service and block until 1266 1385 * success. 1267 1386 * 1268 * @param phoneid 1269 * @param arg1 1270 * @param arg2 1271 * @param arg3 1272 * 1273 * @return 1274 * /1275 int 1276 async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,1387 * @param phoneid Phone handle used for contacting the other side. 1388 * @param arg1 User defined argument. 1389 * @param arg2 User defined argument. 1390 * @param arg3 User defined argument. 1391 * 1392 * @return New phone handle on success or a negative error code. 1393 * 1394 */ 1395 int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2, 1277 1396 sysarg_t arg3) 1278 1397 { 1279 int rc;1280 1398 sysarg_t newphid; 1281 1282 rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1399 int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 1283 1400 IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); 1284 1401 1285 if (rc != EOK) 1402 if (rc != EOK) 1286 1403 return rc; 1287 1404 1288 1405 return newphid; 1289 1406 } 1290 1407 1291 /** Wrapper for making IPC_M_SHARE_IN calls using the async framework. 1292 * 1293 * @param phoneid Phone that will be used to contact the receiving side. 1294 * @param dst Destination address space area base. 1295 * @param size Size of the destination address space area. 1296 * @param arg User defined argument. 1297 * @param flags Storage where the received flags will be stored. Can be 1298 * NULL. 1299 * 1300 * @return Zero on success or a negative error code from errno.h. 1408 /** Connect to a task specified by id. 1409 * 1410 */ 1411 int async_connect_kbox(task_id_t id) 1412 { 1413 return ipc_connect_kbox(id); 1414 } 1415 1416 /** Wrapper for ipc_hangup. 1417 * 1418 * @param phone Phone handle to hung up. 1419 * 1420 * @return Zero on success or a negative error code. 1421 * 1422 */ 1423 int async_hangup(int phone) 1424 { 1425 return ipc_hangup(phone); 1426 } 1427 1428 /** Interrupt one thread of this task from waiting for IPC. */ 1429 void async_poke(void) 1430 { 1431 ipc_poke(); 1432 } 1433 1434 /** Wrapper for IPC_M_SHARE_IN calls using the async framework. 1435 * 1436 * @param phoneid Phone that will be used to contact the receiving side. 1437 * @param dst Destination address space area base. 1438 * @param size Size of the destination address space area. 1439 * @param arg User defined argument. 1440 * @param flags Storage for the received flags. Can be NULL. 1441 * 1442 * @return Zero on success or a negative error code from errno.h. 1443 * 1301 1444 */ 1302 1445 int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg, 1303 int *flags) 1304 { 1305 int res; 1446 unsigned int *flags) 1447 { 1306 1448 sysarg_t tmp_flags; 1307 res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,1449 int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst, 1308 1450 (sysarg_t) size, arg, NULL, &tmp_flags); 1451 1309 1452 if (flags) 1310 *flags = tmp_flags; 1453 *flags = (unsigned int) tmp_flags; 1454 1311 1455 return res; 1312 1456 } … … 1314 1458 /** Wrapper for receiving the IPC_M_SHARE_IN calls using the async framework. 1315 1459 * 1316 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN calls 1317 * so that the user doesn't have to remember the meaning of each IPC argument. 1460 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN 1461 * calls so that the user doesn't have to remember the meaning of each IPC 1462 * argument. 1318 1463 * 1319 1464 * So far, this wrapper is to be used from within a connection fibril. 1320 1465 * 1321 * @param callid Storage where the hash of the IPC_M_SHARE_IN call will 1322 * be stored. 1323 * @param size Destination address space area size. 1324 * 1325 * @return Non-zero on success, zero on failure. 1326 */ 1327 int async_share_in_receive(ipc_callid_t *callid, size_t *size) 1328 { 1329 ipc_call_t data; 1330 1466 * @param callid Storage for the hash of the IPC_M_SHARE_IN call. 1467 * @param size Destination address space area size. 1468 * 1469 * @return True on success, false on failure. 1470 * 1471 */ 1472 bool async_share_in_receive(ipc_callid_t *callid, size_t *size) 1473 { 1331 1474 assert(callid); 1332 1475 assert(size); 1333 1476 1477 ipc_call_t data; 1334 1478 *callid = async_get_call(&data); 1479 1335 1480 if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_IN) 1336 return 0; 1481 return false; 1482 1337 1483 *size = (size_t) IPC_GET_ARG2(data); 1338 return 1;1484 return true; 1339 1485 } 1340 1486 1341 1487 /** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework. 1342 1488 * 1343 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls 1344 * so that the user doesn't have to remember the meaning of each IPC argument. 1345 * 1346 * @param callid Hash of the IPC_M_DATA_READ call to answer. 1347 * @param src Source address space base. 1348 * @param flags Flags to be used for sharing. Bits can be only cleared. 1349 * 1350 * @return Zero on success or a value from @ref errno.h on failure. 1351 */ 1352 int async_share_in_finalize(ipc_callid_t callid, void *src, int flags) 1489 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 1490 * calls so that the user doesn't have to remember the meaning of each IPC 1491 * argument. 1492 * 1493 * @param callid Hash of the IPC_M_DATA_READ call to answer. 1494 * @param src Source address space base. 1495 * @param flags Flags to be used for sharing. Bits can be only cleared. 1496 * 1497 * @return Zero on success or a value from @ref errno.h on failure. 1498 * 1499 */ 1500 int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags) 1353 1501 { 1354 1502 return ipc_share_in_finalize(callid, src, flags); 1355 1503 } 1356 1504 1357 /** Wrapper for making IPC_M_SHARE_OUT calls using the async framework. 1358 * 1359 * @param phoneid Phone that will be used to contact the receiving side. 1360 * @param src Source address space area base address. 1361 * @param flags Flags to be used for sharing. Bits can be only cleared. 1362 * 1363 * @return Zero on success or a negative error code from errno.h. 1364 */ 1365 int async_share_out_start(int phoneid, void *src, int flags) 1505 /** Wrapper for IPC_M_SHARE_OUT calls using the async framework. 1506 * 1507 * @param phoneid Phone that will be used to contact the receiving side. 1508 * @param src Source address space area base address. 1509 * @param flags Flags to be used for sharing. Bits can be only cleared. 1510 * 1511 * @return Zero on success or a negative error code from errno.h. 1512 * 1513 */ 1514 int async_share_out_start(int phoneid, void *src, unsigned int flags) 1366 1515 { 1367 1516 return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0, … … 1371 1520 /** Wrapper for receiving the IPC_M_SHARE_OUT calls using the async framework. 1372 1521 * 1373 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT calls 1374 * so that the user doesn't have to remember the meaning of each IPC argument. 1522 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT 1523 * calls so that the user doesn't have to remember the meaning of each IPC 1524 * argument. 1375 1525 * 1376 1526 * So far, this wrapper is to be used from within a connection fibril. 1377 1527 * 1378 * @param callid Storage where the hash of the IPC_M_SHARE_OUT call will 1379 * be stored. 1380 * @param size Storage where the source address space area size will be 1381 * stored. 1382 * @param flags Storage where the sharing flags will be stored. 1383 * 1384 * @return Non-zero on success, zero on failure. 1385 */ 1386 int async_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags) 1387 { 1388 ipc_call_t data; 1389 1528 * @param callid Storage for the hash of the IPC_M_SHARE_OUT call. 1529 * @param size Storage for the source address space area size. 1530 * @param flags Storage for the sharing flags. 1531 * 1532 * @return True on success, false on failure. 1533 * 1534 */ 1535 bool async_share_out_receive(ipc_callid_t *callid, size_t *size, unsigned int *flags) 1536 { 1390 1537 assert(callid); 1391 1538 assert(size); 1392 1539 assert(flags); 1393 1540 1541 ipc_call_t data; 1394 1542 *callid = async_get_call(&data); 1543 1395 1544 if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_OUT) 1396 return 0; 1545 return false; 1546 1397 1547 *size = (size_t) IPC_GET_ARG2(data); 1398 *flags = ( int) IPC_GET_ARG3(data);1399 return 1;1548 *flags = (unsigned int) IPC_GET_ARG3(data); 1549 return true; 1400 1550 } 1401 1551 1402 1552 /** Wrapper for answering the IPC_M_SHARE_OUT calls using the async framework. 1403 1553 * 1404 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls 1405 * so that the user doesn't have to remember the meaning of each IPC argument. 1406 * 1407 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 1408 * @param dst Destination address space area base address. 1409 * 1410 * @return Zero on success or a value from @ref errno.h on failure. 1554 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT 1555 * calls so that the user doesn't have to remember the meaning of each IPC 1556 * argument. 1557 * 1558 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 1559 * @param dst Destination address space area base address. 1560 * 1561 * @return Zero on success or a value from @ref errno.h on failure. 1562 * 1411 1563 */ 1412 1564 int async_share_out_finalize(ipc_callid_t callid, void *dst) … … 1415 1567 } 1416 1568 1417 1418 /** Wrapper for making IPC_M_DATA_READ calls using the async framework. 1419 * 1420 * @param phoneid Phone that will be used to contact the receiving side.1421 * @param dst Address of the beginningof the destination buffer.1422 * @param size Size of the destination buffer.1423 * 1424 * @return Zero on success or a negative error code from errno.h.1569 /** Wrapper for IPC_M_DATA_READ calls using the async framework. 1570 * 1571 * @param phoneid Phone that will be used to contact the receiving side. 1572 * @param dst Address of the beginning of the destination buffer. 1573 * @param size Size of the destination buffer. 1574 * 1575 * @return Zero on success or a negative error code from errno.h. 1576 * 1425 1577 */ 1426 1578 int async_data_read_start(int phoneid, void *dst, size_t size) … … 1432 1584 /** Wrapper for receiving the IPC_M_DATA_READ calls using the async framework. 1433 1585 * 1434 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ calls 1435 * so that the user doesn't have to remember the meaning of each IPC argument. 1586 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ 1587 * calls so that the user doesn't have to remember the meaning of each IPC 1588 * argument. 1436 1589 * 1437 1590 * So far, this wrapper is to be used from within a connection fibril. 1438 1591 * 1439 * @param callid Storage where the hash of the IPC_M_DATA_READ call will 1440 * be stored. 1441 * @param size Storage where the maximum size will be stored. Can be 1442 * NULL. 1443 * 1444 * @return Non-zero on success, zero on failure. 1445 */ 1446 int async_data_read_receive(ipc_callid_t *callid, size_t *size) 1447 { 1592 * @param callid Storage for the hash of the IPC_M_DATA_READ. 1593 * @param size Storage for the maximum size. Can be NULL. 1594 * 1595 * @return True on success, false on failure. 1596 * 1597 */ 1598 bool async_data_read_receive(ipc_callid_t *callid, size_t *size) 1599 { 1600 assert(callid); 1601 1448 1602 ipc_call_t data; 1449 1450 assert(callid);1451 1452 1603 *callid = async_get_call(&data); 1604 1453 1605 if (IPC_GET_IMETHOD(data) != IPC_M_DATA_READ) 1454 return 0; 1606 return false; 1607 1455 1608 if (size) 1456 1609 *size = (size_t) IPC_GET_ARG2(data); 1457 return 1; 1610 1611 return true; 1458 1612 } 1459 1613 1460 1614 /** Wrapper for answering the IPC_M_DATA_READ calls using the async framework. 1461 1615 * 1462 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls 1463 * so that the user doesn't have to remember the meaning of each IPC argument. 1464 * 1465 * @param callid Hash of the IPC_M_DATA_READ call to answer. 1466 * @param src Source address for the IPC_M_DATA_READ call. 1467 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 1468 * the maximum size announced by the sender. 1469 * 1470 * @return Zero on success or a value from @ref errno.h on failure. 1616 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 1617 * calls so that the user doesn't have to remember the meaning of each IPC 1618 * argument. 1619 * 1620 * @param callid Hash of the IPC_M_DATA_READ call to answer. 1621 * @param src Source address for the IPC_M_DATA_READ call. 1622 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 1623 * the maximum size announced by the sender. 1624 * 1625 * @return Zero on success or a value from @ref errno.h on failure. 1626 * 1471 1627 */ 1472 1628 int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size) … … 1476 1632 1477 1633 /** Wrapper for forwarding any read request 1478 *1479 1634 * 1480 1635 */ … … 1509 1664 } 1510 1665 1511 /** Wrapper for makingIPC_M_DATA_WRITE calls using the async framework.1666 /** Wrapper for IPC_M_DATA_WRITE calls using the async framework. 1512 1667 * 1513 1668 * @param phoneid Phone that will be used to contact the receiving side. … … 1526 1681 /** Wrapper for receiving the IPC_M_DATA_WRITE calls using the async framework. 1527 1682 * 1528 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE calls 1529 * so that the user doesn't have to remember the meaning of each IPC argument. 1683 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE 1684 * calls so that the user doesn't have to remember the meaning of each IPC 1685 * argument. 1530 1686 * 1531 1687 * So far, this wrapper is to be used from within a connection fibril. 1532 1688 * 1533 * @param callid Storage where the hash of the IPC_M_DATA_WRITE call will1534 * be stored.1535 * @param size Storage where the suggested size will be stored. May be1536 * NULL1537 * 1538 * @return Non-zero on success, zero on failure.1539 * 1540 */ 1541 int async_data_write_receive(ipc_callid_t *callid, size_t *size) 1542 { 1689 * @param callid Storage for the hash of the IPC_M_DATA_WRITE. 1690 * @param size Storage for the suggested size. May be NULL. 1691 * 1692 * @return True on success, false on failure. 1693 * 1694 */ 1695 bool async_data_write_receive(ipc_callid_t *callid, size_t *size) 1696 { 1697 assert(callid); 1698 1543 1699 ipc_call_t data; 1544 1545 assert(callid);1546 1547 1700 *callid = async_get_call(&data); 1701 1548 1702 if (IPC_GET_IMETHOD(data) != IPC_M_DATA_WRITE) 1549 return 0;1703 return false; 1550 1704 1551 1705 if (size) 1552 1706 *size = (size_t) IPC_GET_ARG2(data); 1553 1707 1554 return 1;1708 return true; 1555 1709 } 1556 1710 1557 1711 /** Wrapper for answering the IPC_M_DATA_WRITE calls using the async framework. 1558 1712 * 1559 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls 1560 * so that the user doesn't have to remember the meaning of each IPC argument. 1713 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE 1714 * calls so that the user doesn't have to remember the meaning of each IPC 1715 * argument. 1561 1716 * 1562 1717 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. … … 1654 1809 * 1655 1810 */ 1656 void async_data_write_void( const int retval)1811 void async_data_write_void(sysarg_t retval) 1657 1812 { 1658 1813 ipc_callid_t callid; … … 1662 1817 1663 1818 /** Wrapper for forwarding any data that is about to be received 1664 *1665 1819 * 1666 1820 */ -
uspace/lib/c/generic/async_sess.c
r89acf204 r474afc9 99 99 100 100 #include <async_sess.h> 101 #include <ipc/ipc.h>102 101 #include <fibril_synch.h> 103 102 #include <adt/list.h> … … 106 105 #include <errno.h> 107 106 #include <assert.h> 107 #include "private/async_sess.h" 108 108 109 109 /** An inactive open connection. */ … … 138 138 * 139 139 * Needs to be called prior to any other interface in this file. 140 */ 141 void _async_sess_init(void) 140 * 141 */ 142 void __async_sess_init(void) 142 143 { 143 144 fibril_mutex_initialize(&async_sess_mutex); … … 200 201 list_remove(&conn->global_link); 201 202 202 ipc_hangup(conn->data_phone);203 async_hangup(conn->data_phone); 203 204 free(conn); 204 205 } … … 260 261 data_phone = conn->data_phone; 261 262 free(conn); 262 ipc_hangup(data_phone);263 async_hangup(data_phone); 263 264 goto retry; 264 265 } else { … … 292 293 * means that we simply hang up. 293 294 */ 294 ipc_hangup(data_phone);295 async_hangup(data_phone); 295 296 fibril_mutex_unlock(&async_sess_mutex); 296 297 return; -
uspace/lib/c/generic/clipboard.c
r89acf204 r474afc9 39 39 40 40 #include <clipboard.h> 41 #include <ipc/ns.h> 41 42 #include <ipc/services.h> 42 43 #include <ipc/clipboard.h> … … 54 55 { 55 56 while (clip_phone < 0) 56 clip_phone = ipc_connect_me_to_blocking(PHONE_NS,SERVICE_CLIPBOARD, 0, 0);57 clip_phone = service_connect_blocking(SERVICE_CLIPBOARD, 0, 0); 57 58 } 58 59 -
uspace/lib/c/generic/ddi.c
r89acf204 r474afc9 127 127 } 128 128 129 /** Register IRQ notification. 130 * 131 * @param inr IRQ number. 132 * @param devno Device number of the device generating inr. 133 * @param method Use this method for notifying me. 134 * @param ucode Top-half pseudocode handler. 135 * 136 * @return Value returned by the kernel. 137 * 138 */ 139 int register_irq(int inr, int devno, int method, irq_code_t *ucode) 140 { 141 return __SYSCALL4(SYS_REGISTER_IRQ, inr, devno, method, 142 (sysarg_t) ucode); 143 } 144 145 /** Unregister IRQ notification. 146 * 147 * @param inr IRQ number. 148 * @param devno Device number of the device generating inr. 149 * 150 * @return Value returned by the kernel. 151 * 152 */ 153 int unregister_irq(int inr, int devno) 154 { 155 return __SYSCALL2(SYS_UNREGISTER_IRQ, inr, devno); 156 } 157 129 158 /** @} 130 159 */ -
uspace/lib/c/generic/devman.c
r89acf204 r474afc9 28 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 29 */ 30 31 30 31 /** @addtogroup libc 32 32 * @{ 33 33 */ … … 37 37 #include <str.h> 38 38 #include <stdio.h> 39 #include <ipc/ipc.h>40 39 #include <ipc/services.h> 41 40 #include <ipc/devman.h> … … 116 115 async_set_client_connection(conn); 117 116 118 ipc_connect_to_me(phone, 0, 0, 0, NULL, NULL);117 async_connect_to_me(phone, 0, 0, 0, NULL); 119 118 async_wait_for(req, &retval); 120 119 … … 221 220 case DEVMAN_DRIVER: 222 221 if (devman_phone_driver >= 0) { 223 ipc_hangup(devman_phone_driver);222 async_hangup(devman_phone_driver); 224 223 devman_phone_driver = -1; 225 224 } … … 227 226 case DEVMAN_CLIENT: 228 227 if (devman_phone_client >= 0) { 229 ipc_hangup(devman_phone_client);228 async_hangup(devman_phone_client); 230 229 devman_phone_client = -1; 231 230 } -
uspace/lib/c/generic/devmap.c
r89acf204 r474afc9 29 29 30 30 #include <str.h> 31 #include <ipc/ipc.h>32 31 #include <ipc/services.h> 32 #include <ipc/ns.h> 33 33 #include <ipc/devmap.h> 34 34 #include <devmap.h> … … 50 50 51 51 if (flags & IPC_FLAG_BLOCKING) 52 devmap_phone_driver = ipc_connect_me_to_blocking(PHONE_NS,53 SERVICE_DEVMAP,DEVMAP_DRIVER, 0);52 devmap_phone_driver = service_connect_blocking(SERVICE_DEVMAP, 53 DEVMAP_DRIVER, 0); 54 54 else 55 devmap_phone_driver = ipc_connect_me_to(PHONE_NS,56 SERVICE_DEVMAP,DEVMAP_DRIVER, 0);55 devmap_phone_driver = service_connect(SERVICE_DEVMAP, 56 DEVMAP_DRIVER, 0); 57 57 58 58 return devmap_phone_driver; … … 62 62 63 63 if (flags & IPC_FLAG_BLOCKING) 64 devmap_phone_client = ipc_connect_me_to_blocking(PHONE_NS,65 SERVICE_DEVMAP,DEVMAP_CLIENT, 0);64 devmap_phone_client = service_connect_blocking(SERVICE_DEVMAP, 65 DEVMAP_CLIENT, 0); 66 66 else 67 devmap_phone_client = ipc_connect_me_to(PHONE_NS,68 SERVICE_DEVMAP,DEVMAP_CLIENT, 0);67 devmap_phone_client = service_connect(SERVICE_DEVMAP, 68 DEVMAP_CLIENT, 0); 69 69 70 70 return devmap_phone_client; … … 79 79 case DEVMAP_DRIVER: 80 80 if (devmap_phone_driver >= 0) { 81 ipc_hangup(devmap_phone_driver);81 async_hangup(devmap_phone_driver); 82 82 devmap_phone_driver = -1; 83 83 } … … 85 85 case DEVMAP_CLIENT: 86 86 if (devmap_phone_client >= 0) { 87 ipc_hangup(devmap_phone_client);87 async_hangup(devmap_phone_client); 88 88 devmap_phone_client = -1; 89 89 } … … 116 116 async_set_client_connection(conn); 117 117 118 ipc_connect_to_me(phone, 0, 0, 0, NULL, NULL);118 async_connect_to_me(phone, 0, 0, 0, NULL); 119 119 async_wait_for(req, &retval); 120 120 -
uspace/lib/c/generic/event.c
r89acf204 r474afc9 35 35 */ 36 36 /** @file 37 */ 37 */ 38 38 39 39 #include <libc.h> 40 40 #include <event.h> 41 41 #include <kernel/ipc/event_types.h> 42 #include <ipc/ipc.h>43 42 44 43 /** Subscribe for event notifications. -
uspace/lib/c/generic/fibril_synch.c
r89acf204 r474afc9 36 36 #include <fibril.h> 37 37 #include <async.h> 38 #include <async_priv.h>39 38 #include <adt/list.h> 40 39 #include <futex.h> … … 44 43 #include <stacktrace.h> 45 44 #include <stdlib.h> 45 #include "private/async.h" 46 46 47 47 static void optimize_execution_power(void) … … 55 55 */ 56 56 if (atomic_get(&threads_in_ipc_wait) > 0) 57 ipc_poke();57 async_poke(); 58 58 } 59 59 … … 105 105 106 106 if (fibril_get_sercount() != 0) 107 core();107 abort(); 108 108 109 109 futex_down(&async_futex); … … 198 198 199 199 if (fibril_get_sercount() != 0) 200 core();200 abort(); 201 201 202 202 futex_down(&async_futex); … … 226 226 227 227 if (fibril_get_sercount() != 0) 228 core();228 abort(); 229 229 230 230 futex_down(&async_futex); -
uspace/lib/c/generic/io/io.c
r89acf204 r474afc9 41 41 #include <bool.h> 42 42 #include <malloc.h> 43 #include <async.h> 43 44 #include <io/klog.h> 44 45 #include <vfs/vfs.h> 45 46 #include <ipc/devmap.h> 46 47 #include <adt/list.h> 48 #include "../private/io.h" 47 49 48 50 static void _ffillbuf(FILE *stream); … … 322 324 323 325 if (stream->phone >= 0) 324 ipc_hangup(stream->phone);326 async_hangup(stream->phone); 325 327 326 328 if (stream->fd >= 0) -
uspace/lib/c/generic/ipc.c
r89acf204 r474afc9 45 45 #include <errno.h> 46 46 #include <adt/list.h> 47 #include <stdio.h>48 #include <unistd.h>49 47 #include <futex.h> 50 #include <kernel/synch/synch.h>51 #include <async.h>52 48 #include <fibril.h> 53 #include <assert.h>54 49 55 50 /** 56 * Structures of this type are used for keeping track of sent asynchronous calls57 * and queing unsent calls.51 * Structures of this type are used for keeping track 52 * of sent asynchronous calls and queing unsent calls. 58 53 */ 59 54 typedef struct { 60 55 link_t list; 61 56 62 57 ipc_async_callback_t callback; 63 58 void *private; 59 64 60 union { 65 61 ipc_callid_t callid; … … 69 65 } msg; 70 66 } u; 71 fid_t fid; /**< Fibril waiting for sending this call. */ 67 68 /** Fibril waiting for sending this call. */ 69 fid_t fid; 72 70 } async_call_t; 73 71 … … 76 74 /** List of asynchronous calls that were not accepted by kernel. 77 75 * 78 * It is protected by async_futex, because if the call cannot be sent into the 79 * kernel, the async framework is used automatically. 76 * Protected by async_futex, because if the call is not accepted 77 * by the kernel, the async framework is used automatically. 78 * 80 79 */ 81 80 LIST_INITIALIZE(queued_calls); … … 83 82 static atomic_t ipc_futex = FUTEX_INITIALIZER; 84 83 85 /** Make a fast synchronous call.86 * 87 * Only three payload arguments can be passed using this function. However, this88 * function is faster than the generic ipc_call_sync_slow() because the payload89 * is passed directly in registers.90 * 91 * @param phoneid 92 * @param method 93 * @param arg1 94 * @param arg2 95 * @param arg3 96 * @param result1 97 * @param result2 98 * @param result3 99 * @param result4 100 * @param result5 101 * 102 * @return Negative values represent errors returned by IPC.103 * Otherwise the RETVAL of the answer is returned.104 * /105 int 106 i pc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1, sysarg_t arg2,107 sysarg_t arg 3, sysarg_t *result1, sysarg_t *result2, sysarg_t *result3,108 sysarg_t *result 4, sysarg_t *result5)84 /** Fast synchronous call. 85 * 86 * Only three payload arguments can be passed using this function. However, 87 * this function is faster than the generic ipc_call_sync_slow() because 88 * the payload is passed directly in registers. 89 * 90 * @param phoneid Phone handle for the call. 91 * @param method Requested method. 92 * @param arg1 Service-defined payload argument. 93 * @param arg2 Service-defined payload argument. 94 * @param arg3 Service-defined payload argument. 95 * @param result1 If non-NULL, the return ARG1 will be stored there. 96 * @param result2 If non-NULL, the return ARG2 will be stored there. 97 * @param result3 If non-NULL, the return ARG3 will be stored there. 98 * @param result4 If non-NULL, the return ARG4 will be stored there. 99 * @param result5 If non-NULL, the return ARG5 will be stored there. 100 * 101 * @return Negative values representing IPC errors. 102 * @return Otherwise the RETVAL of the answer. 103 * 104 */ 105 int ipc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1, 106 sysarg_t arg2, sysarg_t arg3, sysarg_t *result1, sysarg_t *result2, 107 sysarg_t *result3, sysarg_t *result4, sysarg_t *result5) 109 108 { 110 109 ipc_call_t resdata; 111 int callres; 112 113 callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1, 110 int callres = __SYSCALL6(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1, 114 111 arg2, arg3, (sysarg_t) &resdata); 115 112 if (callres) 116 113 return callres; 114 117 115 if (result1) 118 116 *result1 = IPC_GET_ARG1(resdata); … … 125 123 if (result5) 126 124 *result5 = IPC_GET_ARG5(resdata); 127 125 128 126 return IPC_GET_RETVAL(resdata); 129 127 } 130 128 131 /** Make a synchronous call transmitting 5 arguments of payload.129 /** Synchronous call transmitting 5 arguments of payload. 132 130 * 133 131 * @param phoneid Phone handle for the call. … … 144 142 * @param result5 If non-NULL, storage for the fifth return argument. 145 143 * 146 * @return Negative value means IPC error.147 * 148 * 149 */ 150 int 151 ipc_call_sync_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,152 sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, sysarg_t *result1,153 sysarg_t *result 2, sysarg_t *result3, sysarg_t *result4, sysarg_t *result5)144 * @return Negative values representing IPC errors. 145 * @return Otherwise the RETVAL of the answer. 146 * 147 */ 148 int ipc_call_sync_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, 149 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 150 sysarg_t *result1, sysarg_t *result2, sysarg_t *result3, sysarg_t *result4, 151 sysarg_t *result5) 154 152 { 155 153 ipc_call_t data; … … 181 179 } 182 180 183 /** S yscall to send asynchronous message.181 /** Send asynchronous message via syscall. 184 182 * 185 183 * @param phoneid Phone handle for the call. … … 189 187 * 190 188 */ 191 static ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data)189 static ipc_callid_t ipc_call_async_internal(int phoneid, ipc_call_t *data) 192 190 { 193 191 return __SYSCALL2(SYS_IPC_CALL_ASYNC_SLOW, phoneid, (sysarg_t) data); 194 192 } 195 193 196 /** Prolog to ipc_call_async_*() functions. 197 * 198 * @param private Argument for the answer/error callback. 199 * @param callback Answer/error callback. 200 * 201 * @return New, partially initialized async_call structure or NULL. 194 /** Prolog for ipc_call_async_*() functions. 195 * 196 * @param private Argument for the answer/error callback. 197 * @param callback Answer/error callback. 198 * 199 * @return New, partially initialized async_call structure or NULL. 200 * 202 201 */ 203 202 static inline async_call_t *ipc_prepare_async(void *private, 204 203 ipc_async_callback_t callback) 205 204 { 206 async_call_t *call; 207 208 call = malloc(sizeof(*call)); 205 async_call_t *call = 206 (async_call_t *) malloc(sizeof(async_call_t)); 209 207 if (!call) { 210 208 if (callback) 211 209 callback(private, ENOMEM, NULL); 210 212 211 return NULL; 213 212 } 213 214 214 call->callback = callback; 215 215 call->private = private; 216 216 217 217 return call; 218 218 } 219 219 220 /** Epilogue of ipc_call_async_*() functions. 221 * 222 * @param callid Value returned by the SYS_IPC_CALL_ASYNC_* syscall. 223 * @param phoneid Phone handle through which the call was made. 224 * @param call async_call structure returned by ipc_prepare_async(). 225 * @param can_preempt If non-zero, the current fibril can be preempted in this 226 * call. 220 /** Epilog for ipc_call_async_*() functions. 221 * 222 * @param callid Value returned by the SYS_IPC_CALL_ASYNC_* syscall. 223 * @param phoneid Phone handle through which the call was made. 224 * @param call Structure returned by ipc_prepare_async(). 225 * @param can_preempt If true, the current fibril can be preempted 226 * in this call. 227 * 227 228 */ 228 229 static inline void ipc_finish_async(ipc_callid_t callid, int phoneid, 229 async_call_t *call, int can_preempt) 230 { 231 if (!call) { /* Nothing to do regardless if failed or not */ 230 async_call_t *call, bool can_preempt) 231 { 232 if (!call) { 233 /* Nothing to do regardless if failed or not */ 232 234 futex_up(&ipc_futex); 233 235 return; 234 236 } 235 237 236 238 if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) { 237 239 futex_up(&ipc_futex); 240 238 241 /* Call asynchronous handler with error code */ 239 242 if (call->callback) 240 243 call->callback(call->private, ENOENT, NULL); 244 241 245 free(call); 242 246 return; 243 247 } 244 248 245 249 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { 246 250 futex_up(&ipc_futex); 247 251 248 252 call->u.msg.phoneid = phoneid; 249 253 250 254 futex_down(&async_futex); 251 255 list_append(&call->list, &queued_calls); 252 256 253 257 if (can_preempt) { 254 258 call->fid = fibril_get_id(); … … 259 263 futex_up(&async_futex); 260 264 } 265 261 266 return; 262 267 } 268 263 269 call->u.callid = callid; 270 264 271 /* Add call to the list of dispatched calls */ 265 272 list_append(&call->list, &dispatched_calls); 266 273 futex_up(&ipc_futex); 267 268 } 269 270 /** Make a fast asynchronous call. 274 } 275 276 /** Fast asynchronous call. 271 277 * 272 278 * This function can only handle four arguments of payload. It is, however, … … 274 280 * 275 281 * Note that this function is a void function. 276 * During normal opertation, answering this call will trigger the callback. 277 * In case of fatal error, call the callback handler with the proper error code. 278 * If the call cannot be temporarily made, queue it. 282 * 283 * During normal operation, answering this call will trigger the callback. 284 * In case of fatal error, the callback handler is called with the proper 285 * error code. If the call cannot be temporarily made, it is queued. 279 286 * 280 287 * @param phoneid Phone handle for the call. … … 286 293 * @param private Argument to be passed to the answer/error callback. 287 294 * @param callback Answer or error callback. 288 * @param can_preempt If non-zero, the current fibril will be preempted in295 * @param can_preempt If true, the current fibril will be preempted in 289 296 * case the kernel temporarily refuses to accept more 290 297 * asynchronous calls. … … 293 300 void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1, 294 301 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private, 295 ipc_async_callback_t callback, intcan_preempt)302 ipc_async_callback_t callback, bool can_preempt) 296 303 { 297 304 async_call_t *call = NULL; … … 304 311 305 312 /* 306 * We need to make sure that we get callid before another thread307 * accesses the queue again.313 * We need to make sure that we get callid 314 * before another thread accesses the queue again. 308 315 */ 316 309 317 futex_down(&ipc_futex); 310 318 ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid, … … 317 325 return; 318 326 } 327 319 328 IPC_SET_IMETHOD(call->u.msg.data, imethod); 320 329 IPC_SET_ARG1(call->u.msg.data, arg1); … … 322 331 IPC_SET_ARG3(call->u.msg.data, arg3); 323 332 IPC_SET_ARG4(call->u.msg.data, arg4); 333 324 334 /* 325 335 * To achieve deterministic behavior, we always zero out the 326 336 * arguments that are beyond the limits of the fast version. 327 337 */ 338 328 339 IPC_SET_ARG5(call->u.msg.data, 0); 329 340 } 341 330 342 ipc_finish_async(callid, phoneid, call, can_preempt); 331 343 } 332 344 333 /** Make an asynchronous call transmitting the entire payload.345 /** Asynchronous call transmitting the entire payload. 334 346 * 335 347 * Note that this function is a void function. 336 * During normal opertation, answering this call will trigger the callback. 337 * In case of fatal error, call the callback handler with the proper error code. 338 * If the call cannot be temporarily made, queue it. 348 * 349 * During normal operation, answering this call will trigger the callback. 350 * In case of fatal error, the callback handler is called with the proper 351 * error code. If the call cannot be temporarily made, it is queued. 339 352 * 340 353 * @param phoneid Phone handle for the call. … … 347 360 * @param private Argument to be passed to the answer/error callback. 348 361 * @param callback Answer or error callback. 349 * @param can_preempt If non-zero, the current fibril will be preempted in362 * @param can_preempt If true, the current fibril will be preempted in 350 363 * case the kernel temporarily refuses to accept more 351 364 * asynchronous calls. … … 354 367 void ipc_call_async_slow(int phoneid, sysarg_t imethod, sysarg_t arg1, 355 368 sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, void *private, 356 ipc_async_callback_t callback, int can_preempt) 357 { 358 async_call_t *call; 359 ipc_callid_t callid; 360 361 call = ipc_prepare_async(private, callback); 369 ipc_async_callback_t callback, bool can_preempt) 370 { 371 async_call_t *call = ipc_prepare_async(private, callback); 362 372 if (!call) 363 373 return; 364 374 365 375 IPC_SET_IMETHOD(call->u.msg.data, imethod); 366 376 IPC_SET_ARG1(call->u.msg.data, arg1); … … 369 379 IPC_SET_ARG4(call->u.msg.data, arg4); 370 380 IPC_SET_ARG5(call->u.msg.data, arg5); 381 371 382 /* 372 * We need to make sure that we get callid before another thread373 * accesses the queue again.383 * We need to make sure that we get callid 384 * before another threadaccesses the queue again. 374 385 */ 386 375 387 futex_down(&ipc_futex); 376 callid = _ipc_call_async(phoneid, &call->u.msg.data); 377 388 ipc_callid_t callid = 389 ipc_call_async_internal(phoneid, &call->u.msg.data); 390 378 391 ipc_finish_async(callid, phoneid, call, can_preempt); 379 392 } 380 393 381 382 /** Answer a received call - fast version. 394 /** Answer received call (fast version). 383 395 * 384 396 * The fast answer makes use of passing retval and first four arguments in 385 397 * registers. If you need to return more, use the ipc_answer_slow() instead. 386 398 * 387 * @param callid Hash of the call being answered. 388 * @param retval Return value. 389 * @param arg1 First return argument. 390 * @param arg2 Second return argument. 391 * @param arg3 Third return argument. 392 * @param arg4 Fourth return argument. 393 * 394 * @return Zero on success or a value from @ref errno.h on failure. 399 * @param callid Hash of the call being answered. 400 * @param retval Return value. 401 * @param arg1 First return argument. 402 * @param arg2 Second return argument. 403 * @param arg3 Third return argument. 404 * @param arg4 Fourth return argument. 405 * 406 * @return Zero on success. 407 * @return Value from @ref errno.h on failure. 408 * 395 409 */ 396 410 sysarg_t ipc_answer_fast(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, … … 401 415 } 402 416 403 /** Answer a received call - slow full version. 404 * 405 * @param callid Hash of the call being answered. 406 * @param retval Return value. 407 * @param arg1 First return argument. 408 * @param arg2 Second return argument. 409 * @param arg3 Third return argument. 410 * @param arg4 Fourth return argument. 411 * @param arg5 Fifth return argument. 412 * 413 * @return Zero on success or a value from @ref errno.h on failure. 417 /** Answer received call (entire payload). 418 * 419 * @param callid Hash of the call being answered. 420 * @param retval Return value. 421 * @param arg1 First return argument. 422 * @param arg2 Second return argument. 423 * @param arg3 Third return argument. 424 * @param arg4 Fourth return argument. 425 * @param arg5 Fifth return argument. 426 * 427 * @return Zero on success. 428 * @return Value from @ref errno.h on failure. 429 * 414 430 */ 415 431 sysarg_t ipc_answer_slow(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1, … … 417 433 { 418 434 ipc_call_t data; 419 435 420 436 IPC_SET_RETVAL(data, retval); 421 437 IPC_SET_ARG1(data, arg1); … … 424 440 IPC_SET_ARG4(data, arg4); 425 441 IPC_SET_ARG5(data, arg5); 426 442 427 443 return __SYSCALL2(SYS_IPC_ANSWER_SLOW, callid, (sysarg_t) &data); 428 444 } 429 445 430 431 /** Try to dispatch queued calls from the async queue. */ 432 static void try_dispatch_queued_calls(void) 433 { 434 async_call_t *call; 435 ipc_callid_t callid; 436 446 /** Try to dispatch queued calls from the async queue. 447 * 448 */ 449 static void dispatch_queued_calls(void) 450 { 437 451 /** @todo 438 * Integrate intelligently ipc_futex ,so that it is locked during439 * ipc_call_async_*() ,until it is added to dispatched_calls.452 * Integrate intelligently ipc_futex so that it is locked during 453 * ipc_call_async_*() until it is added to dispatched_calls. 440 454 */ 455 441 456 futex_down(&async_futex); 457 442 458 while (!list_empty(&queued_calls)) { 443 call = list_get_instance(queued_calls.next, async_call_t, list); 444 callid = _ipc_call_async(call->u.msg.phoneid, 445 &call->u.msg.data); 446 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) { 459 async_call_t *call = 460 list_get_instance(queued_calls.next, async_call_t, list); 461 ipc_callid_t callid = 462 ipc_call_async_internal(call->u.msg.phoneid, &call->u.msg.data); 463 464 if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) 447 465 break; 448 }466 449 467 list_remove(&call->list); 450 468 451 469 futex_up(&async_futex); 470 452 471 if (call->fid) 453 472 fibril_add_ready(call->fid); … … 456 475 if (call->callback) 457 476 call->callback(call->private, ENOENT, NULL); 477 458 478 free(call); 459 479 } else { 460 480 call->u.callid = callid; 481 461 482 futex_down(&ipc_futex); 462 483 list_append(&call->list, &dispatched_calls); 463 484 futex_up(&ipc_futex); 464 485 } 486 465 487 futex_down(&async_futex); 466 488 } 489 467 490 futex_up(&async_futex); 468 491 } 469 492 470 /** Handle areceived answer.493 /** Handle received answer. 471 494 * 472 495 * Find the hash of the answer and call the answer callback. 473 496 * 474 * @todo Make it use hash table. 475 * 476 * @param callid Hash of the received answer. 477 * The answer has the same hash as the request OR'ed with 478 * the IPC_CALLID_ANSWERED bit. 479 * @param data Call data of the answer. 497 * The answer has the same hash as the request OR'ed with 498 * the IPC_CALLID_ANSWERED bit. 499 * 500 * @todo Use hash table. 501 * 502 * @param callid Hash of the received answer. 503 * @param data Call data of the answer. 504 * 480 505 */ 481 506 static void handle_answer(ipc_callid_t callid, ipc_call_t *data) 482 507 { 508 callid &= ~IPC_CALLID_ANSWERED; 509 510 futex_down(&ipc_futex); 511 483 512 link_t *item; 484 async_call_t *call;485 486 callid &= ~IPC_CALLID_ANSWERED;487 488 futex_down(&ipc_futex);489 513 for (item = dispatched_calls.next; item != &dispatched_calls; 490 514 item = item->next) { 491 call = list_get_instance(item, async_call_t, list); 515 async_call_t *call = 516 list_get_instance(item, async_call_t, list); 517 492 518 if (call->u.callid == callid) { 493 519 list_remove(&call->list); 520 494 521 futex_up(&ipc_futex); 522 495 523 if (call->callback) 496 call->callback(call->private, 524 call->callback(call->private, 497 525 IPC_GET_RETVAL(*data), data); 526 498 527 free(call); 499 528 return; 500 529 } 501 530 } 531 502 532 futex_up(&ipc_futex); 503 533 } 504 534 505 506 /** Wait for a first call to come. 507 * 508 * @param call Storage where the incoming call data will be stored.509 * @param usec Timeout in microseconds510 * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking).511 * 512 * @return Hash of the call. Note that certain bits have special513 * meaning. IPC_CALLID_ANSWERED will be set in an answer514 * and IPC_CALLID_NOTIFICATION is used for notifications.515 * 516 */ 517 ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec,int flags)518 { 519 ipc_callid_t callid ;520 521 callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags);535 /** Wait for first IPC call to come. 536 * 537 * @param call Incoming call storage. 538 * @param usec Timeout in microseconds 539 * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking). 540 * 541 * @return Hash of the call. Note that certain bits have special 542 * meaning: IPC_CALLID_ANSWERED is set in an answer 543 * and IPC_CALLID_NOTIFICATION is used for notifications. 544 * 545 */ 546 ipc_callid_t ipc_wait_cycle(ipc_call_t *call, sysarg_t usec, 547 unsigned int flags) 548 { 549 ipc_callid_t callid = 550 __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags); 551 522 552 /* Handle received answers */ 523 553 if (callid & IPC_CALLID_ANSWERED) { 524 554 handle_answer(callid, call); 525 try_dispatch_queued_calls();555 dispatch_queued_calls(); 526 556 } 527 557 528 558 return callid; 529 559 } 530 560 531 /** Wait some time for an IPC call. 532 * 533 * The call will return after an answer is received. 534 * 535 * @param call Storage where the incoming call data will be stored. 536 * @param usec Timeout in microseconds. 537 * 538 * @return Hash of the answer. 539 */ 540 ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec) 561 /** Interrupt one thread of this task from waiting for IPC. 562 * 563 */ 564 void ipc_poke(void) 565 { 566 __SYSCALL0(SYS_IPC_POKE); 567 } 568 569 /** Wait for first IPC call to come. 570 * 571 * Only requests are returned, answers are processed internally. 572 * 573 * @param call Incoming call storage. 574 * @param usec Timeout in microseconds 575 * 576 * @return Hash of the call. 577 * 578 */ 579 ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, sysarg_t usec) 541 580 { 542 581 ipc_callid_t callid; 543 582 544 583 do { 545 584 callid = ipc_wait_cycle(call, usec, SYNCH_FLAGS_NONE); 546 585 } while (callid & IPC_CALLID_ANSWERED); 547 586 548 587 return callid; 549 588 } … … 551 590 /** Check if there is an IPC call waiting to be picked up. 552 591 * 553 * @param call Storage where the incoming call will be stored. 554 * @return Hash of the answer. 592 * Only requests are returned, answers are processed internally. 593 * 594 * @param call Incoming call storage. 595 * 596 * @return Hash of the call. 597 * 555 598 */ 556 599 ipc_callid_t ipc_trywait_for_call(ipc_call_t *call) 557 600 { 558 601 ipc_callid_t callid; 559 602 560 603 do { 561 604 callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, 562 605 SYNCH_FLAGS_NON_BLOCKING); 563 606 } while (callid & IPC_CALLID_ANSWERED); 564 607 565 608 return callid; 566 609 } 567 610 568 /** Interrupt one thread of this task from waiting for IPC. */ 569 void ipc_poke(void) 570 { 571 __SYSCALL0(SYS_IPC_POKE); 572 } 573 574 /** Ask destination to do a callback connection. 575 * 576 * @param phoneid Phone handle used for contacting the other side. 577 * @param arg1 Service-defined argument. 578 * @param arg2 Service-defined argument. 579 * @param arg3 Service-defined argument. 580 * @param taskhash Storage where the kernel will store an opaque 581 * identifier of the client task. 582 * @param phonehash Storage where the kernel will store an opaque 583 * identifier of the phone that will be used for incoming 584 * calls. This identifier can be used for connection 585 * tracking. 586 * 587 * @return Zero on success or a negative error code. 588 */ 589 int ipc_connect_to_me(int phoneid, int arg1, int arg2, int arg3, 611 /** Request callback connection. 612 * 613 * The @a taskhash and @a phonehash identifiers returned 614 * by the kernel can be used for connection tracking. 615 * 616 * @param phoneid Phone handle used for contacting the other side. 617 * @param arg1 User defined argument. 618 * @param arg2 User defined argument. 619 * @param arg3 User defined argument. 620 * @param taskhash Opaque identifier of the client task. 621 * @param phonehash Opaque identifier of the phone that will 622 * be used for incoming calls. 623 * 624 * @return Zero on success or a negative error code. 625 * 626 */ 627 int ipc_connect_to_me(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, 590 628 sysarg_t *taskhash, sysarg_t *phonehash) 591 629 { … … 594 632 } 595 633 596 /** Ask through phone for a new connection to some service. 597 * 598 * @param phoneid Phone handle used for contacting the other side. 599 * @param arg1 User defined argument. 600 * @param arg2 User defined argument. 601 * @param arg3 User defined argument. 602 * 603 * @return New phone handle on success or a negative error code. 604 */ 605 int ipc_connect_me_to(int phoneid, int arg1, int arg2, int arg3) 634 /** Request new connection. 635 * 636 * @param phoneid Phone handle used for contacting the other side. 637 * @param arg1 User defined argument. 638 * @param arg2 User defined argument. 639 * @param arg3 User defined argument. 640 * 641 * @return New phone handle on success or a negative error code. 642 * 643 */ 644 int ipc_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3) 606 645 { 607 646 sysarg_t newphid; 608 int res; 609 610 res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 647 int res = ipc_call_sync_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 611 648 NULL, NULL, NULL, NULL, &newphid); 612 649 if (res) 613 650 return res; 651 614 652 return newphid; 615 653 } 616 654 617 /** Ask through phone for a new connection to some service.655 /** Request new connection (blocking) 618 656 * 619 657 * If the connection is not available at the moment, the 620 * call will block. 621 * 622 * @param phoneid Phone handle used for contacting the other side. 623 * @param arg1 User defined argument. 624 * @param arg2 User defined argument. 625 * @param arg3 User defined argument. 626 * 627 * @return New phone handle on success or a negative error code. 628 */ 629 int ipc_connect_me_to_blocking(int phoneid, int arg1, int arg2, int arg3) 658 * call should block. This has to be, however, implemented 659 * on the server side. 660 * 661 * @param phoneid Phone handle used for contacting the other side. 662 * @param arg1 User defined argument. 663 * @param arg2 User defined argument. 664 * @param arg3 User defined argument. 665 * 666 * @return New phone handle on success or a negative error code. 667 * 668 */ 669 int ipc_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2, 670 sysarg_t arg3) 630 671 { 631 672 sysarg_t newphid; 632 int res; 633 634 res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 673 int res = ipc_call_sync_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, 635 674 IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid); 636 675 if (res) 637 676 return res; 677 638 678 return newphid; 639 679 } … … 641 681 /** Hang up a phone. 642 682 * 643 * @param phoneid Handle of the phone to be hung up. 644 * 645 * @return Zero on success or a negative error code. 683 * @param phoneid Handle of the phone to be hung up. 684 * 685 * @return Zero on success or a negative error code. 686 * 646 687 */ 647 688 int ipc_hangup(int phoneid) … … 650 691 } 651 692 652 /** Register IRQ notification.653 *654 * @param inr IRQ number.655 * @param devno Device number of the device generating inr.656 * @param method Use this method for notifying me.657 * @param ucode Top-half pseudocode handler.658 *659 * @return Value returned by the kernel.660 */661 int ipc_register_irq(int inr, int devno, int method, irq_code_t *ucode)662 {663 return __SYSCALL4(SYS_IPC_REGISTER_IRQ, inr, devno, method,664 (sysarg_t) ucode);665 }666 667 /** Unregister IRQ notification.668 *669 * @param inr IRQ number.670 * @param devno Device number of the device generating inr.671 *672 * @return Value returned by the kernel.673 */674 int ipc_unregister_irq(int inr, int devno)675 {676 return __SYSCALL2(SYS_IPC_UNREGISTER_IRQ, inr, devno);677 }678 679 693 /** Forward a received call to another destination. 694 * 695 * For non-system methods, the old method, arg1 and arg2 are rewritten 696 * by the new values. For system methods, the new method, arg1 and arg2 697 * are written to the old arg1, arg2 and arg3, respectivelly. Calls with 698 * immutable methods are forwarded verbatim. 680 699 * 681 700 * @param callid Hash of the call to forward. … … 688 707 * @return Zero on success or an error code. 689 708 * 690 * For non-system methods, the old method, arg1 and arg2 are rewritten by the 691 * new values. For system methods, the new method, arg1 and arg2 are written 692 * to the old arg1, arg2 and arg3, respectivelly. Calls with immutable 693 * methods are forwarded verbatim. 694 */ 695 int ipc_forward_fast(ipc_callid_t callid, int phoneid, int imethod, 696 sysarg_t arg1, sysarg_t arg2, int mode) 709 */ 710 int ipc_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod, 711 sysarg_t arg1, sysarg_t arg2, unsigned int mode) 697 712 { 698 713 return __SYSCALL6(SYS_IPC_FORWARD_FAST, callid, phoneid, imethod, arg1, … … 700 715 } 701 716 702 703 int ipc_forward_slow(ipc_callid_t callid, int phoneid, int imethod, 717 int ipc_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod, 704 718 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5, 705 int mode)719 unsigned int mode) 706 720 { 707 721 ipc_call_t data; … … 714 728 IPC_SET_ARG5(data, arg5); 715 729 716 return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, mode); 717 } 718 719 /** Wrapper for making IPC_M_SHARE_IN calls. 720 * 721 * @param phoneid Phone that will be used to contact the receiving side. 722 * @param dst Destination address space area base. 723 * @param size Size of the destination address space area. 724 * @param arg User defined argument. 725 * @param flags Storage where the received flags will be stored. Can be 726 * NULL. 727 * 728 * @return Zero on success or a negative error code from errno.h. 730 return __SYSCALL4(SYS_IPC_FORWARD_SLOW, callid, phoneid, (sysarg_t) &data, 731 mode); 732 } 733 734 /** Wrapper for IPC_M_SHARE_IN calls. 735 * 736 * @param phoneid Phone that will be used to contact the receiving side. 737 * @param dst Destination address space area base. 738 * @param size Size of the destination address space area. 739 * @param arg User defined argument. 740 * @param flags Storage for received flags. Can be NULL. 741 * 742 * @return Zero on success or a negative error code from errno.h. 743 * 729 744 */ 730 745 int ipc_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg, 731 int *flags)746 unsigned int *flags) 732 747 { 733 748 sysarg_t tmp_flags = 0; … … 736 751 737 752 if (flags) 738 *flags = tmp_flags;753 *flags = (unsigned int) tmp_flags; 739 754 740 755 return res; … … 743 758 /** Wrapper for answering the IPC_M_SHARE_IN calls. 744 759 * 745 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls 746 * so that the user doesn't have to remember the meaning of each IPC argument. 747 * 748 * @param callid Hash of the IPC_M_DATA_READ call to answer. 749 * @param src Source address space base. 750 * @param flags Flags to be used for sharing. Bits can be only cleared. 751 * 752 * @return Zero on success or a value from @ref errno.h on failure. 753 */ 754 int ipc_share_in_finalize(ipc_callid_t callid, void *src, int flags) 760 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 761 * calls so that the user doesn't have to remember the meaning of each 762 * IPC argument. 763 * 764 * @param callid Hash of the IPC_M_DATA_READ call to answer. 765 * @param src Source address space base. 766 * @param flags Flags to be used for sharing. Bits can be only cleared. 767 * 768 * @return Zero on success or a value from @ref errno.h on failure. 769 * 770 */ 771 int ipc_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags) 755 772 { 756 773 return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) flags); 757 774 } 758 775 759 /** Wrapper for making IPC_M_SHARE_OUT calls. 760 * 761 * @param phoneid Phone that will be used to contact the receiving side. 762 * @param src Source address space area base address. 763 * @param flags Flags to be used for sharing. Bits can be only cleared. 764 * 765 * @return Zero on success or a negative error code from errno.h. 766 */ 767 int ipc_share_out_start(int phoneid, void *src, int flags) 776 /** Wrapper for IPC_M_SHARE_OUT calls. 777 * 778 * @param phoneid Phone that will be used to contact the receiving side. 779 * @param src Source address space area base address. 780 * @param flags Flags to be used for sharing. Bits can be only cleared. 781 * 782 * @return Zero on success or a negative error code from errno.h. 783 * 784 */ 785 int ipc_share_out_start(int phoneid, void *src, unsigned int flags) 768 786 { 769 787 return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0, … … 773 791 /** Wrapper for answering the IPC_M_SHARE_OUT calls. 774 792 * 775 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls 776 * so that the user doesn't have to remember the meaning of each IPC argument. 777 * 778 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 779 * @param dst Destination address space area base address. 780 * 781 * @return Zero on success or a value from @ref errno.h on failure. 793 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT 794 * calls so that the user doesn't have to remember the meaning of each 795 * IPC argument. 796 * 797 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 798 * @param dst Destination address space area base address. 799 * 800 * @return Zero on success or a value from @ref errno.h on failure. 801 * 782 802 */ 783 803 int ipc_share_out_finalize(ipc_callid_t callid, void *dst) … … 786 806 } 787 807 788 789 /** Wrapper for making IPC_M_DATA_READ calls. 790 * 791 * @param phoneid Phone that will be used to contact the receiving side.792 * @param dst Address of the beginningof the destination buffer.793 * @param size Size of the destination buffer.794 * 795 * @return Zero on success or a negative error code from errno.h.808 /** Wrapper for IPC_M_DATA_READ calls. 809 * 810 * @param phoneid Phone that will be used to contact the receiving side. 811 * @param dst Address of the beginning of the destination buffer. 812 * @param size Size of the destination buffer. 813 * 814 * @return Zero on success or a negative error code from errno.h. 815 * 796 816 */ 797 817 int ipc_data_read_start(int phoneid, void *dst, size_t size) … … 803 823 /** Wrapper for answering the IPC_M_DATA_READ calls. 804 824 * 805 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls 806 * so that the user doesn't have to remember the meaning of each IPC argument. 807 * 808 * @param callid Hash of the IPC_M_DATA_READ call to answer. 809 * @param src Source address for the IPC_M_DATA_READ call. 810 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 811 * the maximum size announced by the sender. 812 * 813 * @return Zero on success or a value from @ref errno.h on failure. 825 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ 826 * calls so that the user doesn't have to remember the meaning of each 827 * IPC argument. 828 * 829 * @param callid Hash of the IPC_M_DATA_READ call to answer. 830 * @param src Source address for the IPC_M_DATA_READ call. 831 * @param size Size for the IPC_M_DATA_READ call. Can be smaller than 832 * the maximum size announced by the sender. 833 * 834 * @return Zero on success or a value from @ref errno.h on failure. 835 * 814 836 */ 815 837 int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size) … … 818 840 } 819 841 820 /** Wrapper for making IPC_M_DATA_WRITE calls. 821 * 822 * @param phoneid Phone that will be used to contact the receiving side. 823 * @param src Address of the beginning of the source buffer. 824 * @param size Size of the source buffer. 825 * 826 * @return Zero on success or a negative error code from errno.h. 842 /** Wrapper for IPC_M_DATA_WRITE calls. 843 * 844 * @param phoneid Phone that will be used to contact the receiving side. 845 * @param src Address of the beginning of the source buffer. 846 * @param size Size of the source buffer. 847 * 848 * @return Zero on success or a negative error code from errno.h. 849 * 827 850 */ 828 851 int ipc_data_write_start(int phoneid, const void *src, size_t size) … … 834 857 /** Wrapper for answering the IPC_M_DATA_WRITE calls. 835 858 * 836 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls 837 * so that the user doesn't have to remember the meaning of each IPC argument. 838 * 839 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 840 * @param dst Final destination address for the IPC_M_DATA_WRITE call. 841 * @param size Final size for the IPC_M_DATA_WRITE call. 842 * 843 * @return Zero on success or a value from @ref errno.h on failure. 859 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE 860 * calls so that the user doesn't have to remember the meaning of each 861 * IPC argument. 862 * 863 * @param callid Hash of the IPC_M_DATA_WRITE call to answer. 864 * @param dst Final destination address for the IPC_M_DATA_WRITE call. 865 * @param size Final size for the IPC_M_DATA_WRITE call. 866 * 867 * @return Zero on success or a value from @ref errno.h on failure. 868 * 844 869 */ 845 870 int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size) -
uspace/lib/c/generic/libc.c
r89acf204 r474afc9 42 42 43 43 #include <libc.h> 44 #include <stdio.h> 45 #include <unistd.h> 46 #include <malloc.h> 44 #include <stdlib.h> 47 45 #include <tls.h> 48 #include <thread.h>49 46 #include <fibril.h> 50 #include <ipc/ipc.h> 51 #include <async.h> 52 #include <as.h> 47 #include <task.h> 53 48 #include <loader/pcb.h> 49 #include "private/libc.h" 50 #include "private/async.h" 51 #include "private/async_sess.h" 52 #include "private/malloc.h" 53 #include "private/io.h" 54 54 55 extern int main(int argc, char *argv[]); 56 57 void _exit(int status) 58 { 59 thread_exit(status); 60 } 55 static bool env_setup = false; 61 56 62 57 void __main(void *pcb_ptr) 63 58 { 64 59 /* Initialize user task run-time environment */ 65 __ heap_init();60 __malloc_init(); 66 61 __async_init(); 62 __async_sess_init(); 63 67 64 fibril_t *fibril = fibril_setup(); 65 if (fibril == NULL) 66 abort(); 67 68 68 __tcb_set(fibril->tcb); 69 69 … … 71 71 __pcb = (pcb_t *) pcb_ptr; 72 72 73 /* The basic run-time environment is setup */ 74 env_setup = true; 75 73 76 int argc; 74 77 char **argv; 75 78 76 /* Get command line arguments and initialize 77 standard input and output */ 79 /* 80 * Get command line arguments and initialize 81 * standard input and output 82 */ 78 83 if (__pcb == NULL) { 79 84 argc = 0; … … 87 92 } 88 93 89 /* Run main() and set task return value 90 according the result */ 91 (void) task_retval(main(argc, argv)); 94 /* 95 * Run main() and set task return value 96 * according the result 97 */ 98 int retval = main(argc, argv); 99 exit(retval); 92 100 } 93 101 94 void __exit(void)102 void exit(int status) 95 103 { 96 __stdio_done(); 97 fibril_teardown(__tcb_get()->fibril_data); 98 _exit(0); 104 if (env_setup) { 105 __stdio_done(); 106 task_retval(status); 107 fibril_teardown(__tcb_get()->fibril_data); 108 } 109 110 __SYSCALL1(SYS_TASK_EXIT, false); 111 112 /* Unreachable */ 113 while (1); 114 } 115 116 void abort(void) 117 { 118 __SYSCALL1(SYS_TASK_EXIT, true); 119 120 /* Unreachable */ 121 while (1); 99 122 } 100 123 -
uspace/lib/c/generic/loader.c
r89acf204 r474afc9 33 33 */ 34 34 35 #include <ipc/ipc.h>36 35 #include <ipc/loader.h> 37 36 #include <ipc/services.h> 37 #include <ipc/ns.h> 38 38 #include <libc.h> 39 39 #include <task.h> … … 63 63 loader_t *loader_connect(void) 64 64 { 65 int phone_id = ipc_connect_me_to_blocking(PHONE_NS,SERVICE_LOAD, 0, 0);65 int phone_id = service_connect_blocking(SERVICE_LOAD, 0, 0); 66 66 if (phone_id < 0) 67 67 return NULL; … … 319 319 return rc; 320 320 321 ipc_hangup(ldr->phone_id);321 async_hangup(ldr->phone_id); 322 322 ldr->phone_id = 0; 323 323 return EOK; … … 337 337 void loader_abort(loader_t *ldr) 338 338 { 339 ipc_hangup(ldr->phone_id);339 async_hangup(ldr->phone_id); 340 340 ldr->phone_id = 0; 341 341 } -
uspace/lib/c/generic/malloc.c
r89acf204 r474afc9 45 45 #include <futex.h> 46 46 #include <adt/gcdlcm.h> 47 48 /* Magic used in heap headers. */ 49 #define HEAP_BLOCK_HEAD_MAGIC 0xBEEF0101 50 51 /* Magic used in heap footers. */ 52 #define HEAP_BLOCK_FOOT_MAGIC 0xBEEF0202 53 54 /** Allocation alignment (this also covers the alignment of fields 55 in the heap header and footer) */ 47 #include "private/malloc.h" 48 49 /** Magic used in heap headers. */ 50 #define HEAP_BLOCK_HEAD_MAGIC UINT32_C(0xBEEF0101) 51 52 /** Magic used in heap footers. */ 53 #define HEAP_BLOCK_FOOT_MAGIC UINT32_C(0xBEEF0202) 54 55 /** Magic used in heap descriptor. */ 56 #define HEAP_AREA_MAGIC UINT32_C(0xBEEFCAFE) 57 58 /** Allocation alignment. 59 * 60 * This also covers the alignment of fields 61 * in the heap header and footer. 62 * 63 */ 56 64 #define BASE_ALIGN 16 57 65 58 /** 59 * Either 4 * 256M on 32-bit architecures or 16 * 256M on 64-bit architectures 60 */ 61 #define MAX_HEAP_SIZE (sizeof(uintptr_t) << 28) 62 63 /** 64 * 65 */ 66 #define STRUCT_OVERHEAD (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t)) 67 68 /** 69 * Calculate real size of a heap block (with header and footer) 66 /** Overhead of each heap block. */ 67 #define STRUCT_OVERHEAD \ 68 (sizeof(heap_block_head_t) + sizeof(heap_block_foot_t)) 69 70 /** Calculate real size of a heap block. 71 * 72 * Add header and footer size. 73 * 70 74 */ 71 75 #define GROSS_SIZE(size) ((size) + STRUCT_OVERHEAD) 72 76 73 /** 74 * Calculate net size of a heap block (without header and footer) 77 /** Calculate net size of a heap block. 78 * 79 * Subtract header and footer size. 80 * 75 81 */ 76 82 #define NET_SIZE(size) ((size) - STRUCT_OVERHEAD) 83 84 /** Get first block in heap area. 85 * 86 */ 87 #define AREA_FIRST_BLOCK(area) \ 88 (ALIGN_UP(((uintptr_t) (area)) + sizeof(heap_area_t), BASE_ALIGN)) 89 90 /** Get footer in heap block. 91 * 92 */ 93 #define BLOCK_FOOT(head) \ 94 ((heap_block_foot_t *) \ 95 (((uintptr_t) head) + head->size - sizeof(heap_block_foot_t))) 96 97 /** Heap area. 98 * 99 * The memory managed by the heap allocator is divided into 100 * multiple discontinuous heaps. Each heap is represented 101 * by a separate address space area which has this structure 102 * at its very beginning. 103 * 104 */ 105 typedef struct heap_area { 106 /** Start of the heap area (including this structure) 107 * 108 * Aligned on page boundary. 109 * 110 */ 111 void *start; 112 113 /** End of the heap area (aligned on page boundary) */ 114 void *end; 115 116 /** Next heap area */ 117 struct heap_area *next; 118 119 /** A magic value */ 120 uint32_t magic; 121 } heap_area_t; 77 122 78 123 /** Header of a heap block … … 86 131 bool free; 87 132 133 /** Heap area this block belongs to */ 134 heap_area_t *area; 135 88 136 /* A magic value to detect overwrite of heap header */ 89 137 uint32_t magic; … … 101 149 } heap_block_foot_t; 102 150 103 /** Linker heap symbol */ 104 extern char _heap; 151 /** First heap area */ 152 static heap_area_t *first_heap_area = NULL; 153 154 /** Last heap area */ 155 static heap_area_t *last_heap_area = NULL; 156 157 /** Next heap block to examine (next fit algorithm) */ 158 static heap_block_head_t *next = NULL; 105 159 106 160 /** Futex for thread-safe heap manipulation */ 107 161 static futex_t malloc_futex = FUTEX_INITIALIZER; 108 162 109 /** Address of heap start */110 static void *heap_start = 0;111 112 /** Address of heap end */113 static void *heap_end = 0;114 115 /** Maximum heap size */116 static size_t max_heap_size = (size_t) -1;117 118 /** Current number of pages of heap area */119 static size_t heap_pages = 0;120 121 163 /** Initialize a heap block 122 164 * 123 * Fill sin the structures related to a heap block.165 * Fill in the structures related to a heap block. 124 166 * Should be called only inside the critical section. 125 167 * … … 127 169 * @param size Size of the block including the header and the footer. 128 170 * @param free Indication of a free block. 129 * 130 */ 131 static void block_init(void *addr, size_t size, bool free) 171 * @param area Heap area the block belongs to. 172 * 173 */ 174 static void block_init(void *addr, size_t size, bool free, heap_area_t *area) 132 175 { 133 176 /* Calculate the position of the header and the footer */ 134 177 heap_block_head_t *head = (heap_block_head_t *) addr; 135 heap_block_foot_t *foot =136 (heap_block_foot_t *) (addr + size - sizeof(heap_block_foot_t));137 178 138 179 head->size = size; 139 180 head->free = free; 181 head->area = area; 140 182 head->magic = HEAP_BLOCK_HEAD_MAGIC; 183 184 heap_block_foot_t *foot = BLOCK_FOOT(head); 141 185 142 186 foot->size = size; … … 159 203 assert(head->magic == HEAP_BLOCK_HEAD_MAGIC); 160 204 161 heap_block_foot_t *foot = 162 (heap_block_foot_t *) (addr + head->size - sizeof(heap_block_foot_t)); 205 heap_block_foot_t *foot = BLOCK_FOOT(head); 163 206 164 207 assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC); … … 166 209 } 167 210 168 /** Increase the heap area size 169 * 170 * Should be called only inside the critical section. 171 * 172 * @param size Number of bytes to grow the heap by. 173 * 174 */ 175 static bool grow_heap(size_t size) 211 /** Check a heap area structure 212 * 213 * @param addr Address of the heap area. 214 * 215 */ 216 static void area_check(void *addr) 217 { 218 heap_area_t *area = (heap_area_t *) addr; 219 220 assert(area->magic == HEAP_AREA_MAGIC); 221 assert(area->start < area->end); 222 assert(((uintptr_t) area->start % PAGE_SIZE) == 0); 223 assert(((uintptr_t) area->end % PAGE_SIZE) == 0); 224 } 225 226 /** Create new heap area 227 * 228 * @param start Preffered starting address of the new area. 229 * @param size Size of the area. 230 * 231 */ 232 static bool area_create(size_t size) 233 { 234 void *start = as_get_mappable_page(size); 235 if (start == NULL) 236 return false; 237 238 /* Align the heap area on page boundary */ 239 void *astart = (void *) ALIGN_UP((uintptr_t) start, PAGE_SIZE); 240 size_t asize = ALIGN_UP(size, PAGE_SIZE); 241 242 astart = as_area_create(astart, asize, AS_AREA_WRITE | AS_AREA_READ); 243 if (astart == (void *) -1) 244 return false; 245 246 heap_area_t *area = (heap_area_t *) astart; 247 248 area->start = astart; 249 area->end = (void *) 250 ALIGN_DOWN((uintptr_t) astart + asize, BASE_ALIGN); 251 area->next = NULL; 252 area->magic = HEAP_AREA_MAGIC; 253 254 void *block = (void *) AREA_FIRST_BLOCK(area); 255 size_t bsize = (size_t) (area->end - block); 256 257 block_init(block, bsize, true, area); 258 259 if (last_heap_area == NULL) { 260 first_heap_area = area; 261 last_heap_area = area; 262 } else { 263 last_heap_area->next = area; 264 last_heap_area = area; 265 } 266 267 return true; 268 } 269 270 /** Try to enlarge a heap area 271 * 272 * @param area Heap area to grow. 273 * @param size Gross size of item to allocate (bytes). 274 * 275 */ 276 static bool area_grow(heap_area_t *area, size_t size) 176 277 { 177 278 if (size == 0) 279 return true; 280 281 area_check(area); 282 283 size_t asize = ALIGN_UP((size_t) (area->end - area->start) + size, 284 PAGE_SIZE); 285 286 /* New heap area size */ 287 void *end = (void *) 288 ALIGN_DOWN((uintptr_t) area->start + asize, BASE_ALIGN); 289 290 /* Check for overflow */ 291 if (end < area->start) 178 292 return false; 179 180 if ((heap_start + size < heap_start) || (heap_end + size < heap_end)) 293 294 /* Resize the address space area */ 295 int ret = as_area_resize(area->start, asize, 0); 296 if (ret != EOK) 181 297 return false; 182 298 183 size_t heap_size = (size_t) (heap_end - heap_start); 184 185 if ((max_heap_size != (size_t) -1) && (heap_size + size > max_heap_size)) 186 return false; 187 188 size_t pages = (size - 1) / PAGE_SIZE + 1; 189 190 if (as_area_resize((void *) &_heap, (heap_pages + pages) * PAGE_SIZE, 0) 191 == EOK) { 192 void *end = (void *) ALIGN_DOWN(((uintptr_t) &_heap) + 193 (heap_pages + pages) * PAGE_SIZE, BASE_ALIGN); 194 block_init(heap_end, end - heap_end, true); 195 heap_pages += pages; 196 heap_end = end; 299 /* Add new free block */ 300 block_init(area->end, (size_t) (end - area->end), true, area); 301 302 /* Update heap area parameters */ 303 area->end = end; 304 305 return true; 306 } 307 308 /** Try to enlarge any of the heap areas 309 * 310 * @param size Gross size of item to allocate (bytes). 311 * 312 */ 313 static bool heap_grow(size_t size) 314 { 315 if (size == 0) 197 316 return true; 198 } 199 200 return false; 201 } 202 203 /** Decrease the heap area 204 * 205 * Should be called only inside the critical section. 206 * 207 * @param size Number of bytes to shrink the heap by. 208 * 209 */ 210 static void shrink_heap(void) 211 { 212 // TODO 317 318 /* First try to enlarge some existing area */ 319 heap_area_t *area; 320 for (area = first_heap_area; area != NULL; area = area->next) { 321 if (area_grow(area, size)) 322 return true; 323 } 324 325 /* Eventually try to create a new area */ 326 return area_create(AREA_FIRST_BLOCK(size)); 327 } 328 329 /** Try to shrink heap space 330 * 331 * In all cases the next pointer is reset. 332 * 333 */ 334 static void heap_shrink(void) 335 { 336 next = NULL; 213 337 } 214 338 215 339 /** Initialize the heap allocator 216 340 * 217 * Find how much physical memory we have and create 218 * the heap management structures that mark the whole 219 * physical memory as a single free block. 220 * 221 */ 222 void __heap_init(void) 223 { 224 futex_down(&malloc_futex); 225 226 if (as_area_create((void *) &_heap, PAGE_SIZE, 227 AS_AREA_WRITE | AS_AREA_READ)) { 228 heap_pages = 1; 229 heap_start = (void *) ALIGN_UP((uintptr_t) &_heap, BASE_ALIGN); 230 heap_end = 231 (void *) ALIGN_DOWN(((uintptr_t) &_heap) + PAGE_SIZE, BASE_ALIGN); 232 233 /* Make the entire area one large block. */ 234 block_init(heap_start, heap_end - heap_start, true); 235 } 236 237 futex_up(&malloc_futex); 238 } 239 240 /** Get maximum heap address 241 * 242 */ 243 uintptr_t get_max_heap_addr(void) 244 { 245 futex_down(&malloc_futex); 246 247 if (max_heap_size == (size_t) -1) 248 max_heap_size = 249 max((size_t) (heap_end - heap_start), MAX_HEAP_SIZE); 250 251 uintptr_t max_heap_addr = (uintptr_t) heap_start + max_heap_size; 252 253 futex_up(&malloc_futex); 254 255 return max_heap_addr; 341 * Create initial heap memory area. This routine is 342 * only called from libc initialization, thus we do not 343 * take any locks. 344 * 345 */ 346 void __malloc_init(void) 347 { 348 if (!area_create(PAGE_SIZE)) 349 abort(); 256 350 } 257 351 … … 275 369 /* Block big enough -> split. */ 276 370 void *next = ((void *) cur) + size; 277 block_init(next, cur->size - size, true );278 block_init(cur, size, false );371 block_init(next, cur->size - size, true, cur->area); 372 block_init(cur, size, false, cur->area); 279 373 } else { 280 374 /* Block too small -> use as is. */ … … 283 377 } 284 378 285 /** Allocate a memoryblock379 /** Allocate memory from heap area starting from given block 286 380 * 287 381 * Should be called only inside the critical section. 288 * 289 * @param size The size of the block to allocate.290 * @param align Memory address alignment.291 * 292 * @ return the address of the block or NULL when not enough memory.293 * 294 * /295 static void *malloc_internal(const size_t size, const size_t align) 296 { 297 if (align == 0) 298 return NULL; 299 300 size_t falign = lcm(align, BASE_ALIGN); 301 size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign)); 302 303 bool grown = false; 304 void *result;305 306 loop: 307 result = NULL;308 heap_block_head_t *cur = (heap_block_head_t *) heap_start;309 310 while ((result == NULL) && ((void *) cur < heap_end)) {382 * As a side effect this function also sets the current 383 * pointer on successful allocation. 384 * 385 * @param area Heap area where to allocate from. 386 * @param first_block Starting heap block. 387 * @param final_block Heap block where to finish the search 388 * (may be NULL). 389 * @param real_size Gross number of bytes to allocate. 390 * @param falign Physical alignment of the block. 391 * 392 * @return Address of the allocated block or NULL on not enough memory. 393 * 394 */ 395 static void *malloc_area(heap_area_t *area, heap_block_head_t *first_block, 396 heap_block_head_t *final_block, size_t real_size, size_t falign) 397 { 398 area_check((void *) area); 399 assert((void *) first_block >= (void *) AREA_FIRST_BLOCK(area)); 400 assert((void *) first_block < area->end); 401 402 heap_block_head_t *cur; 403 for (cur = first_block; (void *) cur < area->end; 404 cur = (heap_block_head_t *) (((void *) cur) + cur->size)) { 311 405 block_check(cur); 406 407 /* Finish searching on the final block */ 408 if ((final_block != NULL) && (cur == final_block)) 409 break; 312 410 313 411 /* Try to find a block that is free and large enough. */ 314 412 if ((cur->free) && (cur->size >= real_size)) { 315 /* We have found a suitable block. 316 Check for alignment properties. */ 317 void *addr = ((void *) cur) + sizeof(heap_block_head_t); 318 void *aligned = (void *) ALIGN_UP(addr, falign); 413 /* 414 * We have found a suitable block. 415 * Check for alignment properties. 416 */ 417 void *addr = (void *) 418 ((uintptr_t) cur + sizeof(heap_block_head_t)); 419 void *aligned = (void *) 420 ALIGN_UP((uintptr_t) addr, falign); 319 421 320 422 if (addr == aligned) { 321 423 /* Exact block start including alignment. */ 322 424 split_mark(cur, real_size); 323 result = addr; 425 426 next = cur; 427 return addr; 324 428 } else { 325 429 /* Block start has to be aligned */ … … 327 431 328 432 if (cur->size >= real_size + excess) { 329 /* The current block is large enough to fit 330 data in including alignment */ 331 if ((void *) cur > heap_start) { 332 /* There is a block before the current block. 333 This previous block can be enlarged to compensate 334 for the alignment excess */ 335 heap_block_foot_t *prev_foot = 336 ((void *) cur) - sizeof(heap_block_foot_t); 433 /* 434 * The current block is large enough to fit 435 * data in (including alignment). 436 */ 437 if ((void *) cur > (void *) AREA_FIRST_BLOCK(area)) { 438 /* 439 * There is a block before the current block. 440 * This previous block can be enlarged to 441 * compensate for the alignment excess. 442 */ 443 heap_block_foot_t *prev_foot = (heap_block_foot_t *) 444 ((void *) cur - sizeof(heap_block_foot_t)); 337 445 338 heap_block_head_t *prev_head = 339 ( heap_block_head_t *) (((void *) cur)- prev_foot->size);446 heap_block_head_t *prev_head = (heap_block_head_t *) 447 ((void *) cur - prev_foot->size); 340 448 341 449 block_check(prev_head); … … 344 452 heap_block_head_t *next_head = ((void *) cur) + excess; 345 453 346 if ((!prev_head->free) && (excess >= STRUCT_OVERHEAD)) { 347 /* The previous block is not free and there is enough 348 space to fill in a new free block between the previous 349 and current block */ 350 block_init(cur, excess, true); 454 if ((!prev_head->free) && 455 (excess >= STRUCT_OVERHEAD)) { 456 /* 457 * The previous block is not free and there 458 * is enough free space left to fill in 459 * a new free block between the previous 460 * and current block. 461 */ 462 block_init(cur, excess, true, area); 351 463 } else { 352 /* The previous block is free (thus there is no need to 353 induce additional fragmentation to the heap) or the 354 excess is small, thus just enlarge the previous block */ 355 block_init(prev_head, prev_head->size + excess, prev_head->free); 464 /* 465 * The previous block is free (thus there 466 * is no need to induce additional 467 * fragmentation to the heap) or the 468 * excess is small. Therefore just enlarge 469 * the previous block. 470 */ 471 block_init(prev_head, prev_head->size + excess, 472 prev_head->free, area); 356 473 } 357 474 358 block_init(next_head, reduced_size, true );475 block_init(next_head, reduced_size, true, area); 359 476 split_mark(next_head, real_size); 360 result = aligned; 361 cur = next_head; 477 478 next = next_head; 479 return aligned; 362 480 } else { 363 /* The current block is the first block on the heap. 364 We have to make sure that the alignment excess 365 is large enough to fit a new free block just 366 before the current block */ 481 /* 482 * The current block is the first block 483 * in the heap area. We have to make sure 484 * that the alignment excess is large enough 485 * to fit a new free block just before the 486 * current block. 487 */ 367 488 while (excess < STRUCT_OVERHEAD) { 368 489 aligned += falign; … … 373 494 if (cur->size >= real_size + excess) { 374 495 size_t reduced_size = cur->size - excess; 375 cur = (heap_block_head_t *) (heap_start + excess); 496 cur = (heap_block_head_t *) 497 (AREA_FIRST_BLOCK(area) + excess); 376 498 377 block_init(heap_start, excess, true); 378 block_init(cur, reduced_size, true); 499 block_init((void *) AREA_FIRST_BLOCK(area), excess, 500 true, area); 501 block_init(cur, reduced_size, true, area); 379 502 split_mark(cur, real_size); 380 result = aligned; 503 504 next = cur; 505 return aligned; 381 506 } 382 507 } … … 384 509 } 385 510 } 386 387 /* Advance to the next block. */ 388 cur = (heap_block_head_t *) (((void *) cur) + cur->size); 389 } 390 391 if ((result == NULL) && (!grown)) { 392 if (grow_heap(real_size)) { 393 grown = true; 511 } 512 513 return NULL; 514 } 515 516 /** Allocate a memory block 517 * 518 * Should be called only inside the critical section. 519 * 520 * @param size The size of the block to allocate. 521 * @param align Memory address alignment. 522 * 523 * @return Address of the allocated block or NULL on not enough memory. 524 * 525 */ 526 static void *malloc_internal(const size_t size, const size_t align) 527 { 528 assert(first_heap_area != NULL); 529 530 if (align == 0) 531 return NULL; 532 533 size_t falign = lcm(align, BASE_ALIGN); 534 size_t real_size = GROSS_SIZE(ALIGN_UP(size, falign)); 535 536 bool retry = false; 537 heap_block_head_t *split; 538 539 loop: 540 541 /* Try the next fit approach */ 542 split = next; 543 544 if (split != NULL) { 545 void *addr = malloc_area(split->area, split, NULL, real_size, 546 falign); 547 548 if (addr != NULL) 549 return addr; 550 } 551 552 /* Search the entire heap */ 553 heap_area_t *area; 554 for (area = first_heap_area; area != NULL; area = area->next) { 555 heap_block_head_t *first = (heap_block_head_t *) 556 AREA_FIRST_BLOCK(area); 557 558 void *addr = malloc_area(area, first, split, real_size, 559 falign); 560 561 if (addr != NULL) 562 return addr; 563 } 564 565 if (!retry) { 566 /* Try to grow the heap space */ 567 if (heap_grow(real_size)) { 568 retry = true; 394 569 goto loop; 395 570 } 396 571 } 397 572 398 return result;573 return NULL; 399 574 } 400 575 … … 475 650 (heap_block_head_t *) (addr - sizeof(heap_block_head_t)); 476 651 477 assert((void *) head >= heap_start);478 assert((void *) head < heap_end);479 480 652 block_check(head); 481 653 assert(!head->free); 654 655 heap_area_t *area = head->area; 656 657 area_check(area); 658 assert((void *) head >= (void *) AREA_FIRST_BLOCK(area)); 659 assert((void *) head < area->end); 482 660 483 661 void *ptr = NULL; … … 489 667 /* Shrink */ 490 668 if (orig_size - real_size >= STRUCT_OVERHEAD) { 491 /* Split the original block to a full block 492 and a trailing free block */ 493 block_init((void *) head, real_size, false); 669 /* 670 * Split the original block to a full block 671 * and a trailing free block. 672 */ 673 block_init((void *) head, real_size, false, area); 494 674 block_init((void *) head + real_size, 495 orig_size - real_size, true );496 shrink_heap();675 orig_size - real_size, true, area); 676 heap_shrink(); 497 677 } 498 678 499 679 ptr = ((void *) head) + sizeof(heap_block_head_t); 500 680 } else { 501 /* Look at the next block. If it is free and the size is 502 sufficient then merge the two. Otherwise just allocate 503 a new block, copy the original data into it and 504 free the original block. */ 681 /* 682 * Look at the next block. If it is free and the size is 683 * sufficient then merge the two. Otherwise just allocate 684 * a new block, copy the original data into it and 685 * free the original block. 686 */ 505 687 heap_block_head_t *next_head = 506 688 (heap_block_head_t *) (((void *) head) + head->size); 507 689 508 if (((void *) next_head < heap_end) &&690 if (((void *) next_head < area->end) && 509 691 (head->size + next_head->size >= real_size) && 510 692 (next_head->free)) { 511 693 block_check(next_head); 512 block_init(head, head->size + next_head->size, false );694 block_init(head, head->size + next_head->size, false, area); 513 695 split_mark(head, real_size); 514 696 515 697 ptr = ((void *) head) + sizeof(heap_block_head_t); 698 next = NULL; 516 699 } else 517 700 reloc = true; … … 544 727 = (heap_block_head_t *) (addr - sizeof(heap_block_head_t)); 545 728 546 assert((void *) head >= heap_start);547 assert((void *) head < heap_end);548 549 729 block_check(head); 550 730 assert(!head->free); 731 732 heap_area_t *area = head->area; 733 734 area_check(area); 735 assert((void *) head >= (void *) AREA_FIRST_BLOCK(area)); 736 assert((void *) head < area->end); 551 737 552 738 /* Mark the block itself as free. */ … … 557 743 = (heap_block_head_t *) (((void *) head) + head->size); 558 744 559 if ((void *) next_head < heap_end) {745 if ((void *) next_head < area->end) { 560 746 block_check(next_head); 561 747 if (next_head->free) 562 block_init(head, head->size + next_head->size, true );748 block_init(head, head->size + next_head->size, true, area); 563 749 } 564 750 565 751 /* Look at the previous block. If it is free, merge the two. */ 566 if ((void *) head > heap_start) {752 if ((void *) head > (void *) AREA_FIRST_BLOCK(area)) { 567 753 heap_block_foot_t *prev_foot = 568 754 (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t)); … … 574 760 575 761 if (prev_head->free) 576 block_init(prev_head, prev_head->size + head->size, true); 577 } 578 579 shrink_heap(); 762 block_init(prev_head, prev_head->size + head->size, true, 763 area); 764 } 765 766 heap_shrink(); 580 767 581 768 futex_up(&malloc_futex); -
uspace/lib/c/generic/net/icmp_api.c
r89acf204 r474afc9 41 41 #include <net/modules.h> 42 42 #include <net/ip_codes.h> 43 44 43 #include <async.h> 45 44 #include <sys/types.h> 46 45 #include <sys/time.h> 47 46 #include <errno.h> 48 49 #include <ipc/ipc.h>50 47 #include <ipc/services.h> 51 48 #include <ipc/icmp.h> -
uspace/lib/c/generic/net/modules.c
r89acf204 r474afc9 43 43 #include <errno.h> 44 44 #include <sys/time.h> 45 46 #include <ipc/ipc.h>47 45 #include <ipc/services.h> 48 49 46 #include <net/modules.h> 50 47 … … 67 64 switch (count) { 68 65 case 0: 69 ipc_answer_0(callid, (sysarg_t) result);66 async_answer_0(callid, (sysarg_t) result); 70 67 break; 71 68 case 1: 72 ipc_answer_1(callid, (sysarg_t) result,69 async_answer_1(callid, (sysarg_t) result, 73 70 IPC_GET_ARG1(*answer)); 74 71 break; 75 72 case 2: 76 ipc_answer_2(callid, (sysarg_t) result,73 async_answer_2(callid, (sysarg_t) result, 77 74 IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer)); 78 75 break; 79 76 case 3: 80 ipc_answer_3(callid, (sysarg_t) result,77 async_answer_3(callid, (sysarg_t) result, 81 78 IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer), 82 79 IPC_GET_ARG3(*answer)); 83 80 break; 84 81 case 4: 85 ipc_answer_4(callid, (sysarg_t) result,82 async_answer_4(callid, (sysarg_t) result, 86 83 IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer), 87 84 IPC_GET_ARG3(*answer), IPC_GET_ARG4(*answer)); … … 89 86 case 5: 90 87 default: 91 ipc_answer_5(callid, (sysarg_t) result,88 async_answer_5(callid, (sysarg_t) result, 92 89 IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer), 93 90 IPC_GET_ARG3(*answer), IPC_GET_ARG4(*answer), … … 137 134 sysarg_t arg3, async_client_conn_t client_receiver, suseconds_t timeout) 138 135 { 139 int rc;140 141 136 /* Connect to the needed service */ 142 137 int phone = connect_to_service_timeout(need, timeout); 143 138 if (phone >= 0) { 144 139 /* Request the bidirectional connection */ 145 sysarg_t taskhash; 146 sysarg_t phonehash; 147 148 rc = ipc_connect_to_me(phone, arg1, arg2, arg3, &taskhash, 149 &phonehash); 140 int rc = async_connect_to_me(phone, arg1, arg2, arg3, client_receiver); 150 141 if (rc != EOK) { 151 ipc_hangup(phone);142 async_hangup(phone); 152 143 return rc; 153 144 } 154 async_new_connection(taskhash, phonehash, 0, NULL,155 client_receiver);156 145 } 157 146 -
uspace/lib/c/generic/net/socket_client.c
r89acf204 r474afc9 43 43 #include <stdlib.h> 44 44 #include <errno.h> 45 45 #include <task.h> 46 46 #include <ipc/services.h> 47 47 #include <ipc/socket.h> 48 49 48 #include <net/modules.h> 50 49 #include <net/in.h> … … 278 277 } 279 278 280 ipc_answer_0(callid, (sysarg_t) rc);279 async_answer_0(callid, (sysarg_t) rc); 281 280 goto loop; 282 281 } … … 687 686 688 687 /* Read address */ 689 ipc_data_read_start(socket->phone, cliaddr, *addrlen);688 async_data_read_start(socket->phone, cliaddr, *addrlen); 690 689 fibril_rwlock_write_unlock(&socket_globals.lock); 691 690 async_wait_for(message_id, &ipc_result); -
uspace/lib/c/generic/private/async.h
r89acf204 r474afc9 33 33 */ 34 34 35 #ifndef LIBC_ ASYNC_PRIV_H_36 #define LIBC_ ASYNC_PRIV_H_35 #ifndef LIBC_PRIVATE_ASYNC_H_ 36 #define LIBC_PRIVATE_ASYNC_H_ 37 37 38 38 #include <adt/list.h> … … 51 51 /** If true, we have timed out. */ 52 52 bool occurred; 53 53 54 54 /** Expiration time. */ 55 55 struct timeval expires; … … 65 65 } wu_event_t; 66 66 67 68 67 /** Structures of this type represent a waiting fibril. */ 69 68 typedef struct { … … 73 72 /** If true, this fibril is currently active. */ 74 73 bool active; 75 74 76 75 /** Timeout wait data. */ 77 76 to_event_t to_event; … … 80 79 } awaiter_t; 81 80 82 extern void async_insert_timeout(awaiter_t *wd); 81 extern void __async_init(void); 82 extern void async_insert_timeout(awaiter_t *); 83 83 84 84 #endif -
uspace/lib/c/generic/private/async_sess.h
r89acf204 r474afc9 1 1 /* 2 * Copyright (c) 20 06 Ondrej Palkovsky2 * Copyright (c) 2011 Martin Decky 3 3 * All rights reserved. 4 4 * … … 33 33 */ 34 34 35 #i nclude <stdio.h>36 # include <stdlib.h>35 #ifndef LIBC_PRIVATE_ASYNC_SESS_H_ 36 #define LIBC_PRIVATE_ASYNC_SESS_H_ 37 37 38 /* TODO 39 void errx(int __status, __const char *__format, ...) 40 { 41 _exit(0); 42 } 43 */ 38 extern void __async_sess_init(void); 39 40 #endif 44 41 45 42 /** @} -
uspace/lib/c/generic/thread.c
r89acf204 r474afc9 31 31 */ 32 32 /** @file 33 */ 33 */ 34 34 35 35 #include <thread.h> … … 41 41 #include <str.h> 42 42 #include <async.h> 43 #include "private/thread.h" 43 44 44 45 #ifndef THREAD_INITIAL_STACK_PAGES_NO … … 50 51 * This function is called from __thread_entry() and is used 51 52 * to call the thread's implementing function and perform cleanup 52 * and exit when thread returns back. Do not call this function 53 * directly. 53 * and exit when thread returns back. 54 54 * 55 55 * @param uarg Pointer to userspace argument structure. 56 * 56 57 */ 57 58 void __thread_main(uspace_arg_t *uarg) 58 59 { 59 fibril_t *f; 60 61 f = fibril_setup(); 62 __tcb_set(f->tcb); 63 60 fibril_t *fibril = fibril_setup(); 61 if (fibril == NULL) 62 thread_exit(0); 63 64 __tcb_set(fibril->tcb); 65 64 66 uarg->uspace_thread_function(uarg->uspace_thread_arg); 65 /* XXX: we cannot free the userspace stack while running on it */ 66 // free(uarg->uspace_stack); 67 // free(uarg); 68 67 /* XXX: we cannot free the userspace stack while running on it 68 free(uarg->uspace_stack); 69 free(uarg); 70 */ 71 69 72 /* If there is a manager, destroy it */ 70 73 async_destroy_manager(); 71 fibril_teardown(f );72 74 fibril_teardown(fibril); 75 73 76 thread_exit(0); 74 77 } … … 127 130 * 128 131 * @param status Exit status. Currently not used. 132 * 129 133 */ 130 134 void thread_exit(int status) 131 135 { 132 136 __SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status); 133 for (;;) 134 ; 137 138 /* Unreachable */ 139 while (1); 135 140 } 136 141 -
uspace/lib/c/generic/time.c
r89acf204 r474afc9 34 34 35 35 #include <sys/time.h> 36 #include <unistd.h> 37 #include <ipc/ipc.h> 38 #include <stdio.h> 36 #include <time.h> 37 #include <bool.h> 39 38 #include <arch/barrier.h> 40 #include <unistd.h> 41 #include <atomic.h> 42 #include <sysinfo.h> 43 #include <ipc/services.h> 44 #include <libc.h> 45 39 #include <macros.h> 40 #include <errno.h> 46 41 #include <sysinfo.h> 47 42 #include <as.h> 48 43 #include <ddi.h> 49 50 #include <time.h> 51 52 /* Pointers to public variables with time */ 44 #include <libc.h> 45 46 /** Pointer to kernel shared variables with time */ 53 47 struct { 54 48 volatile sysarg_t seconds1; … … 59 53 /** Add microseconds to given timeval. 60 54 * 61 * @param tv Destination timeval. 62 * @param usecs Number of microseconds to add. 55 * @param tv Destination timeval. 56 * @param usecs Number of microseconds to add. 57 * 63 58 */ 64 59 void tv_add(struct timeval *tv, suseconds_t usecs) … … 66 61 tv->tv_sec += usecs / 1000000; 67 62 tv->tv_usec += usecs % 1000000; 63 68 64 if (tv->tv_usec > 1000000) { 69 65 tv->tv_sec++; … … 74 70 /** Subtract two timevals. 75 71 * 76 * @param tv1 First timeval. 77 * @param tv2 Second timeval. 78 * 79 * @return Return difference between tv1 and tv2 (tv1 - tv2) in 80 * microseconds. 72 * @param tv1 First timeval. 73 * @param tv2 Second timeval. 74 * 75 * @return Difference between tv1 and tv2 (tv1 - tv2) in 76 * microseconds. 77 * 81 78 */ 82 79 suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2) 83 80 { 84 suseconds_t result; 85 86 result = tv1->tv_usec - tv2->tv_usec; 87 result += (tv1->tv_sec - tv2->tv_sec) * 1000000; 88 89 return result; 81 return (tv1->tv_usec - tv2->tv_usec) + 82 ((tv1->tv_sec - tv2->tv_sec) * 1000000); 90 83 } 91 84 92 85 /** Decide if one timeval is greater than the other. 93 86 * 94 * @param t1 First timeval. 95 * @param t2 Second timeval. 96 * 97 * @return Return true tv1 is greater than tv2. Otherwise return 98 * false. 87 * @param t1 First timeval. 88 * @param t2 Second timeval. 89 * 90 * @return True if tv1 is greater than tv2. 91 * @return False otherwise. 92 * 99 93 */ 100 94 int tv_gt(struct timeval *tv1, struct timeval *tv2) 101 95 { 102 96 if (tv1->tv_sec > tv2->tv_sec) 103 return 1; 104 if (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec > tv2->tv_usec) 105 return 1; 106 return 0; 97 return true; 98 99 if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec > tv2->tv_usec)) 100 return true; 101 102 return false; 107 103 } 108 104 109 105 /** Decide if one timeval is greater than or equal to the other. 110 106 * 111 * @param tv1 First timeval. 112 * @param tv2 Second timeval. 113 * 114 * @return Return true if tv1 is greater than or equal to tv2. 115 * Otherwise return false. 107 * @param tv1 First timeval. 108 * @param tv2 Second timeval. 109 * 110 * @return True if tv1 is greater than or equal to tv2. 111 * @return False otherwise. 112 * 116 113 */ 117 114 int tv_gteq(struct timeval *tv1, struct timeval *tv2) 118 115 { 119 116 if (tv1->tv_sec > tv2->tv_sec) 120 return 1; 121 if (tv1->tv_sec == tv2->tv_sec && tv1->tv_usec >= tv2->tv_usec) 122 return 1; 123 return 0; 124 } 125 126 127 /** POSIX gettimeofday 128 * 129 * The time variables are memory mapped(RO) from kernel, which updates 130 * them periodically. As it is impossible to read 2 values atomically, we 131 * use a trick: First read a seconds, then read microseconds, then 132 * read seconds again. If a second elapsed in the meantime, set it to zero. 133 * This provides assurance, that at least the 134 * sequence of subsequent gettimeofday calls is ordered. 117 return true; 118 119 if ((tv1->tv_sec == tv2->tv_sec) && (tv1->tv_usec >= tv2->tv_usec)) 120 return true; 121 122 return false; 123 } 124 125 /** Get time of day 126 * 127 * The time variables are memory mapped (read-only) from kernel which 128 * updates them periodically. 129 * 130 * As it is impossible to read 2 values atomically, we use a trick: 131 * First we read the seconds, then we read the microseconds, then we 132 * read the seconds again. If a second elapsed in the meantime, set 133 * the microseconds to zero. 134 * 135 * This assures that the values returned by two subsequent calls 136 * to gettimeofday() are monotonous. 137 * 135 138 */ 136 139 int gettimeofday(struct timeval *tv, struct timezone *tz) 137 140 { 138 void *mapping; 139 sysarg_t s1, s2; 140 int rights; 141 int res; 142 143 if (!ktime) { 144 mapping = as_get_mappable_page(PAGE_SIZE); 145 /* Get the mapping of kernel clock */ 146 res = ipc_share_in_start_1_1(PHONE_NS, mapping, PAGE_SIZE, 147 SERVICE_MEM_REALTIME, &rights); 148 if (res) { 149 printf("Failed to initialize timeofday memarea\n"); 150 _exit(1); 141 if (ktime == NULL) { 142 uintptr_t faddr; 143 int rc = sysinfo_get_value("clock.faddr", &faddr); 144 if (rc != EOK) { 145 errno = rc; 146 return -1; 151 147 } 152 if (!(rights & AS_AREA_READ)) {153 printf("Received bad rights on time area: %X\n",154 rights);155 as_area_destroy(mapping);156 _exit(1);148 149 void *addr = as_get_mappable_page(PAGE_SIZE); 150 if (addr == NULL) { 151 errno = ENOMEM; 152 return -1; 157 153 } 158 ktime = mapping; 159 } 154 155 rc = physmem_map((void *) faddr, addr, 1, 156 AS_AREA_READ | AS_AREA_CACHEABLE); 157 if (rc != EOK) { 158 as_area_destroy(addr); 159 errno = rc; 160 return -1; 161 } 162 163 ktime = addr; 164 } 165 160 166 if (tz) { 161 167 tz->tz_minuteswest = 0; 162 168 tz->tz_dsttime = DST_NONE; 163 169 } 164 165 s2 = ktime->seconds2; 170 171 sysarg_t s2 = ktime->seconds2; 172 166 173 read_barrier(); 167 174 tv->tv_usec = ktime->useconds; 175 168 176 read_barrier(); 169 s1 = ktime->seconds1; 177 sysarg_t s1 = ktime->seconds1; 178 170 179 if (s1 != s2) { 180 tv->tv_sec = max(s1, s2); 171 181 tv->tv_usec = 0; 172 tv->tv_sec = s1 > s2 ? s1 : s2;173 182 } else 174 183 tv->tv_sec = s1; 175 184 176 185 return 0; 177 186 } … … 180 189 { 181 190 struct timeval tv; 182 183 191 if (gettimeofday(&tv, NULL)) 184 192 return (time_t) -1; 193 185 194 if (tloc) 186 195 *tloc = tv.tv_sec; 196 187 197 return tv.tv_sec; 188 198 } 189 199 190 /** Wait unconditionally for specified number of microseconds */ 200 /** Wait unconditionally for specified number of microseconds 201 * 202 */ 191 203 int usleep(useconds_t usec) 192 204 { … … 195 207 } 196 208 197 /** Wait unconditionally for specified number of seconds */ 209 /** Wait unconditionally for specified number of seconds 210 * 211 */ 198 212 unsigned int sleep(unsigned int sec) 199 213 { 200 /* Sleep in 1000 second steps to support 201 full argument range */ 214 /* 215 * Sleep in 1000 second steps to support 216 * full argument range 217 */ 218 202 219 while (sec > 0) { 203 220 unsigned int period = (sec > 1000) ? 1000 : sec; 204 221 205 222 usleep(period * 1000000); 206 223 sec -= period; 207 224 } 225 208 226 return 0; 209 227 } -
uspace/lib/c/generic/udebug.c
r89acf204 r474afc9 31 31 */ 32 32 /** @file 33 */ 33 */ 34 34 35 35 #include <udebug.h> 36 36 #include <sys/types.h> 37 #include <ipc/ipc.h>38 37 #include <async.h> 39 38 -
uspace/lib/c/generic/vfs/vfs.c
r89acf204 r474afc9 1 1 /* 2 * Copyright (c) 2008 Jakub Jermar 2 * Copyright (c) 2008 Jakub Jermar 3 3 * All rights reserved. 4 4 * … … 43 43 #include <sys/stat.h> 44 44 #include <sys/types.h> 45 #include <ipc/ipc.h>46 45 #include <ipc/services.h> 46 #include <ipc/ns.h> 47 47 #include <async.h> 48 48 #include <fibril_synch.h> … … 118 118 static void vfs_connect(void) 119 119 { 120 while (vfs_phone < 0) { 121 vfs_phone = async_connect_me_to_blocking(PHONE_NS, SERVICE_VFS, 122 0, 0); 123 } 120 while (vfs_phone < 0) 121 vfs_phone = service_connect_blocking(SERVICE_VFS, 0, 0); 124 122 125 123 async_session_create(&vfs_session, vfs_phone, 0);
Note:
See TracChangeset
for help on using the changeset viewer.