Changeset 474afc9 in mainline for uspace/lib/c/generic


Ignore:
Timestamp:
2011-02-04T22:40:13Z (14 years ago)
Author:
Jan Vesely <jano.vesely@…>
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.
Message:

development branch changes

Location:
uspace/lib/c/generic
Files:
5 added
21 edited
2 moved

Legend:

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

    r89acf204 r474afc9  
    4141#include <bitops.h>
    4242#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"
    4644
    4745/** Create address space area.
     
    104102}
    105103
    106 /** Return pointer to some unmapped area, where fits new as_area
     104/** Return pointer to unmapped address space area
    107105 *
    108106 * @param size Requested size of the allocation.
    109107 *
    110  * @return pointer to the beginning
     108 * @return Pointer to the beginning of unmapped address space area.
    111109 *
    112110 */
    113111void *as_get_mappable_page(size_t size)
    114112{
    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);
    129115}
    130116
  • uspace/lib/c/generic/async.c

    r89acf204 r474afc9  
    4343 * framework will automatically take care of most synchronization problems.
    4444 *
    45  * Default semantics:
    46  * - async_send_*(): Send asynchronously. If the kernel refuses to send
    47  *                   more messages, [ try to get responses from kernel, if
    48  *                   nothing found, might try synchronous ]
    49  *
    5045 * Example of use (pseudo C):
    5146 *
     
    5853 *   int fibril1(void *arg)
    5954 *   {
    60  *     conn = ipc_connect_me_to();
     55 *     conn = async_connect_me_to();
    6156 *     c1 = async_send(conn);
    6257 *     c2 = async_send(conn);
     
    7772 *   {
    7873 *     if (want_refuse) {
    79  *       ipc_answer_0(icallid, ELIMIT);
     74 *       async_answer_0(icallid, ELIMIT);
    8075 *       return;
    8176 *     }
    82  *     ipc_answer_0(icallid, EOK);
     77 *     async_answer_0(icallid, EOK);
    8378 *
    8479 *     callid = async_get_call(&call);
    8580 *     somehow_handle_the_call(callid, call);
    86  *     ipc_answer_2(callid, 1, 2, 3);
     81 *     async_answer_2(callid, 1, 2, 3);
    8782 *
    8883 *     callid = async_get_call(&call);
     
    9287 */
    9388
     89#define LIBC_ASYNC_C_
     90#include <ipc/ipc.h>
     91#include <async.h>
     92#undef LIBC_ASYNC_C_
     93
    9494#include <futex.h>
    95 #include <async.h>
    96 #include <async_priv.h>
    9795#include <fibril.h>
    9896#include <stdio.h>
    9997#include <adt/hash_table.h>
    10098#include <adt/list.h>
    101 #include <ipc/ipc.h>
    10299#include <assert.h>
    103100#include <errno.h>
     
    105102#include <arch/barrier.h>
    106103#include <bool.h>
     104#include "private/async.h"
    107105
    108106atomic_t async_futex = FUTEX_INITIALIZER;
     
    124122
    125123/**
    126  * Structures of this type are used to group information about a call and a
    127  * message queue link.
     124 * Structures of this type are used to group information about
     125 * a call and about a message queue link.
    128126 */
    129127typedef struct {
     
    153151        /** Link to the client tracking structure. */
    154152        client_t *client;
    155 
     153       
    156154        /** Messages that should be delivered to this fibril. */
    157155        link_t msg_queue;
     
    170168
    171169/** Identifier of the incoming connection handled by the current fibril. */
    172 fibril_local connection_t *FIBRIL_connection;
     170static fibril_local connection_t *FIBRIL_connection;
    173171
    174172static void *default_client_data_constructor(void)
     
    199197{
    200198        assert(FIBRIL_connection);
    201 
    202199        return FIBRIL_connection->client->data;
    203200}
    204201
    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 */
     210static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
     211{
     212        ipc_answer_0(callid, ENOENT);
     213}
    207214
    208215/**
     
    210217 */
    211218static 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 */
     228static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)
     229{
     230}
    212231
    213232/**
     
    221240static LIST_INITIALIZE(timeout_list);
    222241
    223 #define CLIENT_HASH_TABLE_BUCKETS       32
    224 #define CONN_HASH_TABLE_BUCKETS         32
    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
     245static hash_index_t client_hash(unsigned long key[])
    227246{
    228247        assert(key);
    229         return (((*key) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
     248        return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
    230249}
    231250
    232251static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
    233252{
    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);
    236255}
    237256
     
    254273 *
    255274 */
    256 static hash_index_t conn_hash(unsigned long *key)
     275static hash_index_t conn_hash(unsigned long key[])
    257276{
    258277        assert(key);
    259         return (((*key) >> 4) % CONN_HASH_TABLE_BUCKETS);
     278        return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
    260279}
    261280
     
    271290static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
    272291{
    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
    285296static void conn_remove(link_t *item)
    286297{
    287         free(hash_table_get_instance(item, connection_t, link));
    288 }
    289 
     298}
    290299
    291300/** Operations for the connection hash table. */
     
    308317        link_t *tmp = timeout_list.next;
    309318        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               
    313322                if (tv_gteq(&cur->to_event.expires, &wd->to_event.expires))
    314323                        break;
     324               
    315325                tmp = tmp->next;
    316326        }
     
    329339 *
    330340 * @return False if the call doesn't match any connection.
    331  *         True if the call was passed to the respective connection fibril.
     341 * @return True if the call was passed to the respective connection fibril.
    332342 *
    333343 */
     
    420430       
    421431        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       
    422438        fibril_add_ready(fid);
    423439       
     
    466482                         * the first IPC_M_PHONE_HUNGUP call and continues to
    467483                         * call async_get_call_timeout(). Repeat
    468                          * IPC_M_PHONE_HUNGUP until the caller notices. 
     484                         * IPC_M_PHONE_HUNGUP until the caller notices.
    469485                         */
    470486                        memset(call, 0, sizeof(ipc_call_t));
     
    473489                        return conn->close_callid;
    474490                }
    475 
     491               
    476492                if (usecs)
    477493                        async_insert_timeout(&conn->wdata);
     
    511527}
    512528
    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 
    538529/** Wrapper for client connection fibril.
    539530 *
     
    548539static int connection_fibril(void *arg)
    549540{
    550         unsigned long key;
    551         client_t *cl;
    552         link_t *lnk;
    553         bool destroy = false;
    554 
    555541        /*
    556542         * Setup fibril-local connection pointer.
    557543         */
    558544        FIBRIL_connection = (connection_t *) arg;
    559 
     545       
     546        futex_down(&async_futex);
     547       
    560548        /*
    561549         * Add our reference for the current connection in the client task
     
    563551         * hash in a new tracking structure.
    564552         */
    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       
    568559        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++;
    571562        } else {
    572                 cl = malloc(sizeof(client_t));
    573                 if (!cl) {
     563                client = malloc(sizeof(client_t));
     564                if (!client) {
    574565                        ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
    575566                        futex_up(&async_futex);
    576567                        return 0;
    577568                }
    578                 cl->in_task_hash = FIBRIL_connection->in_task_hash;
     569               
     570                client->in_task_hash = FIBRIL_connection->in_task_hash;
     571               
    579572                async_serialize_start();
    580                 cl->data = async_client_data_create();
     573                client->data = async_client_data_create();
    581574                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       
    585580        futex_up(&async_futex);
    586 
    587         FIBRIL_connection->client = cl;
    588 
     581       
     582        FIBRIL_connection->client = client;
     583       
    589584        /*
    590585         * Call the connection handler function.
     
    596591         * Remove the reference for this client task connection.
    597592         */
     593        bool destroy;
     594       
    598595        futex_down(&async_futex);
    599         if (--cl->refcnt == 0) {
     596       
     597        if (--client->refcnt == 0) {
    600598                hash_table_remove(&client_hash_table, &key, 1);
    601599                destroy = true;
    602         }
     600        } else
     601                destroy = false;
     602       
    603603        futex_up(&async_futex);
    604 
     604       
    605605        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       
    611612        /*
    612613         * Remove myself from the connection hash table.
     
    621622         */
    622623        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               
    627628                list_remove(&msg->link);
    628629                ipc_answer_0(msg->callid, EHANGUP);
     
    637638                ipc_answer_0(FIBRIL_connection->close_callid, EOK);
    638639       
     640        free(FIBRIL_connection);
    639641        return 0;
    640642}
     
    667669                if (callid)
    668670                        ipc_answer_0(callid, ENOMEM);
     671               
    669672                return (uintptr_t) NULL;
    670673        }
     
    684687        conn->wdata.fid = fibril_create(connection_fibril, conn);
    685688       
    686         if (!conn->wdata.fid) {
     689        if (conn->wdata.fid == 0) {
    687690                free(conn);
     691               
    688692                if (callid)
    689693                        ipc_answer_0(callid, ENOMEM);
     694               
    690695                return (uintptr_t) NULL;
    691696        }
     
    714719static void handle_call(ipc_callid_t callid, ipc_call_t *call)
    715720{
    716         /* Unrouted call - do some default behaviour */
     721        /* Unrouted call - take some default action */
    717722        if ((callid & IPC_CALLID_NOTIFICATION)) {
    718723                process_notification(callid, call);
    719                 goto out;
     724                return;
    720725        }
    721726       
     
    723728        case IPC_M_CONNECT_ME:
    724729        case IPC_M_CONNECT_ME_TO:
    725                 /* Open new connection with fibril etc. */
     730                /* Open new connection with fibril, etc. */
    726731                async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call),
    727732                    callid, call, client_connection);
    728                 goto out;
     733                return;
    729734        }
    730735       
    731736        /* Try to route the call through the connection hash table */
    732737        if (route_call(callid, call))
    733                 goto out;
     738                return;
    734739       
    735740        /* Unknown call from unknown phone - hang it up */
    736741        ipc_answer_0(callid, EHANGUP);
    737         return;
    738        
    739 out:
    740         ;
    741742}
    742743
     
    751752        link_t *cur = timeout_list.next;
    752753        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               
    756757                if (tv_gt(&waiter->to_event.expires, &tv))
    757758                        break;
    758 
     759               
    759760                cur = cur->next;
    760 
     761               
    761762                list_remove(&waiter->to_event.link);
    762763                waiter->to_event.inlist = false;
     
    785786        while (true) {
    786787                if (fibril_switch(FIBRIL_FROM_MANAGER)) {
    787                         futex_up(&async_futex); 
     788                        futex_up(&async_futex);
    788789                        /*
    789790                         * async_futex is always held when entering a manager
     
    808809                                continue;
    809810                        } else
    810                                 timeout = tv_sub(&waiter->to_event.expires,
    811                                     &tv);
     811                                timeout = tv_sub(&waiter->to_event.expires, &tv);
    812812                } else
    813813                        timeout = SYNCH_NO_TIMEOUT;
    814814               
    815815                futex_up(&async_futex);
    816 
     816               
    817817                atomic_inc(&threads_in_ipc_wait);
    818818               
     
    822822               
    823823                atomic_dec(&threads_in_ipc_wait);
    824 
     824               
    825825                if (!callid) {
    826826                        handle_expired_timeouts();
     
    861861{
    862862        fid_t fid = fibril_create(async_manager_fibril, NULL);
    863         fibril_add_manager(fid);
     863        if (fid != 0)
     864                fibril_add_manager(fid);
    864865}
    865866
     
    872873/** Initialize the async framework.
    873874 *
    874  * @return Zero on success or an error code.
    875  */
    876 int __async_init(void)
     875 */
     876void __async_init(void)
    877877{
    878878        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();
    887885}
    888886
     
    897895 * @param retval Value returned in the answer.
    898896 * @param data   Call data of the answer.
     897 *
    899898 */
    900899static void reply_received(void *arg, int retval, ipc_call_t *data)
     
    944943    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
    945944{
    946         amsg_t *msg = malloc(sizeof(*msg));
     945        amsg_t *msg = malloc(sizeof(amsg_t));
    947946       
    948947        if (!msg)
     
    953952       
    954953        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         */
    956959        msg->wdata.active = true;
    957960       
     
    984987    ipc_call_t *dataptr)
    985988{
    986         amsg_t *msg = malloc(sizeof(*msg));
     989        amsg_t *msg = malloc(sizeof(amsg_t));
    987990       
    988991        if (!msg)
     
    993996       
    994997        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         */
    9961003        msg->wdata.active = true;
    9971004       
     
    10921099void async_usleep(suseconds_t timeout)
    10931100{
    1094         amsg_t *msg = malloc(sizeof(*msg));
     1101        amsg_t *msg = malloc(sizeof(amsg_t));
    10951102       
    10961103        if (!msg)
     
    12351242}
    12361243
     1244void async_msg_0(int phone, sysarg_t imethod)
     1245{
     1246        ipc_call_async_0(phone, imethod, NULL, NULL, true);
     1247}
     1248
     1249void 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
     1254void 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
     1259void 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
     1265void 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
     1272void 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
     1279sysarg_t async_answer_0(ipc_callid_t callid, sysarg_t retval)
     1280{
     1281        return ipc_answer_0(callid, retval);
     1282}
     1283
     1284sysarg_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
     1289sysarg_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
     1295sysarg_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
     1301sysarg_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
     1307sysarg_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
     1313int 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
     1319int 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 */
     1340int 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
    12371357/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
    1238  * 
     1358 *
    12391359 * Ask through phone for a new connection to some service.
    12401360 *
    1241  * @param phoneid       Phone handle used for contacting the other side.
    1242  * @param arg1          User defined argument.
    1243  * @param arg2          User defined argument.
    1244  * @param arg3          User defined argument.
    1245  *
    1246  * @return              New phone handle on success or a negative error code.
    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 */
     1369int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2,
     1370    sysarg_t arg3)
     1371{
    12521372        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)
    12581377                return rc;
    1259 
     1378       
    12601379        return newphid;
    12611380}
    12621381
    12631382/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
    1264  * 
     1383 *
    12651384 * Ask through phone for a new connection to some service and block until
    12661385 * success.
    12671386 *
    1268  * @param phoneid       Phone handle used for contacting the other side.
    1269  * @param arg1          User defined argument.
    1270  * @param arg2          User defined argument.
    1271  * @param arg3          User defined argument.
    1272  *
    1273  * @return              New phone handle on success or a negative error code.
    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 */
     1395int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
    12771396    sysarg_t arg3)
    12781397{
    1279         int rc;
    12801398        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,
    12831400            IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
    12841401       
    1285         if (rc != EOK) 
     1402        if (rc != EOK)
    12861403                return rc;
    1287 
     1404       
    12881405        return newphid;
    12891406}
    12901407
    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 */
     1411int 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 */
     1423int async_hangup(int phone)
     1424{
     1425        return ipc_hangup(phone);
     1426}
     1427
     1428/** Interrupt one thread of this task from waiting for IPC. */
     1429void 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 *
    13011444 */
    13021445int 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{
    13061448        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,
    13081450            (sysarg_t) size, arg, NULL, &tmp_flags);
     1451       
    13091452        if (flags)
    1310                 *flags = tmp_flags;
     1453                *flags = (unsigned int) tmp_flags;
     1454       
    13111455        return res;
    13121456}
     
    13141458/** Wrapper for receiving the IPC_M_SHARE_IN calls using the async framework.
    13151459 *
    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.
    13181463 *
    13191464 * So far, this wrapper is to be used from within a connection fibril.
    13201465 *
    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 */
     1472bool async_share_in_receive(ipc_callid_t *callid, size_t *size)
     1473{
    13311474        assert(callid);
    13321475        assert(size);
    1333 
     1476       
     1477        ipc_call_t data;
    13341478        *callid = async_get_call(&data);
     1479       
    13351480        if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_IN)
    1336                 return 0;
     1481                return false;
     1482       
    13371483        *size = (size_t) IPC_GET_ARG2(data);
    1338         return 1;
     1484        return true;
    13391485}
    13401486
    13411487/** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework.
    13421488 *
    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 */
     1500int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
    13531501{
    13541502        return ipc_share_in_finalize(callid, src, flags);
    13551503}
    13561504
    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 */
     1514int async_share_out_start(int phoneid, void *src, unsigned int flags)
    13661515{
    13671516        return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
     
    13711520/** Wrapper for receiving the IPC_M_SHARE_OUT calls using the async framework.
    13721521 *
    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.
    13751525 *
    13761526 * So far, this wrapper is to be used from within a connection fibril.
    13771527 *
    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 */
     1535bool async_share_out_receive(ipc_callid_t *callid, size_t *size, unsigned int *flags)
     1536{
    13901537        assert(callid);
    13911538        assert(size);
    13921539        assert(flags);
    1393 
     1540       
     1541        ipc_call_t data;
    13941542        *callid = async_get_call(&data);
     1543       
    13951544        if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_OUT)
    1396                 return 0;
     1545                return false;
     1546       
    13971547        *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;
    14001550}
    14011551
    14021552/** Wrapper for answering the IPC_M_SHARE_OUT calls using the async framework.
    14031553 *
    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 *
    14111563 */
    14121564int async_share_out_finalize(ipc_callid_t callid, void *dst)
     
    14151567}
    14161568
    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 beginning of 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 *
    14251577 */
    14261578int async_data_read_start(int phoneid, void *dst, size_t size)
     
    14321584/** Wrapper for receiving the IPC_M_DATA_READ calls using the async framework.
    14331585 *
    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.
    14361589 *
    14371590 * So far, this wrapper is to be used from within a connection fibril.
    14381591 *
    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 */
     1598bool async_data_read_receive(ipc_callid_t *callid, size_t *size)
     1599{
     1600        assert(callid);
     1601       
    14481602        ipc_call_t data;
    1449        
    1450         assert(callid);
    1451 
    14521603        *callid = async_get_call(&data);
     1604       
    14531605        if (IPC_GET_IMETHOD(data) != IPC_M_DATA_READ)
    1454                 return 0;
     1606                return false;
     1607       
    14551608        if (size)
    14561609                *size = (size_t) IPC_GET_ARG2(data);
    1457         return 1;
     1610       
     1611        return true;
    14581612}
    14591613
    14601614/** Wrapper for answering the IPC_M_DATA_READ calls using the async framework.
    14611615 *
    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 *
    14711627 */
    14721628int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
     
    14761632
    14771633/** Wrapper for forwarding any read request
    1478  *
    14791634 *
    14801635 */
     
    15091664}
    15101665
    1511 /** Wrapper for making IPC_M_DATA_WRITE calls using the async framework.
     1666/** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
    15121667 *
    15131668 * @param phoneid Phone that will be used to contact the receiving side.
     
    15261681/** Wrapper for receiving the IPC_M_DATA_WRITE calls using the async framework.
    15271682 *
    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.
    15301686 *
    15311687 * So far, this wrapper is to be used from within a connection fibril.
    15321688 *
    1533  * @param callid Storage where the hash of the IPC_M_DATA_WRITE call will
    1534  *               be stored.
    1535  * @param size   Storage where the suggested size will be stored. May be
    1536  *               NULL
    1537  *
    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 */
     1695bool async_data_write_receive(ipc_callid_t *callid, size_t *size)
     1696{
     1697        assert(callid);
     1698       
    15431699        ipc_call_t data;
    1544        
    1545         assert(callid);
    1546        
    15471700        *callid = async_get_call(&data);
     1701       
    15481702        if (IPC_GET_IMETHOD(data) != IPC_M_DATA_WRITE)
    1549                 return 0;
     1703                return false;
    15501704       
    15511705        if (size)
    15521706                *size = (size_t) IPC_GET_ARG2(data);
    15531707       
    1554         return 1;
     1708        return true;
    15551709}
    15561710
    15571711/** Wrapper for answering the IPC_M_DATA_WRITE calls using the async framework.
    15581712 *
    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.
    15611716 *
    15621717 * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
     
    16541809 *
    16551810 */
    1656 void async_data_write_void(const int retval)
     1811void async_data_write_void(sysarg_t retval)
    16571812{
    16581813        ipc_callid_t callid;
     
    16621817
    16631818/** Wrapper for forwarding any data that is about to be received
    1664  *
    16651819 *
    16661820 */
  • uspace/lib/c/generic/async_sess.c

    r89acf204 r474afc9  
    9999
    100100#include <async_sess.h>
    101 #include <ipc/ipc.h>
    102101#include <fibril_synch.h>
    103102#include <adt/list.h>
     
    106105#include <errno.h>
    107106#include <assert.h>
     107#include "private/async_sess.h"
    108108
    109109/** An inactive open connection. */
     
    138138 *
    139139 * Needs to be called prior to any other interface in this file.
    140  */
    141 void _async_sess_init(void)
     140 *
     141 */
     142void __async_sess_init(void)
    142143{
    143144        fibril_mutex_initialize(&async_sess_mutex);
     
    200201                list_remove(&conn->global_link);
    201202               
    202                 ipc_hangup(conn->data_phone);
     203                async_hangup(conn->data_phone);
    203204                free(conn);
    204205        }
     
    260261                        data_phone = conn->data_phone;
    261262                        free(conn);
    262                         ipc_hangup(data_phone);
     263                        async_hangup(data_phone);
    263264                        goto retry;
    264265                } else {
     
    292293                 * means that we simply hang up.
    293294                 */
    294                 ipc_hangup(data_phone);
     295                async_hangup(data_phone);
    295296                fibril_mutex_unlock(&async_sess_mutex);
    296297                return;
  • uspace/lib/c/generic/clipboard.c

    r89acf204 r474afc9  
    3939
    4040#include <clipboard.h>
     41#include <ipc/ns.h>
    4142#include <ipc/services.h>
    4243#include <ipc/clipboard.h>
     
    5455{
    5556        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);
    5758}
    5859
  • uspace/lib/c/generic/ddi.c

    r89acf204 r474afc9  
    127127}
    128128
     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 */
     139int 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 */
     153int unregister_irq(int inr, int devno)
     154{
     155        return __SYSCALL2(SYS_UNREGISTER_IRQ, inr, devno);
     156}
     157
    129158/** @}
    130159 */
  • uspace/lib/c/generic/devman.c

    r89acf204 r474afc9  
    2828 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2929 */
    30  
    31  /** @addtogroup libc
     30
     31/** @addtogroup libc
    3232 * @{
    3333 */
     
    3737#include <str.h>
    3838#include <stdio.h>
    39 #include <ipc/ipc.h>
    4039#include <ipc/services.h>
    4140#include <ipc/devman.h>
     
    116115        async_set_client_connection(conn);
    117116       
    118         ipc_connect_to_me(phone, 0, 0, 0, NULL, NULL);
     117        async_connect_to_me(phone, 0, 0, 0, NULL);
    119118        async_wait_for(req, &retval);
    120119       
     
    221220        case DEVMAN_DRIVER:
    222221                if (devman_phone_driver >= 0) {
    223                         ipc_hangup(devman_phone_driver);
     222                        async_hangup(devman_phone_driver);
    224223                        devman_phone_driver = -1;
    225224                }
     
    227226        case DEVMAN_CLIENT:
    228227                if (devman_phone_client >= 0) {
    229                         ipc_hangup(devman_phone_client);
     228                        async_hangup(devman_phone_client);
    230229                        devman_phone_client = -1;
    231230                }
  • uspace/lib/c/generic/devmap.c

    r89acf204 r474afc9  
    2929
    3030#include <str.h>
    31 #include <ipc/ipc.h>
    3231#include <ipc/services.h>
     32#include <ipc/ns.h>
    3333#include <ipc/devmap.h>
    3434#include <devmap.h>
     
    5050               
    5151                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);
    5454                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);
    5757               
    5858                return devmap_phone_driver;
     
    6262               
    6363                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);
    6666                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);
    6969               
    7070                return devmap_phone_client;
     
    7979        case DEVMAP_DRIVER:
    8080                if (devmap_phone_driver >= 0) {
    81                         ipc_hangup(devmap_phone_driver);
     81                        async_hangup(devmap_phone_driver);
    8282                        devmap_phone_driver = -1;
    8383                }
     
    8585        case DEVMAP_CLIENT:
    8686                if (devmap_phone_client >= 0) {
    87                         ipc_hangup(devmap_phone_client);
     87                        async_hangup(devmap_phone_client);
    8888                        devmap_phone_client = -1;
    8989                }
     
    116116        async_set_client_connection(conn);
    117117       
    118         ipc_connect_to_me(phone, 0, 0, 0, NULL, NULL);
     118        async_connect_to_me(phone, 0, 0, 0, NULL);
    119119        async_wait_for(req, &retval);
    120120       
  • uspace/lib/c/generic/event.c

    r89acf204 r474afc9  
    3535 */
    3636/** @file
    37  */ 
     37 */
    3838
    3939#include <libc.h>
    4040#include <event.h>
    4141#include <kernel/ipc/event_types.h>
    42 #include <ipc/ipc.h>
    4342
    4443/** Subscribe for event notifications.
  • uspace/lib/c/generic/fibril_synch.c

    r89acf204 r474afc9  
    3636#include <fibril.h>
    3737#include <async.h>
    38 #include <async_priv.h>
    3938#include <adt/list.h>
    4039#include <futex.h>
     
    4443#include <stacktrace.h>
    4544#include <stdlib.h>
     45#include "private/async.h"
    4646
    4747static void optimize_execution_power(void)
     
    5555         */
    5656        if (atomic_get(&threads_in_ipc_wait) > 0)
    57                 ipc_poke();
     57                async_poke();
    5858}
    5959
     
    105105
    106106        if (fibril_get_sercount() != 0)
    107                 core();
     107                abort();
    108108
    109109        futex_down(&async_futex);
     
    198198       
    199199        if (fibril_get_sercount() != 0)
    200                 core();
     200                abort();
    201201
    202202        futex_down(&async_futex);
     
    226226       
    227227        if (fibril_get_sercount() != 0)
    228                 core();
     228                abort();
    229229
    230230        futex_down(&async_futex);
  • uspace/lib/c/generic/io/io.c

    r89acf204 r474afc9  
    4141#include <bool.h>
    4242#include <malloc.h>
     43#include <async.h>
    4344#include <io/klog.h>
    4445#include <vfs/vfs.h>
    4546#include <ipc/devmap.h>
    4647#include <adt/list.h>
     48#include "../private/io.h"
    4749
    4850static void _ffillbuf(FILE *stream);
     
    322324       
    323325        if (stream->phone >= 0)
    324                 ipc_hangup(stream->phone);
     326                async_hangup(stream->phone);
    325327       
    326328        if (stream->fd >= 0)
  • uspace/lib/c/generic/ipc.c

    r89acf204 r474afc9  
    4545#include <errno.h>
    4646#include <adt/list.h>
    47 #include <stdio.h>
    48 #include <unistd.h>
    4947#include <futex.h>
    50 #include <kernel/synch/synch.h>
    51 #include <async.h>
    5248#include <fibril.h>
    53 #include <assert.h>
    5449
    5550/**
    56  * Structures of this type are used for keeping track of sent asynchronous calls
    57  * and queing unsent calls.
     51 * Structures of this type are used for keeping track
     52 * of sent asynchronous calls and queing unsent calls.
    5853 */
    5954typedef struct {
    6055        link_t list;
    61 
     56       
    6257        ipc_async_callback_t callback;
    6358        void *private;
     59       
    6460        union {
    6561                ipc_callid_t callid;
     
    6965                } msg;
    7066        } u;
    71         fid_t fid;      /**< Fibril waiting for sending this call. */
     67       
     68        /** Fibril waiting for sending this call. */
     69        fid_t fid;
    7270} async_call_t;
    7371
     
    7674/** List of asynchronous calls that were not accepted by kernel.
    7775 *
    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 *
    8079 */
    8180LIST_INITIALIZE(queued_calls);
     
    8382static atomic_t ipc_futex = FUTEX_INITIALIZER;
    8483
    85 /** Make a fast synchronous call.
    86  *
    87  * Only three payload arguments can be passed using this function. However, this
    88  * function is faster than the generic ipc_call_sync_slow() because the payload
    89  * is passed directly in registers.
    90  *
    91  * @param phoneid       Phone handle for the call.
    92  * @param method        Requested method.
    93  * @param arg1          Service-defined payload argument.
    94  * @param arg2          Service-defined payload argument.
    95  * @param arg3          Service-defined payload argument.
    96  * @param result1       If non-NULL, the return ARG1 will be stored there.
    97  * @param result2       If non-NULL, the return ARG2 will be stored there.
    98  * @param result3       If non-NULL, the return ARG3 will be stored there.
    99  * @param result4       If non-NULL, the return ARG4 will be stored there.
    100  * @param result5       If non-NULL, the return ARG5 will be stored there.
    101  *
    102  * @return              Negative values represent errors returned by IPC.
    103  *                      Otherwise the RETVAL of the answer is returned.
    104  */
    105 int
    106 ipc_call_sync_fast(int phoneid, sysarg_t method, sysarg_t arg1, sysarg_t arg2,
    107     sysarg_t arg3, sysarg_t *result1, sysarg_t *result2, sysarg_t *result3,
    108     sysarg_t *result4, 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 */
     105int 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)
    109108{
    110109        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,
    114111            arg2, arg3, (sysarg_t) &resdata);
    115112        if (callres)
    116113                return callres;
     114       
    117115        if (result1)
    118116                *result1 = IPC_GET_ARG1(resdata);
     
    125123        if (result5)
    126124                *result5 = IPC_GET_ARG5(resdata);
    127 
     125       
    128126        return IPC_GET_RETVAL(resdata);
    129127}
    130128
    131 /** Make a synchronous call transmitting 5 arguments of payload.
     129/** Synchronous call transmitting 5 arguments of payload.
    132130 *
    133131 * @param phoneid Phone handle for the call.
     
    144142 * @param result5 If non-NULL, storage for the fifth return argument.
    145143 *
    146  * @return Negative value means IPC error.
    147  *         Otherwise the RETVAL of the answer.
    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 *result2, 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 */
     148int 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)
    154152{
    155153        ipc_call_t data;
     
    181179}
    182180
    183 /** Syscall to send asynchronous message.
     181/** Send asynchronous message via syscall.
    184182 *
    185183 * @param phoneid Phone handle for the call.
     
    189187 *
    190188 */
    191 static ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data)
     189static ipc_callid_t ipc_call_async_internal(int phoneid, ipc_call_t *data)
    192190{
    193191        return __SYSCALL2(SYS_IPC_CALL_ASYNC_SLOW, phoneid, (sysarg_t) data);
    194192}
    195193
    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 *
    202201 */
    203202static inline async_call_t *ipc_prepare_async(void *private,
    204203    ipc_async_callback_t callback)
    205204{
    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));
    209207        if (!call) {
    210208                if (callback)
    211209                        callback(private, ENOMEM, NULL);
     210               
    212211                return NULL;
    213212        }
     213       
    214214        call->callback = callback;
    215215        call->private = private;
    216 
     216       
    217217        return call;
    218218}
    219219
    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 *
    227228 */
    228229static 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 */
    232234                futex_up(&ipc_futex);
    233235                return;
    234236        }
    235 
     237       
    236238        if (callid == (ipc_callid_t) IPC_CALLRET_FATAL) {
    237239                futex_up(&ipc_futex);
     240               
    238241                /* Call asynchronous handler with error code */
    239242                if (call->callback)
    240243                        call->callback(call->private, ENOENT, NULL);
     244               
    241245                free(call);
    242246                return;
    243247        }
    244 
     248       
    245249        if (callid == (ipc_callid_t) IPC_CALLRET_TEMPORARY) {
    246250                futex_up(&ipc_futex);
    247 
     251               
    248252                call->u.msg.phoneid = phoneid;
    249253               
    250254                futex_down(&async_futex);
    251255                list_append(&call->list, &queued_calls);
    252 
     256               
    253257                if (can_preempt) {
    254258                        call->fid = fibril_get_id();
     
    259263                        futex_up(&async_futex);
    260264                }
     265               
    261266                return;
    262267        }
     268       
    263269        call->u.callid = callid;
     270       
    264271        /* Add call to the list of dispatched calls */
    265272        list_append(&call->list, &dispatched_calls);
    266273        futex_up(&ipc_futex);
    267        
    268 }
    269 
    270 /** Make a fast asynchronous call.
     274}
     275
     276/** Fast asynchronous call.
    271277 *
    272278 * This function can only handle four arguments of payload. It is, however,
     
    274280 *
    275281 * 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.
    279286 *
    280287 * @param phoneid     Phone handle for the call.
     
    286293 * @param private     Argument to be passed to the answer/error callback.
    287294 * @param callback    Answer or error callback.
    288  * @param can_preempt If non-zero, the current fibril will be preempted in
     295 * @param can_preempt If true, the current fibril will be preempted in
    289296 *                    case the kernel temporarily refuses to accept more
    290297 *                    asynchronous calls.
     
    293300void ipc_call_async_fast(int phoneid, sysarg_t imethod, sysarg_t arg1,
    294301    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, void *private,
    295     ipc_async_callback_t callback, int can_preempt)
     302    ipc_async_callback_t callback, bool can_preempt)
    296303{
    297304        async_call_t *call = NULL;
     
    304311       
    305312        /*
    306          * We need to make sure that we get callid before another thread
    307          * accesses the queue again.
     313         * We need to make sure that we get callid
     314         * before another thread accesses the queue again.
    308315         */
     316       
    309317        futex_down(&ipc_futex);
    310318        ipc_callid_t callid = __SYSCALL6(SYS_IPC_CALL_ASYNC_FAST, phoneid,
     
    317325                                return;
    318326                }
     327               
    319328                IPC_SET_IMETHOD(call->u.msg.data, imethod);
    320329                IPC_SET_ARG1(call->u.msg.data, arg1);
     
    322331                IPC_SET_ARG3(call->u.msg.data, arg3);
    323332                IPC_SET_ARG4(call->u.msg.data, arg4);
     333               
    324334                /*
    325335                 * To achieve deterministic behavior, we always zero out the
    326336                 * arguments that are beyond the limits of the fast version.
    327337                 */
     338               
    328339                IPC_SET_ARG5(call->u.msg.data, 0);
    329340        }
     341       
    330342        ipc_finish_async(callid, phoneid, call, can_preempt);
    331343}
    332344
    333 /** Make an asynchronous call transmitting the entire payload.
     345/** Asynchronous call transmitting the entire payload.
    334346 *
    335347 * 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.
    339352 *
    340353 * @param phoneid     Phone handle for the call.
     
    347360 * @param private     Argument to be passed to the answer/error callback.
    348361 * @param callback    Answer or error callback.
    349  * @param can_preempt If non-zero, the current fibril will be preempted in
     362 * @param can_preempt If true, the current fibril will be preempted in
    350363 *                    case the kernel temporarily refuses to accept more
    351364 *                    asynchronous calls.
     
    354367void ipc_call_async_slow(int phoneid, sysarg_t imethod, sysarg_t arg1,
    355368    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);
    362372        if (!call)
    363373                return;
    364 
     374       
    365375        IPC_SET_IMETHOD(call->u.msg.data, imethod);
    366376        IPC_SET_ARG1(call->u.msg.data, arg1);
     
    369379        IPC_SET_ARG4(call->u.msg.data, arg4);
    370380        IPC_SET_ARG5(call->u.msg.data, arg5);
     381       
    371382        /*
    372          * We need to make sure that we get callid before another thread
    373          * accesses the queue again.
     383         * We need to make sure that we get callid
     384         * before another threadaccesses the queue again.
    374385         */
     386       
    375387        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       
    378391        ipc_finish_async(callid, phoneid, call, can_preempt);
    379392}
    380393
    381 
    382 /** Answer a received call - fast version.
     394/** Answer received call (fast version).
    383395 *
    384396 * The fast answer makes use of passing retval and first four arguments in
    385397 * registers. If you need to return more, use the ipc_answer_slow() instead.
    386398 *
    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 *
    395409 */
    396410sysarg_t ipc_answer_fast(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     
    401415}
    402416
    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 *
    414430 */
    415431sysarg_t ipc_answer_slow(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
     
    417433{
    418434        ipc_call_t data;
    419 
     435       
    420436        IPC_SET_RETVAL(data, retval);
    421437        IPC_SET_ARG1(data, arg1);
     
    424440        IPC_SET_ARG4(data, arg4);
    425441        IPC_SET_ARG5(data, arg5);
    426 
     442       
    427443        return __SYSCALL2(SYS_IPC_ANSWER_SLOW, callid, (sysarg_t) &data);
    428444}
    429445
    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 */
     449static void dispatch_queued_calls(void)
     450{
    437451        /** @todo
    438          * Integrate intelligently ipc_futex, so that it is locked during
    439          * 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.
    440454         */
     455       
    441456        futex_down(&async_futex);
     457       
    442458        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)
    447465                        break;
    448                 }
     466               
    449467                list_remove(&call->list);
    450 
     468               
    451469                futex_up(&async_futex);
     470               
    452471                if (call->fid)
    453472                        fibril_add_ready(call->fid);
     
    456475                        if (call->callback)
    457476                                call->callback(call->private, ENOENT, NULL);
     477                       
    458478                        free(call);
    459479                } else {
    460480                        call->u.callid = callid;
     481                       
    461482                        futex_down(&ipc_futex);
    462483                        list_append(&call->list, &dispatched_calls);
    463484                        futex_up(&ipc_futex);
    464485                }
     486               
    465487                futex_down(&async_futex);
    466488        }
     489       
    467490        futex_up(&async_futex);
    468491}
    469492
    470 /** Handle a received answer.
     493/** Handle received answer.
    471494 *
    472495 * Find the hash of the answer and call the answer callback.
    473496 *
    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 *
    480505 */
    481506static void handle_answer(ipc_callid_t callid, ipc_call_t *data)
    482507{
     508        callid &= ~IPC_CALLID_ANSWERED;
     509       
     510        futex_down(&ipc_futex);
     511       
    483512        link_t *item;
    484         async_call_t *call;
    485 
    486         callid &= ~IPC_CALLID_ANSWERED;
    487        
    488         futex_down(&ipc_futex);
    489513        for (item = dispatched_calls.next; item != &dispatched_calls;
    490514            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               
    492518                if (call->u.callid == callid) {
    493519                        list_remove(&call->list);
     520                       
    494521                        futex_up(&ipc_futex);
     522                       
    495523                        if (call->callback)
    496                                 call->callback(call->private, 
     524                                call->callback(call->private,
    497525                                    IPC_GET_RETVAL(*data), data);
     526                       
    498527                        free(call);
    499528                        return;
    500529                }
    501530        }
     531       
    502532        futex_up(&ipc_futex);
    503533}
    504534
    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 microseconds
    510  * @param flags         Flags passed to SYS_IPC_WAIT (blocking, nonblocking).
    511  *
    512  * @return              Hash of the call. Note that certain bits have special
    513  *                      meaning. IPC_CALLID_ANSWERED will be set in an answer
    514  *                      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 */
     546ipc_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       
    522552        /* Handle received answers */
    523553        if (callid & IPC_CALLID_ANSWERED) {
    524554                handle_answer(callid, call);
    525                 try_dispatch_queued_calls();
     555                dispatch_queued_calls();
    526556        }
    527 
     557       
    528558        return callid;
    529559}
    530560
    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 */
     564void 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 */
     579ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, sysarg_t usec)
    541580{
    542581        ipc_callid_t callid;
    543 
     582       
    544583        do {
    545584                callid = ipc_wait_cycle(call, usec, SYNCH_FLAGS_NONE);
    546585        } while (callid & IPC_CALLID_ANSWERED);
    547 
     586       
    548587        return callid;
    549588}
     
    551590/** Check if there is an IPC call waiting to be picked up.
    552591 *
    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 *
    555598 */
    556599ipc_callid_t ipc_trywait_for_call(ipc_call_t *call)
    557600{
    558601        ipc_callid_t callid;
    559 
     602       
    560603        do {
    561604                callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT,
    562605                    SYNCH_FLAGS_NON_BLOCKING);
    563606        } while (callid & IPC_CALLID_ANSWERED);
    564 
     607       
    565608        return callid;
    566609}
    567610
    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 */
     627int ipc_connect_to_me(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3,
    590628    sysarg_t *taskhash, sysarg_t *phonehash)
    591629{
     
    594632}
    595633
    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 */
     644int ipc_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
    606645{
    607646        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,
    611648            NULL, NULL, NULL, NULL, &newphid);
    612649        if (res)
    613650                return res;
     651       
    614652        return newphid;
    615653}
    616654
    617 /** Ask through phone for a new connection to some service.
     655/** Request new connection (blocking)
    618656 *
    619657 * 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 */
     669int ipc_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
     670    sysarg_t arg3)
    630671{
    631672        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,
    635674            IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
    636675        if (res)
    637676                return res;
     677       
    638678        return newphid;
    639679}
     
    641681/** Hang up a phone.
    642682 *
    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 *
    646687 */
    647688int ipc_hangup(int phoneid)
     
    650691}
    651692
    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 
    679693/** 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.
    680699 *
    681700 * @param callid  Hash of the call to forward.
     
    688707 * @return Zero on success or an error code.
    689708 *
    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 */
     710int ipc_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
     711    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
    697712{
    698713        return __SYSCALL6(SYS_IPC_FORWARD_FAST, callid, phoneid, imethod, arg1,
     
    700715}
    701716
    702 
    703 int ipc_forward_slow(ipc_callid_t callid, int phoneid, int imethod,
     717int ipc_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
    704718    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
    705     int mode)
     719    unsigned int mode)
    706720{
    707721        ipc_call_t data;
     
    714728        IPC_SET_ARG5(data, arg5);
    715729       
    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 *
    729744 */
    730745int ipc_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
    731     int *flags)
     746    unsigned int *flags)
    732747{
    733748        sysarg_t tmp_flags = 0;
     
    736751       
    737752        if (flags)
    738                 *flags = tmp_flags;
     753                *flags = (unsigned int) tmp_flags;
    739754       
    740755        return res;
     
    743758/** Wrapper for answering the IPC_M_SHARE_IN calls.
    744759 *
    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 */
     771int ipc_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
    755772{
    756773        return ipc_answer_2(callid, EOK, (sysarg_t) src, (sysarg_t) flags);
    757774}
    758775
    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 */
     785int ipc_share_out_start(int phoneid, void *src, unsigned int flags)
    768786{
    769787        return ipc_call_sync_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
     
    773791/** Wrapper for answering the IPC_M_SHARE_OUT calls.
    774792 *
    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 *
    782802 */
    783803int ipc_share_out_finalize(ipc_callid_t callid, void *dst)
     
    786806}
    787807
    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 beginning of 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 *
    796816 */
    797817int ipc_data_read_start(int phoneid, void *dst, size_t size)
     
    803823/** Wrapper for answering the IPC_M_DATA_READ calls.
    804824 *
    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 *
    814836 */
    815837int ipc_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
     
    818840}
    819841
    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 *
    827850 */
    828851int ipc_data_write_start(int phoneid, const void *src, size_t size)
     
    834857/** Wrapper for answering the IPC_M_DATA_WRITE calls.
    835858 *
    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 *
    844869 */
    845870int ipc_data_write_finalize(ipc_callid_t callid, void *dst, size_t size)
  • uspace/lib/c/generic/libc.c

    r89acf204 r474afc9  
    4242
    4343#include <libc.h>
    44 #include <stdio.h>
    45 #include <unistd.h>
    46 #include <malloc.h>
     44#include <stdlib.h>
    4745#include <tls.h>
    48 #include <thread.h>
    4946#include <fibril.h>
    50 #include <ipc/ipc.h>
    51 #include <async.h>
    52 #include <as.h>
     47#include <task.h>
    5348#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"
    5454
    55 extern int main(int argc, char *argv[]);
    56 
    57 void _exit(int status)
    58 {
    59         thread_exit(status);
    60 }
     55static bool env_setup = false;
    6156
    6257void __main(void *pcb_ptr)
    6358{
    6459        /* Initialize user task run-time environment */
    65         __heap_init();
     60        __malloc_init();
    6661        __async_init();
     62        __async_sess_init();
     63       
    6764        fibril_t *fibril = fibril_setup();
     65        if (fibril == NULL)
     66                abort();
     67       
    6868        __tcb_set(fibril->tcb);
    6969       
     
    7171        __pcb = (pcb_t *) pcb_ptr;
    7272       
     73        /* The basic run-time environment is setup */
     74        env_setup = true;
     75       
    7376        int argc;
    7477        char **argv;
    7578       
    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         */
    7883        if (__pcb == NULL) {
    7984                argc = 0;
     
    8792        }
    8893       
    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);
    92100}
    93101
    94 void __exit(void)
     102void exit(int status)
    95103{
    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
     116void abort(void)
     117{
     118        __SYSCALL1(SYS_TASK_EXIT, true);
     119       
     120        /* Unreachable */
     121        while (1);
    99122}
    100123
  • uspace/lib/c/generic/loader.c

    r89acf204 r474afc9  
    3333 */
    3434
    35 #include <ipc/ipc.h>
    3635#include <ipc/loader.h>
    3736#include <ipc/services.h>
     37#include <ipc/ns.h>
    3838#include <libc.h>
    3939#include <task.h>
     
    6363loader_t *loader_connect(void)
    6464{
    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);
    6666        if (phone_id < 0)
    6767                return NULL;
     
    319319                return rc;
    320320       
    321         ipc_hangup(ldr->phone_id);
     321        async_hangup(ldr->phone_id);
    322322        ldr->phone_id = 0;
    323323        return EOK;
     
    337337void loader_abort(loader_t *ldr)
    338338{
    339         ipc_hangup(ldr->phone_id);
     339        async_hangup(ldr->phone_id);
    340340        ldr->phone_id = 0;
    341341}
  • uspace/lib/c/generic/malloc.c

    r89acf204 r474afc9  
    4545#include <futex.h>
    4646#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 */
    5664#define BASE_ALIGN  16
    5765
    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 *
    7074 */
    7175#define GROSS_SIZE(size)  ((size) + STRUCT_OVERHEAD)
    7276
    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 *
    7581 */
    7682#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 */
     105typedef 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;
    77122
    78123/** Header of a heap block
     
    86131        bool free;
    87132       
     133        /** Heap area this block belongs to */
     134        heap_area_t *area;
     135       
    88136        /* A magic value to detect overwrite of heap header */
    89137        uint32_t magic;
     
    101149} heap_block_foot_t;
    102150
    103 /** Linker heap symbol */
    104 extern char _heap;
     151/** First heap area */
     152static heap_area_t *first_heap_area = NULL;
     153
     154/** Last heap area */
     155static heap_area_t *last_heap_area = NULL;
     156
     157/** Next heap block to examine (next fit algorithm) */
     158static heap_block_head_t *next = NULL;
    105159
    106160/** Futex for thread-safe heap manipulation */
    107161static futex_t malloc_futex = FUTEX_INITIALIZER;
    108162
    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 
    121163/** Initialize a heap block
    122164 *
    123  * Fills in the structures related to a heap block.
     165 * Fill in the structures related to a heap block.
    124166 * Should be called only inside the critical section.
    125167 *
     
    127169 * @param size Size of the block including the header and the footer.
    128170 * @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 */
     174static void block_init(void *addr, size_t size, bool free, heap_area_t *area)
    132175{
    133176        /* Calculate the position of the header and the footer */
    134177        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));
    137178       
    138179        head->size = size;
    139180        head->free = free;
     181        head->area = area;
    140182        head->magic = HEAP_BLOCK_HEAD_MAGIC;
     183       
     184        heap_block_foot_t *foot = BLOCK_FOOT(head);
    141185       
    142186        foot->size = size;
     
    159203        assert(head->magic == HEAP_BLOCK_HEAD_MAGIC);
    160204       
    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);
    163206       
    164207        assert(foot->magic == HEAP_BLOCK_FOOT_MAGIC);
     
    166209}
    167210
    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 */
     216static 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 */
     232static 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 */
     276static bool area_grow(heap_area_t *area, size_t size)
    176277{
    177278        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)
    178292                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)
    181297                return false;
    182298       
    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 */
     313static bool heap_grow(size_t size)
     314{
     315        if (size == 0)
    197316                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 */
     334static void heap_shrink(void)
     335{
     336        next = NULL;
    213337}
    214338
    215339/** Initialize the heap allocator
    216340 *
    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 */
     346void __malloc_init(void)
     347{
     348        if (!area_create(PAGE_SIZE))
     349                abort();
    256350}
    257351
     
    275369                /* Block big enough -> split. */
    276370                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);
    279373        } else {
    280374                /* Block too small -> use as is. */
     
    283377}
    284378
    285 /** Allocate a memory block
     379/** Allocate memory from heap area starting from given block
    286380 *
    287381 * 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 */
     395static 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)) {
    311405                block_check(cur);
     406               
     407                /* Finish searching on the final block */
     408                if ((final_block != NULL) && (cur == final_block))
     409                        break;
    312410               
    313411                /* Try to find a block that is free and large enough. */
    314412                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);
    319421                       
    320422                        if (addr == aligned) {
    321423                                /* Exact block start including alignment. */
    322424                                split_mark(cur, real_size);
    323                                 result = addr;
     425                               
     426                                next = cur;
     427                                return addr;
    324428                        } else {
    325429                                /* Block start has to be aligned */
     
    327431                               
    328432                                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));
    337445                                               
    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);
    340448                                               
    341449                                                block_check(prev_head);
     
    344452                                                heap_block_head_t *next_head = ((void *) cur) + excess;
    345453                                               
    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);
    351463                                                } 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);
    356473                                                }
    357474                                               
    358                                                 block_init(next_head, reduced_size, true);
     475                                                block_init(next_head, reduced_size, true, area);
    359476                                                split_mark(next_head, real_size);
    360                                                 result = aligned;
    361                                                 cur = next_head;
     477                                               
     478                                                next = next_head;
     479                                                return aligned;
    362480                                        } 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                                                 */
    367488                                                while (excess < STRUCT_OVERHEAD) {
    368489                                                        aligned += falign;
     
    373494                                                if (cur->size >= real_size + excess) {
    374495                                                        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);
    376498                                                       
    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);
    379502                                                        split_mark(cur, real_size);
    380                                                         result = aligned;
     503                                                       
     504                                                        next = cur;
     505                                                        return aligned;
    381506                                                }
    382507                                        }
     
    384509                        }
    385510                }
    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 */
     526static 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       
     539loop:
     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;
    394569                        goto loop;
    395570                }
    396571        }
    397572       
    398         return result;
     573        return NULL;
    399574}
    400575
     
    475650            (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
    476651       
    477         assert((void *) head >= heap_start);
    478         assert((void *) head < heap_end);
    479        
    480652        block_check(head);
    481653        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);
    482660       
    483661        void *ptr = NULL;
     
    489667                /* Shrink */
    490668                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);
    494674                        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();
    497677                }
    498678               
    499679                ptr = ((void *) head) + sizeof(heap_block_head_t);
    500680        } 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                 */
    505687                heap_block_head_t *next_head =
    506688                    (heap_block_head_t *) (((void *) head) + head->size);
    507689               
    508                 if (((void *) next_head < heap_end) &&
     690                if (((void *) next_head < area->end) &&
    509691                    (head->size + next_head->size >= real_size) &&
    510692                    (next_head->free)) {
    511693                        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);
    513695                        split_mark(head, real_size);
    514696                       
    515697                        ptr = ((void *) head) + sizeof(heap_block_head_t);
     698                        next = NULL;
    516699                } else
    517700                        reloc = true;
     
    544727            = (heap_block_head_t *) (addr - sizeof(heap_block_head_t));
    545728       
    546         assert((void *) head >= heap_start);
    547         assert((void *) head < heap_end);
    548        
    549729        block_check(head);
    550730        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);
    551737       
    552738        /* Mark the block itself as free. */
     
    557743            = (heap_block_head_t *) (((void *) head) + head->size);
    558744       
    559         if ((void *) next_head < heap_end) {
     745        if ((void *) next_head < area->end) {
    560746                block_check(next_head);
    561747                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);
    563749        }
    564750       
    565751        /* 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)) {
    567753                heap_block_foot_t *prev_foot =
    568754                    (heap_block_foot_t *) (((void *) head) - sizeof(heap_block_foot_t));
     
    574760               
    575761                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();
    580767       
    581768        futex_up(&malloc_futex);
  • uspace/lib/c/generic/net/icmp_api.c

    r89acf204 r474afc9  
    4141#include <net/modules.h>
    4242#include <net/ip_codes.h>
    43 
    4443#include <async.h>
    4544#include <sys/types.h>
    4645#include <sys/time.h>
    4746#include <errno.h>
    48 
    49 #include <ipc/ipc.h>
    5047#include <ipc/services.h>
    5148#include <ipc/icmp.h>
  • uspace/lib/c/generic/net/modules.c

    r89acf204 r474afc9  
    4343#include <errno.h>
    4444#include <sys/time.h>
    45 
    46 #include <ipc/ipc.h>
    4745#include <ipc/services.h>
    48 
    4946#include <net/modules.h>
    5047
     
    6764                switch (count) {
    6865                case 0:
    69                         ipc_answer_0(callid, (sysarg_t) result);
     66                        async_answer_0(callid, (sysarg_t) result);
    7067                        break;
    7168                case 1:
    72                         ipc_answer_1(callid, (sysarg_t) result,
     69                        async_answer_1(callid, (sysarg_t) result,
    7370                            IPC_GET_ARG1(*answer));
    7471                        break;
    7572                case 2:
    76                         ipc_answer_2(callid, (sysarg_t) result,
     73                        async_answer_2(callid, (sysarg_t) result,
    7774                            IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer));
    7875                        break;
    7976                case 3:
    80                         ipc_answer_3(callid, (sysarg_t) result,
     77                        async_answer_3(callid, (sysarg_t) result,
    8178                            IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer),
    8279                            IPC_GET_ARG3(*answer));
    8380                        break;
    8481                case 4:
    85                         ipc_answer_4(callid, (sysarg_t) result,
     82                        async_answer_4(callid, (sysarg_t) result,
    8683                            IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer),
    8784                            IPC_GET_ARG3(*answer), IPC_GET_ARG4(*answer));
     
    8986                case 5:
    9087                default:
    91                         ipc_answer_5(callid, (sysarg_t) result,
     88                        async_answer_5(callid, (sysarg_t) result,
    9289                            IPC_GET_ARG1(*answer), IPC_GET_ARG2(*answer),
    9390                            IPC_GET_ARG3(*answer), IPC_GET_ARG4(*answer),
     
    137134    sysarg_t arg3, async_client_conn_t client_receiver, suseconds_t timeout)
    138135{
    139         int rc;
    140        
    141136        /* Connect to the needed service */
    142137        int phone = connect_to_service_timeout(need, timeout);
    143138        if (phone >= 0) {
    144139                /* 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);
    150141                if (rc != EOK) {
    151                         ipc_hangup(phone);
     142                        async_hangup(phone);
    152143                        return rc;
    153144                }
    154                 async_new_connection(taskhash, phonehash, 0, NULL,
    155                     client_receiver);
    156145        }
    157146       
  • uspace/lib/c/generic/net/socket_client.c

    r89acf204 r474afc9  
    4343#include <stdlib.h>
    4444#include <errno.h>
    45 
     45#include <task.h>
    4646#include <ipc/services.h>
    4747#include <ipc/socket.h>
    48 
    4948#include <net/modules.h>
    5049#include <net/in.h>
     
    278277        }
    279278
    280         ipc_answer_0(callid, (sysarg_t) rc);
     279        async_answer_0(callid, (sysarg_t) rc);
    281280        goto loop;
    282281}
     
    687686
    688687        /* Read address */
    689         ipc_data_read_start(socket->phone, cliaddr, *addrlen);
     688        async_data_read_start(socket->phone, cliaddr, *addrlen);
    690689        fibril_rwlock_write_unlock(&socket_globals.lock);
    691690        async_wait_for(message_id, &ipc_result);
  • uspace/lib/c/generic/private/async.h

    r89acf204 r474afc9  
    3333 */
    3434
    35 #ifndef LIBC_ASYNC_PRIV_H_
    36 #define LIBC_ASYNC_PRIV_H_
     35#ifndef LIBC_PRIVATE_ASYNC_H_
     36#define LIBC_PRIVATE_ASYNC_H_
    3737
    3838#include <adt/list.h>
     
    5151        /** If true, we have timed out. */
    5252        bool occurred;
    53 
     53       
    5454        /** Expiration time. */
    5555        struct timeval expires;
     
    6565} wu_event_t;
    6666
    67 
    6867/** Structures of this type represent a waiting fibril. */
    6968typedef struct {
     
    7372        /** If true, this fibril is currently active. */
    7473        bool active;
    75 
     74       
    7675        /** Timeout wait data. */
    7776        to_event_t to_event;
     
    8079} awaiter_t;
    8180
    82 extern void async_insert_timeout(awaiter_t *wd);
     81extern void __async_init(void);
     82extern void async_insert_timeout(awaiter_t *);
    8383
    8484#endif
  • uspace/lib/c/generic/private/async_sess.h

    r89acf204 r474afc9  
    11/*
    2  * Copyright (c) 2006 Ondrej Palkovsky
     2 * Copyright (c) 2011 Martin Decky
    33 * All rights reserved.
    44 *
     
    3333 */
    3434
    35 #include <stdio.h>
    36 #include <stdlib.h>
     35#ifndef LIBC_PRIVATE_ASYNC_SESS_H_
     36#define LIBC_PRIVATE_ASYNC_SESS_H_
    3737
    38 /* TODO
    39 void errx(int __status, __const char *__format, ...)
    40 {
    41         _exit(0);
    42 }
    43 */
     38extern void __async_sess_init(void);
     39
     40#endif
    4441
    4542/** @}
  • uspace/lib/c/generic/thread.c

    r89acf204 r474afc9  
    3131 */
    3232/** @file
    33  */ 
     33 */
    3434
    3535#include <thread.h>
     
    4141#include <str.h>
    4242#include <async.h>
     43#include "private/thread.h"
    4344
    4445#ifndef THREAD_INITIAL_STACK_PAGES_NO
     
    5051 * This function is called from __thread_entry() and is used
    5152 * 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.
    5454 *
    5555 * @param uarg Pointer to userspace argument structure.
     56 *
    5657 */
    5758void __thread_main(uspace_arg_t *uarg)
    5859{
    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       
    6466        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       
    6972        /* If there is a manager, destroy it */
    7073        async_destroy_manager();
    71         fibril_teardown(f);
    72 
     74        fibril_teardown(fibril);
     75       
    7376        thread_exit(0);
    7477}
     
    127130 *
    128131 * @param status Exit status. Currently not used.
     132 *
    129133 */
    130134void thread_exit(int status)
    131135{
    132136        __SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status);
    133         for (;;)
    134                 ;
     137       
     138        /* Unreachable */
     139        while (1);
    135140}
    136141
  • uspace/lib/c/generic/time.c

    r89acf204 r474afc9  
    3434
    3535#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>
    3938#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>
    4641#include <sysinfo.h>
    4742#include <as.h>
    4843#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 */
    5347struct {
    5448        volatile sysarg_t seconds1;
     
    5953/** Add microseconds to given timeval.
    6054 *
    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 *
    6358 */
    6459void tv_add(struct timeval *tv, suseconds_t usecs)
     
    6661        tv->tv_sec += usecs / 1000000;
    6762        tv->tv_usec += usecs % 1000000;
     63       
    6864        if (tv->tv_usec > 1000000) {
    6965                tv->tv_sec++;
     
    7470/** Subtract two timevals.
    7571 *
    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 *
    8178 */
    8279suseconds_t tv_sub(struct timeval *tv1, struct timeval *tv2)
    8380{
    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);
    9083}
    9184
    9285/** Decide if one timeval is greater than the other.
    9386 *
    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 *
    9993 */
    10094int tv_gt(struct timeval *tv1, struct timeval *tv2)
    10195{
    10296        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;
    107103}
    108104
    109105/** Decide if one timeval is greater than or equal to the other.
    110106 *
    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 *
    116113 */
    117114int tv_gteq(struct timeval *tv1, struct timeval *tv2)
    118115{
    119116        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 *
    135138 */
    136139int gettimeofday(struct timeval *tv, struct timezone *tz)
    137140{
    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;
    151147                }
    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;
    157153                }
    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       
    160166        if (tz) {
    161167                tz->tz_minuteswest = 0;
    162168                tz->tz_dsttime = DST_NONE;
    163169        }
    164 
    165         s2 = ktime->seconds2;
     170       
     171        sysarg_t s2 = ktime->seconds2;
     172       
    166173        read_barrier();
    167174        tv->tv_usec = ktime->useconds;
     175       
    168176        read_barrier();
    169         s1 = ktime->seconds1;
     177        sysarg_t s1 = ktime->seconds1;
     178       
    170179        if (s1 != s2) {
     180                tv->tv_sec = max(s1, s2);
    171181                tv->tv_usec = 0;
    172                 tv->tv_sec = s1 > s2 ? s1 : s2;
    173182        } else
    174183                tv->tv_sec = s1;
    175 
     184       
    176185        return 0;
    177186}
     
    180189{
    181190        struct timeval tv;
    182 
    183191        if (gettimeofday(&tv, NULL))
    184192                return (time_t) -1;
     193       
    185194        if (tloc)
    186195                *tloc = tv.tv_sec;
     196       
    187197        return tv.tv_sec;
    188198}
    189199
    190 /** Wait unconditionally for specified number of microseconds */
     200/** Wait unconditionally for specified number of microseconds
     201 *
     202 */
    191203int usleep(useconds_t usec)
    192204{
     
    195207}
    196208
    197 /** Wait unconditionally for specified number of seconds */
     209/** Wait unconditionally for specified number of seconds
     210 *
     211 */
    198212unsigned int sleep(unsigned int sec)
    199213{
    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       
    202219        while (sec > 0) {
    203220                unsigned int period = (sec > 1000) ? 1000 : sec;
    204        
     221               
    205222                usleep(period * 1000000);
    206223                sec -= period;
    207224        }
     225       
    208226        return 0;
    209227}
  • uspace/lib/c/generic/udebug.c

    r89acf204 r474afc9  
    3131 */
    3232/** @file
    33  */ 
     33 */
    3434
    3535#include <udebug.h>
    3636#include <sys/types.h>
    37 #include <ipc/ipc.h>
    3837#include <async.h>
    3938
  • uspace/lib/c/generic/vfs/vfs.c

    r89acf204 r474afc9  
    11/*
    2  * Copyright (c) 2008 Jakub Jermar 
     2 * Copyright (c) 2008 Jakub Jermar
    33 * All rights reserved.
    44 *
     
    4343#include <sys/stat.h>
    4444#include <sys/types.h>
    45 #include <ipc/ipc.h>
    4645#include <ipc/services.h>
     46#include <ipc/ns.h>
    4747#include <async.h>
    4848#include <fibril_synch.h>
     
    118118static void vfs_connect(void)
    119119{
    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);
    124122       
    125123        async_session_create(&vfs_session, vfs_phone, 0);
Note: See TracChangeset for help on using the changeset viewer.