~jkavalik/cdfs/main

« back to all changes in this revision

Viewing changes to uspace/lib/c/generic/async.c

merge mainline
update async in cdfs
add READ TOC support in ata_bd, libblock and cdfs

Show diffs side-by-side

added added

removed removed

Lines of Context:
42
42
 * You should be able to write very simple multithreaded programs, the async
43
43
 * framework will automatically take care of most synchronization problems.
44
44
 *
45
 
 * Default semantics:
46
 
 * - async_send_*(): Send asynchronously. If the kernel refuses to send
47
 
 *                   more messages, [ try to get responses from kernel, if
48
 
 *                   nothing found, might try synchronous ]
49
 
 *
50
45
 * Example of use (pseudo C):
51
46
 *
52
47
 * 1) Multithreaded client application
57
52
 *
58
53
 *   int fibril1(void *arg)
59
54
 *   {
60
 
 *     conn = ipc_connect_me_to();
 
55
 *     conn = async_connect_me_to();
61
56
 *     c1 = async_send(conn);
62
57
 *     c2 = async_send(conn);
63
58
 *     async_wait_for(c1);
76
71
 *   my_client_connection(icallid, *icall)
77
72
 *   {
78
73
 *     if (want_refuse) {
79
 
 *       ipc_answer_0(icallid, ELIMIT);
 
74
 *       async_answer_0(icallid, ELIMIT);
80
75
 *       return;
81
76
 *     }
82
 
 *     ipc_answer_0(icallid, EOK);
 
77
 *     async_answer_0(icallid, EOK);
83
78
 *
84
79
 *     callid = async_get_call(&call);
85
80
 *     somehow_handle_the_call(callid, call);
86
 
 *     ipc_answer_2(callid, 1, 2, 3);
 
81
 *     async_answer_2(callid, 1, 2, 3);
87
82
 *
88
83
 *     callid = async_get_call(&call);
89
84
 *     ...
91
86
 *
92
87
 */
93
88
 
 
89
#define LIBC_ASYNC_C_
 
90
#include <ipc/ipc.h>
 
91
#include <async.h>
 
92
#undef LIBC_ASYNC_C_
 
93
 
94
94
#include <futex.h>
95
 
#include <async.h>
96
 
#include <async_priv.h>
97
95
#include <fibril.h>
98
96
#include <stdio.h>
99
97
#include <adt/hash_table.h>
100
98
#include <adt/list.h>
101
 
#include <ipc/ipc.h>
102
99
#include <assert.h>
103
100
#include <errno.h>
104
101
#include <sys/time.h>
105
102
#include <arch/barrier.h>
106
103
#include <bool.h>
 
104
#include <stdlib.h>
 
105
#include <malloc.h>
 
106
#include "private/async.h"
107
107
 
108
108
atomic_t async_futex = FUTEX_INITIALIZER;
109
109
 
123
123
} amsg_t;
124
124
 
125
125
/**
126
 
 * Structures of this type are used to group information about a call and a
127
 
 * message queue link.
 
126
 * Structures of this type are used to group information about
 
127
 * a call and about a message queue link.
128
128
 */
129
129
typedef struct {
130
130
        link_t link;
133
133
} msg_t;
134
134
 
135
135
typedef struct {
 
136
        sysarg_t in_task_hash;
 
137
        link_t link;
 
138
        int refcnt;
 
139
        void *data;
 
140
} client_t;
 
141
 
 
142
typedef struct {
136
143
        awaiter_t wdata;
137
144
        
138
145
        /** Hash table link. */
139
146
        link_t link;
140
147
        
 
148
        /** Incoming client task hash. */
 
149
        sysarg_t in_task_hash;
141
150
        /** Incoming phone hash. */
142
151
        sysarg_t in_phone_hash;
143
152
        
 
153
        /** Link to the client tracking structure. */
 
154
        client_t *client;
 
155
        
144
156
        /** Messages that should be delivered to this fibril. */
145
157
        link_t msg_queue;
146
158
        
157
169
} connection_t;
158
170
 
159
171
/** Identifier of the incoming connection handled by the current fibril. */
160
 
fibril_local connection_t *FIBRIL_connection;
161
 
 
162
 
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
163
 
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
 
172
static fibril_local connection_t *FIBRIL_connection;
 
173
 
 
174
static void *default_client_data_constructor(void)
 
175
{
 
176
        return NULL;
 
177
}
 
178
 
 
179
static void default_client_data_destructor(void *data)
 
180
{
 
181
}
 
182
 
 
183
static async_client_data_ctor_t async_client_data_create =
 
184
    default_client_data_constructor;
 
185
static async_client_data_dtor_t async_client_data_destroy =
 
186
    default_client_data_destructor;
 
187
 
 
188
void async_set_client_data_constructor(async_client_data_ctor_t ctor)
 
189
{
 
190
        async_client_data_create = ctor;
 
191
}
 
192
 
 
193
void async_set_client_data_destructor(async_client_data_dtor_t dtor)
 
194
{
 
195
        async_client_data_destroy = dtor;
 
196
}
 
197
 
 
198
void *async_client_data_get(void)
 
199
{
 
200
        assert(FIBRIL_connection);
 
201
        return FIBRIL_connection->client->data;
 
202
}
 
203
 
 
204
/** Default fibril function that gets called to handle new connection.
 
205
 *
 
206
 * This function is defined as a weak symbol - to be redefined in user code.
 
207
 *
 
208
 * @param callid Hash of the incoming call.
 
209
 * @param call   Data of the incoming call.
 
210
 *
 
211
 */
 
212
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
 
213
{
 
214
        ipc_answer_0(callid, ENOENT);
 
215
}
164
216
 
165
217
/**
166
218
 * Pointer to a fibril function that will be used to handle connections.
167
219
 */
168
220
static async_client_conn_t client_connection = default_client_connection;
169
221
 
 
222
/** Default fibril function that gets called to handle interrupt notifications.
 
223
 *
 
224
 * This function is defined as a weak symbol - to be redefined in user code.
 
225
 *
 
226
 * @param callid Hash of the incoming call.
 
227
 * @param call   Data of the incoming call.
 
228
 *
 
229
 */
 
230
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)
 
231
{
 
232
}
 
233
 
170
234
/**
171
235
 * Pointer to a fibril function that will be used to handle interrupt
172
236
 * notifications.
173
237
 */
174
238
static async_client_conn_t interrupt_received = default_interrupt_received;
175
239
 
 
240
static hash_table_t client_hash_table;
176
241
static hash_table_t conn_hash_table;
177
242
static LIST_INITIALIZE(timeout_list);
178
243
 
179
 
#define CONN_HASH_TABLE_CHAINS  32
 
244
#define CLIENT_HASH_TABLE_BUCKETS  32
 
245
#define CONN_HASH_TABLE_BUCKETS    32
 
246
 
 
247
static hash_index_t client_hash(unsigned long key[])
 
248
{
 
249
        assert(key);
 
250
        return (((key[0]) >> 4) % CLIENT_HASH_TABLE_BUCKETS);
 
251
}
 
252
 
 
253
static int client_compare(unsigned long key[], hash_count_t keys, link_t *item)
 
254
{
 
255
        client_t *client = hash_table_get_instance(item, client_t, link);
 
256
        return (key[0] == client->in_task_hash);
 
257
}
 
258
 
 
259
static void client_remove(link_t *item)
 
260
{
 
261
}
 
262
 
 
263
/** Operations for the client hash table. */
 
264
static hash_table_operations_t client_hash_table_ops = {
 
265
        .hash = client_hash,
 
266
        .compare = client_compare,
 
267
        .remove_callback = client_remove
 
268
};
180
269
 
181
270
/** Compute hash into the connection hash table based on the source phone hash.
182
271
 *
185
274
 * @return Index into the connection hash table.
186
275
 *
187
276
 */
188
 
static hash_index_t conn_hash(unsigned long *key)
 
277
static hash_index_t conn_hash(unsigned long key[])
189
278
{
190
279
        assert(key);
191
 
        return (((*key) >> 4) % CONN_HASH_TABLE_CHAINS);
 
280
        return (((key[0]) >> 4) % CONN_HASH_TABLE_BUCKETS);
192
281
}
193
282
 
194
283
/** Compare hash table item with a key.
202
291
 */
203
292
static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
204
293
{
205
 
        connection_t *hs = hash_table_get_instance(item, connection_t, link);
206
 
        return (key[0] == hs->in_phone_hash);
 
294
        connection_t *conn = hash_table_get_instance(item, connection_t, link);
 
295
        return (key[0] == conn->in_phone_hash);
207
296
}
208
297
 
209
 
/** Connection hash table removal callback function.
210
 
 *
211
 
 * This function is called whenever a connection is removed from the connection
212
 
 * hash table.
213
 
 *
214
 
 * @param item Connection hash table item being removed.
215
 
 *
216
 
 */
217
298
static void conn_remove(link_t *item)
218
299
{
219
 
        free(hash_table_get_instance(item, connection_t, link));
220
300
}
221
301
 
222
 
 
223
302
/** Operations for the connection hash table. */
224
303
static hash_table_operations_t conn_hash_table_ops = {
225
304
        .hash = conn_hash,
239
318
        
240
319
        link_t *tmp = timeout_list.next;
241
320
        while (tmp != &timeout_list) {
242
 
                awaiter_t *cur;
 
321
                awaiter_t *cur
 
322
                    = list_get_instance(tmp, awaiter_t, to_event.link);
243
323
                
244
 
                cur = list_get_instance(tmp, awaiter_t, to_event.link);
245
324
                if (tv_gteq(&cur->to_event.expires, &wd->to_event.expires))
246
325
                        break;
 
326
                
247
327
                tmp = tmp->next;
248
328
        }
249
329
        
260
340
 * @param call   Data of the incoming call.
261
341
 *
262
342
 * @return False if the call doesn't match any connection.
263
 
 *         True if the call was passed to the respective connection fibril.
 
343
 * @return True if the call was passed to the respective connection fibril.
264
344
 *
265
345
 */
266
346
static bool route_call(ipc_callid_t callid, ipc_call_t *call)
351
431
        msg->call = *call;
352
432
        
353
433
        fid_t fid = fibril_create(notification_fibril, msg);
 
434
        if (fid == 0) {
 
435
                free(msg);
 
436
                futex_up(&async_futex);
 
437
                return false;
 
438
        }
 
439
        
354
440
        fibril_add_ready(fid);
355
441
        
356
442
        futex_up(&async_futex);
397
483
                         * closed by the client but the server did not notice
398
484
                         * the first IPC_M_PHONE_HUNGUP call and continues to
399
485
                         * call async_get_call_timeout(). Repeat
400
 
                         * IPC_M_PHONE_HUNGUP until the caller notices. 
 
486
                         * IPC_M_PHONE_HUNGUP until the caller notices.
401
487
                         */
402
488
                        memset(call, 0, sizeof(ipc_call_t));
403
489
                        IPC_SET_IMETHOD(*call, IPC_M_PHONE_HUNGUP);
404
490
                        futex_up(&async_futex);
405
491
                        return conn->close_callid;
406
492
                }
407
 
 
 
493
                
408
494
                if (usecs)
409
495
                        async_insert_timeout(&conn->wdata);
410
496
                
442
528
        return callid;
443
529
}
444
530
 
445
 
/** Default fibril function that gets called to handle new connection.
446
 
 *
447
 
 * This function is defined as a weak symbol - to be redefined in user code.
448
 
 *
449
 
 * @param callid Hash of the incoming call.
450
 
 * @param call   Data of the incoming call.
451
 
 *
452
 
 */
453
 
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
454
 
{
455
 
        ipc_answer_0(callid, ENOENT);
456
 
}
457
 
 
458
 
/** Default fibril function that gets called to handle interrupt notifications.
459
 
 *
460
 
 * This function is defined as a weak symbol - to be redefined in user code.
461
 
 *
462
 
 * @param callid Hash of the incoming call.
463
 
 * @param call   Data of the incoming call.
464
 
 *
465
 
 */
466
 
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call)
467
 
{
468
 
}
469
 
 
470
531
/** Wrapper for client connection fibril.
471
532
 *
472
533
 * When a new connection arrives, a fibril with this implementing function is
480
541
static int connection_fibril(void *arg)
481
542
{
482
543
        /*
483
 
         * Setup fibril-local connection pointer and call client_connection().
484
 
         *
 
544
         * Setup fibril-local connection pointer.
485
545
         */
486
546
        FIBRIL_connection = (connection_t *) arg;
 
547
        
 
548
        futex_down(&async_futex);
 
549
        
 
550
        /*
 
551
         * Add our reference for the current connection in the client task
 
552
         * tracking structure. If this is the first reference, create and
 
553
         * hash in a new tracking structure.
 
554
         */
 
555
        
 
556
        unsigned long key = FIBRIL_connection->in_task_hash;
 
557
        link_t *lnk = hash_table_find(&client_hash_table, &key);
 
558
        
 
559
        client_t *client;
 
560
        
 
561
        if (lnk) {
 
562
                client = hash_table_get_instance(lnk, client_t, link);
 
563
                client->refcnt++;
 
564
        } else {
 
565
                client = malloc(sizeof(client_t));
 
566
                if (!client) {
 
567
                        ipc_answer_0(FIBRIL_connection->callid, ENOMEM);
 
568
                        futex_up(&async_futex);
 
569
                        return 0;
 
570
                }
 
571
                
 
572
                client->in_task_hash = FIBRIL_connection->in_task_hash;
 
573
                
 
574
                async_serialize_start();
 
575
                client->data = async_client_data_create();
 
576
                async_serialize_end();
 
577
                
 
578
                client->refcnt = 1;
 
579
                hash_table_insert(&client_hash_table, &key, &client->link);
 
580
        }
 
581
        
 
582
        futex_up(&async_futex);
 
583
        
 
584
        FIBRIL_connection->client = client;
 
585
        
 
586
        /*
 
587
         * Call the connection handler function.
 
588
         */
487
589
        FIBRIL_connection->cfibril(FIBRIL_connection->callid,
488
590
            &FIBRIL_connection->call);
489
591
        
490
 
        /* Remove myself from the connection hash table */
491
 
        futex_down(&async_futex);
492
 
        unsigned long key = FIBRIL_connection->in_phone_hash;
 
592
        /*
 
593
         * Remove the reference for this client task connection.
 
594
         */
 
595
        bool destroy;
 
596
        
 
597
        futex_down(&async_futex);
 
598
        
 
599
        if (--client->refcnt == 0) {
 
600
                hash_table_remove(&client_hash_table, &key, 1);
 
601
                destroy = true;
 
602
        } else
 
603
                destroy = false;
 
604
        
 
605
        futex_up(&async_futex);
 
606
        
 
607
        if (destroy) {
 
608
                if (client->data)
 
609
                        async_client_data_destroy(client->data);
 
610
                
 
611
                free(client);
 
612
        }
 
613
        
 
614
        /*
 
615
         * Remove myself from the connection hash table.
 
616
         */
 
617
        futex_down(&async_futex);
 
618
        key = FIBRIL_connection->in_phone_hash;
493
619
        hash_table_remove(&conn_hash_table, &key, 1);
494
620
        futex_up(&async_futex);
495
621
        
496
 
        /* Answer all remaining messages with EHANGUP */
 
622
        /*
 
623
         * Answer all remaining messages with EHANGUP.
 
624
         */
497
625
        while (!list_empty(&FIBRIL_connection->msg_queue)) {
498
 
                msg_t *msg;
 
626
                msg_t *msg =
 
627
                    list_get_instance(FIBRIL_connection->msg_queue.next, msg_t,
 
628
                    link);
499
629
                
500
 
                msg = list_get_instance(FIBRIL_connection->msg_queue.next,
501
 
                    msg_t, link);
502
630
                list_remove(&msg->link);
503
631
                ipc_answer_0(msg->callid, EHANGUP);
504
632
                free(msg);
505
633
        }
506
634
        
 
635
        /*
 
636
         * If the connection was hung-up, answer the last call,
 
637
         * i.e. IPC_M_PHONE_HUNGUP.
 
638
         */
507
639
        if (FIBRIL_connection->close_callid)
508
640
                ipc_answer_0(FIBRIL_connection->close_callid, EOK);
509
641
        
 
642
        free(FIBRIL_connection);
510
643
        return 0;
511
644
}
512
645
 
516
649
 * it into the hash table, so that later we can easily do routing of messages to
517
650
 * particular fibrils.
518
651
 *
 
652
 * @param in_task_hash  Identification of the incoming connection.
519
653
 * @param in_phone_hash Identification of the incoming connection.
520
654
 * @param callid        Hash of the opening IPC_M_CONNECT_ME_TO call.
521
655
 *                      If callid is zero, the connection was opened by
528
662
 * @return New fibril id or NULL on failure.
529
663
 *
530
664
 */
531
 
fid_t async_new_connection(sysarg_t in_phone_hash, ipc_callid_t callid,
532
 
    ipc_call_t *call, void (*cfibril)(ipc_callid_t, ipc_call_t *))
 
665
fid_t async_new_connection(sysarg_t in_task_hash, sysarg_t in_phone_hash,
 
666
    ipc_callid_t callid, ipc_call_t *call,
 
667
    void (*cfibril)(ipc_callid_t, ipc_call_t *))
533
668
{
534
669
        connection_t *conn = malloc(sizeof(*conn));
535
670
        if (!conn) {
536
671
                if (callid)
537
672
                        ipc_answer_0(callid, ENOMEM);
 
673
                
538
674
                return (uintptr_t) NULL;
539
675
        }
540
676
        
 
677
        conn->in_task_hash = in_task_hash;
541
678
        conn->in_phone_hash = in_phone_hash;
542
679
        list_initialize(&conn->msg_queue);
543
680
        conn->callid = callid;
551
688
        conn->cfibril = cfibril;
552
689
        conn->wdata.fid = fibril_create(connection_fibril, conn);
553
690
        
554
 
        if (!conn->wdata.fid) {
 
691
        if (conn->wdata.fid == 0) {
555
692
                free(conn);
 
693
                
556
694
                if (callid)
557
695
                        ipc_answer_0(callid, ENOMEM);
 
696
                
558
697
                return (uintptr_t) NULL;
559
698
        }
560
699
        
581
720
 */
582
721
static void handle_call(ipc_callid_t callid, ipc_call_t *call)
583
722
{
584
 
        /* Unrouted call - do some default behaviour */
 
723
        /* Unrouted call - take some default action */
585
724
        if ((callid & IPC_CALLID_NOTIFICATION)) {
586
725
                process_notification(callid, call);
587
 
                goto out;
 
726
                return;
588
727
        }
589
728
        
590
729
        switch (IPC_GET_IMETHOD(*call)) {
591
730
        case IPC_M_CONNECT_ME:
592
731
        case IPC_M_CONNECT_ME_TO:
593
 
                /* Open new connection with fibril etc. */
594
 
                async_new_connection(IPC_GET_ARG5(*call), callid, call,
595
 
                    client_connection);
596
 
                goto out;
 
732
                /* Open new connection with fibril, etc. */
 
733
                async_new_connection(call->in_task_hash, IPC_GET_ARG5(*call),
 
734
                    callid, call, client_connection);
 
735
                return;
597
736
        }
598
737
        
599
738
        /* Try to route the call through the connection hash table */
600
739
        if (route_call(callid, call))
601
 
                goto out;
 
740
                return;
602
741
        
603
742
        /* Unknown call from unknown phone - hang it up */
604
743
        ipc_answer_0(callid, EHANGUP);
605
 
        return;
606
 
        
607
 
out:
608
 
        ;
609
744
}
610
745
 
611
746
/** Fire all timeouts that expired. */
618
753
        
619
754
        link_t *cur = timeout_list.next;
620
755
        while (cur != &timeout_list) {
621
 
                awaiter_t *waiter;
 
756
                awaiter_t *waiter =
 
757
                    list_get_instance(cur, awaiter_t, to_event.link);
622
758
                
623
 
                waiter = list_get_instance(cur, awaiter_t, to_event.link);
624
759
                if (tv_gt(&waiter->to_event.expires, &tv))
625
760
                        break;
626
 
 
 
761
                
627
762
                cur = cur->next;
628
 
 
 
763
                
629
764
                list_remove(&waiter->to_event.link);
630
765
                waiter->to_event.inlist = false;
631
766
                waiter->to_event.occurred = true;
652
787
{
653
788
        while (true) {
654
789
                if (fibril_switch(FIBRIL_FROM_MANAGER)) {
655
 
                        futex_up(&async_futex); 
 
790
                        futex_up(&async_futex);
656
791
                        /*
657
792
                         * async_futex is always held when entering a manager
658
793
                         * fibril.
675
810
                                handle_expired_timeouts();
676
811
                                continue;
677
812
                        } else
678
 
                                timeout = tv_sub(&waiter->to_event.expires,
679
 
                                    &tv);
 
813
                                timeout = tv_sub(&waiter->to_event.expires, &tv);
680
814
                } else
681
815
                        timeout = SYNCH_NO_TIMEOUT;
682
816
                
683
817
                futex_up(&async_futex);
684
 
 
 
818
                
685
819
                atomic_inc(&threads_in_ipc_wait);
686
820
                
687
821
                ipc_call_t call;
689
823
                    SYNCH_FLAGS_NONE);
690
824
                
691
825
                atomic_dec(&threads_in_ipc_wait);
692
 
 
 
826
                
693
827
                if (!callid) {
694
828
                        handle_expired_timeouts();
695
829
                        continue;
728
862
void async_create_manager(void)
729
863
{
730
864
        fid_t fid = fibril_create(async_manager_fibril, NULL);
731
 
        fibril_add_manager(fid);
 
865
        if (fid != 0)
 
866
                fibril_add_manager(fid);
732
867
}
733
868
 
734
869
/** Remove one manager from manager list */
739
874
 
740
875
/** Initialize the async framework.
741
876
 *
742
 
 * @return Zero on success or an error code.
743
877
 */
744
 
int __async_init(void)
 
878
void __async_init(void)
745
879
{
746
 
        if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_CHAINS, 1,
747
 
            &conn_hash_table_ops)) {
748
 
                printf("%s: Cannot create async hash table\n", "libc");
749
 
                return ENOMEM;
750
 
        }
 
880
        if (!hash_table_create(&client_hash_table, CLIENT_HASH_TABLE_BUCKETS, 1,
 
881
            &client_hash_table_ops))
 
882
                abort();
751
883
        
752
 
        return 0;
 
884
        if (!hash_table_create(&conn_hash_table, CONN_HASH_TABLE_BUCKETS, 1,
 
885
            &conn_hash_table_ops))
 
886
                abort();
753
887
}
754
888
 
755
889
/** Reply received callback.
762
896
 * @param arg    Pointer to the asynchronous message record.
763
897
 * @param retval Value returned in the answer.
764
898
 * @param data   Call data of the answer.
 
899
 *
765
900
 */
766
901
static void reply_received(void *arg, int retval, ipc_call_t *data)
767
902
{
809
944
aid_t async_send_fast(int phoneid, sysarg_t method, sysarg_t arg1,
810
945
    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
811
946
{
812
 
        amsg_t *msg = malloc(sizeof(*msg));
 
947
        amsg_t *msg = malloc(sizeof(amsg_t));
813
948
        
814
949
        if (!msg)
815
950
                return 0;
818
953
        msg->dataptr = dataptr;
819
954
        
820
955
        msg->wdata.to_event.inlist = false;
821
 
        /* We may sleep in the next method, but it will use its own mechanism */
 
956
        
 
957
        /*
 
958
         * We may sleep in the next method,
 
959
         * but it will use its own means
 
960
         */
822
961
        msg->wdata.active = true;
823
962
        
824
963
        ipc_call_async_4(phoneid, method, arg1, arg2, arg3, arg4, msg,
849
988
    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
850
989
    ipc_call_t *dataptr)
851
990
{
852
 
        amsg_t *msg = malloc(sizeof(*msg));
 
991
        amsg_t *msg = malloc(sizeof(amsg_t));
853
992
        
854
993
        if (!msg)
855
994
                return 0;
858
997
        msg->dataptr = dataptr;
859
998
        
860
999
        msg->wdata.to_event.inlist = false;
861
 
        /* We may sleep in next method, but it will use its own mechanism */
 
1000
        
 
1001
        /*
 
1002
         * We may sleep in the next method,
 
1003
         * but it will use its own means
 
1004
         */
862
1005
        msg->wdata.active = true;
863
1006
        
864
1007
        ipc_call_async_5(phoneid, method, arg1, arg2, arg3, arg4, arg5, msg,
957
1100
 */
958
1101
void async_usleep(suseconds_t timeout)
959
1102
{
960
 
        amsg_t *msg = malloc(sizeof(*msg));
 
1103
        amsg_t *msg = malloc(sizeof(amsg_t));
961
1104
        
962
1105
        if (!msg)
963
1106
                return;
1100
1243
        return rc;
1101
1244
}
1102
1245
 
 
1246
void async_msg_0(int phone, sysarg_t imethod)
 
1247
{
 
1248
        ipc_call_async_0(phone, imethod, NULL, NULL, true);
 
1249
}
 
1250
 
 
1251
void async_msg_1(int phone, sysarg_t imethod, sysarg_t arg1)
 
1252
{
 
1253
        ipc_call_async_1(phone, imethod, arg1, NULL, NULL, true);
 
1254
}
 
1255
 
 
1256
void async_msg_2(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2)
 
1257
{
 
1258
        ipc_call_async_2(phone, imethod, arg1, arg2, NULL, NULL, true);
 
1259
}
 
1260
 
 
1261
void async_msg_3(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
 
1262
    sysarg_t arg3)
 
1263
{
 
1264
        ipc_call_async_3(phone, imethod, arg1, arg2, arg3, NULL, NULL, true);
 
1265
}
 
1266
 
 
1267
void async_msg_4(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
 
1268
    sysarg_t arg3, sysarg_t arg4)
 
1269
{
 
1270
        ipc_call_async_4(phone, imethod, arg1, arg2, arg3, arg4, NULL, NULL,
 
1271
            true);
 
1272
}
 
1273
 
 
1274
void async_msg_5(int phone, sysarg_t imethod, sysarg_t arg1, sysarg_t arg2,
 
1275
    sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
 
1276
{
 
1277
        ipc_call_async_5(phone, imethod, arg1, arg2, arg3, arg4, arg5, NULL,
 
1278
            NULL, true);
 
1279
}
 
1280
 
 
1281
sysarg_t async_answer_0(ipc_callid_t callid, sysarg_t retval)
 
1282
{
 
1283
        return ipc_answer_0(callid, retval);
 
1284
}
 
1285
 
 
1286
sysarg_t async_answer_1(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1)
 
1287
{
 
1288
        return ipc_answer_1(callid, retval, arg1);
 
1289
}
 
1290
 
 
1291
sysarg_t async_answer_2(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
 
1292
    sysarg_t arg2)
 
1293
{
 
1294
        return ipc_answer_2(callid, retval, arg1, arg2);
 
1295
}
 
1296
 
 
1297
sysarg_t async_answer_3(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
 
1298
    sysarg_t arg2, sysarg_t arg3)
 
1299
{
 
1300
        return ipc_answer_3(callid, retval, arg1, arg2, arg3);
 
1301
}
 
1302
 
 
1303
sysarg_t async_answer_4(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
 
1304
    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4)
 
1305
{
 
1306
        return ipc_answer_4(callid, retval, arg1, arg2, arg3, arg4);
 
1307
}
 
1308
 
 
1309
sysarg_t async_answer_5(ipc_callid_t callid, sysarg_t retval, sysarg_t arg1,
 
1310
    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5)
 
1311
{
 
1312
        return ipc_answer_5(callid, retval, arg1, arg2, arg3, arg4, arg5);
 
1313
}
 
1314
 
 
1315
int async_forward_fast(ipc_callid_t callid, int phoneid, sysarg_t imethod,
 
1316
    sysarg_t arg1, sysarg_t arg2, unsigned int mode)
 
1317
{
 
1318
        return ipc_forward_fast(callid, phoneid, imethod, arg1, arg2, mode);
 
1319
}
 
1320
 
 
1321
int async_forward_slow(ipc_callid_t callid, int phoneid, sysarg_t imethod,
 
1322
    sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, sysarg_t arg5,
 
1323
    unsigned int mode)
 
1324
{
 
1325
        return ipc_forward_slow(callid, phoneid, imethod, arg1, arg2, arg3, arg4,
 
1326
            arg5, mode);
 
1327
}
 
1328
 
 
1329
/** Wrapper for making IPC_M_CONNECT_TO_ME calls using the async framework.
 
1330
 *
 
1331
 * Ask through phone for a new connection to some service.
 
1332
 *
 
1333
 * @param phone           Phone handle used for contacting the other side.
 
1334
 * @param arg1            User defined argument.
 
1335
 * @param arg2            User defined argument.
 
1336
 * @param arg3            User defined argument.
 
1337
 * @param client_receiver Connection handing routine.
 
1338
 *
 
1339
 * @return New phone handle on success or a negative error code.
 
1340
 *
 
1341
 */
 
1342
int async_connect_to_me(int phone, sysarg_t arg1, sysarg_t arg2,
 
1343
    sysarg_t arg3, async_client_conn_t client_receiver)
 
1344
{
 
1345
        sysarg_t task_hash;
 
1346
        sysarg_t phone_hash;
 
1347
        int rc = async_req_3_5(phone, IPC_M_CONNECT_TO_ME, arg1, arg2, arg3,
 
1348
            NULL, NULL, NULL, &task_hash, &phone_hash);
 
1349
        if (rc != EOK)
 
1350
                return rc;
 
1351
        
 
1352
        if (client_receiver != NULL)
 
1353
                async_new_connection(task_hash, phone_hash, 0, NULL,
 
1354
                    client_receiver);
 
1355
        
 
1356
        return EOK;
 
1357
}
 
1358
 
1103
1359
/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
1104
 
 * 
 
1360
 *
1105
1361
 * Ask through phone for a new connection to some service.
1106
1362
 *
1107
 
 * @param phoneid       Phone handle used for contacting the other side.
1108
 
 * @param arg1          User defined argument.
1109
 
 * @param arg2          User defined argument.
1110
 
 * @param arg3          User defined argument.
1111
 
 *
1112
 
 * @return              New phone handle on success or a negative error code.
 
1363
 * @param phone Phone handle used for contacting the other side.
 
1364
 * @param arg1  User defined argument.
 
1365
 * @param arg2  User defined argument.
 
1366
 * @param arg3  User defined argument.
 
1367
 *
 
1368
 * @return New phone handle on success or a negative error code.
 
1369
 *
1113
1370
 */
1114
 
int
1115
 
async_connect_me_to(int phoneid, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3)
 
1371
int async_connect_me_to(int phone, sysarg_t arg1, sysarg_t arg2,
 
1372
    sysarg_t arg3)
1116
1373
{
1117
 
        int rc;
1118
1374
        sysarg_t newphid;
1119
 
 
1120
 
        rc = async_req_3_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3, NULL,
1121
 
            NULL, NULL, NULL, &newphid);
 
1375
        int rc = async_req_3_5(phone, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
 
1376
            NULL, NULL, NULL, NULL, &newphid);
1122
1377
        
1123
 
        if (rc != EOK)  
 
1378
        if (rc != EOK)
1124
1379
                return rc;
1125
 
 
 
1380
        
1126
1381
        return newphid;
1127
1382
}
1128
1383
 
1129
1384
/** Wrapper for making IPC_M_CONNECT_ME_TO calls using the async framework.
1130
 
 * 
 
1385
 *
1131
1386
 * Ask through phone for a new connection to some service and block until
1132
1387
 * success.
1133
1388
 *
1134
 
 * @param phoneid       Phone handle used for contacting the other side.
1135
 
 * @param arg1          User defined argument.
1136
 
 * @param arg2          User defined argument.
1137
 
 * @param arg3          User defined argument.
1138
 
 *
1139
 
 * @return              New phone handle on success or a negative error code.
 
1389
 * @param phoneid Phone handle used for contacting the other side.
 
1390
 * @param arg1    User defined argument.
 
1391
 * @param arg2    User defined argument.
 
1392
 * @param arg3    User defined argument.
 
1393
 *
 
1394
 * @return New phone handle on success or a negative error code.
 
1395
 *
1140
1396
 */
1141
 
int
1142
 
async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
 
1397
int async_connect_me_to_blocking(int phoneid, sysarg_t arg1, sysarg_t arg2,
1143
1398
    sysarg_t arg3)
1144
1399
{
1145
 
        int rc;
1146
1400
        sysarg_t newphid;
1147
 
 
1148
 
        rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
 
1401
        int rc = async_req_4_5(phoneid, IPC_M_CONNECT_ME_TO, arg1, arg2, arg3,
1149
1402
            IPC_FLAG_BLOCKING, NULL, NULL, NULL, NULL, &newphid);
1150
1403
        
1151
 
        if (rc != EOK)  
 
1404
        if (rc != EOK)
1152
1405
                return rc;
1153
 
 
 
1406
        
1154
1407
        return newphid;
1155
1408
}
1156
1409
 
1157
 
/** Wrapper for making IPC_M_SHARE_IN calls using the async framework.
1158
 
 *
1159
 
 * @param phoneid       Phone that will be used to contact the receiving side.
1160
 
 * @param dst           Destination address space area base.
1161
 
 * @param size          Size of the destination address space area.
1162
 
 * @param arg           User defined argument.
1163
 
 * @param flags         Storage where the received flags will be stored. Can be
1164
 
 *                      NULL.
1165
 
 *
1166
 
 * @return              Zero on success or a negative error code from errno.h.
 
1410
/** Connect to a task specified by id.
 
1411
 *
 
1412
 */
 
1413
int async_connect_kbox(task_id_t id)
 
1414
{
 
1415
        return ipc_connect_kbox(id);
 
1416
}
 
1417
 
 
1418
/** Wrapper for ipc_hangup.
 
1419
 *
 
1420
 * @param phone Phone handle to hung up.
 
1421
 *
 
1422
 * @return Zero on success or a negative error code.
 
1423
 *
 
1424
 */
 
1425
int async_hangup(int phone)
 
1426
{
 
1427
        return ipc_hangup(phone);
 
1428
}
 
1429
 
 
1430
/** Interrupt one thread of this task from waiting for IPC. */
 
1431
void async_poke(void)
 
1432
{
 
1433
        ipc_poke();
 
1434
}
 
1435
 
 
1436
/** Wrapper for IPC_M_SHARE_IN calls using the async framework.
 
1437
 *
 
1438
 * @param phoneid Phone that will be used to contact the receiving side.
 
1439
 * @param dst     Destination address space area base.
 
1440
 * @param size    Size of the destination address space area.
 
1441
 * @param arg     User defined argument.
 
1442
 * @param flags   Storage for the received flags. Can be NULL.
 
1443
 *
 
1444
 * @return Zero on success or a negative error code from errno.h.
 
1445
 *
1167
1446
 */
1168
1447
int async_share_in_start(int phoneid, void *dst, size_t size, sysarg_t arg,
1169
 
    int *flags)
 
1448
    unsigned int *flags)
1170
1449
{
1171
 
        int res;
1172
1450
        sysarg_t tmp_flags;
1173
 
        res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
 
1451
        int res = async_req_3_2(phoneid, IPC_M_SHARE_IN, (sysarg_t) dst,
1174
1452
            (sysarg_t) size, arg, NULL, &tmp_flags);
 
1453
        
1175
1454
        if (flags)
1176
 
                *flags = tmp_flags;
 
1455
                *flags = (unsigned int) tmp_flags;
 
1456
        
1177
1457
        return res;
1178
1458
}
1179
1459
 
1180
1460
/** Wrapper for receiving the IPC_M_SHARE_IN calls using the async framework.
1181
1461
 *
1182
 
 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN calls
1183
 
 * so that the user doesn't have to remember the meaning of each IPC argument.
 
1462
 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_IN
 
1463
 * calls so that the user doesn't have to remember the meaning of each IPC
 
1464
 * argument.
1184
1465
 *
1185
1466
 * So far, this wrapper is to be used from within a connection fibril.
1186
1467
 *
1187
 
 * @param callid        Storage where the hash of the IPC_M_SHARE_IN call will
1188
 
 *                      be stored.
1189
 
 * @param size          Destination address space area size.    
1190
 
 *
1191
 
 * @return              Non-zero on success, zero on failure.
 
1468
 * @param callid Storage for the hash of the IPC_M_SHARE_IN call.
 
1469
 * @param size   Destination address space area size.
 
1470
 *
 
1471
 * @return True on success, false on failure.
 
1472
 *
1192
1473
 */
1193
 
int async_share_in_receive(ipc_callid_t *callid, size_t *size)
 
1474
bool async_share_in_receive(ipc_callid_t *callid, size_t *size)
1194
1475
{
1195
 
        ipc_call_t data;
1196
 
        
1197
1476
        assert(callid);
1198
1477
        assert(size);
1199
 
 
 
1478
        
 
1479
        ipc_call_t data;
1200
1480
        *callid = async_get_call(&data);
 
1481
        
1201
1482
        if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_IN)
1202
 
                return 0;
 
1483
                return false;
 
1484
        
1203
1485
        *size = (size_t) IPC_GET_ARG2(data);
1204
 
        return 1;
 
1486
        return true;
1205
1487
}
1206
1488
 
1207
1489
/** Wrapper for answering the IPC_M_SHARE_IN calls using the async framework.
1208
1490
 *
1209
 
 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
1210
 
 * so that the user doesn't have to remember the meaning of each IPC argument.
1211
 
 *
1212
 
 * @param callid        Hash of the IPC_M_DATA_READ call to answer.
1213
 
 * @param src           Source address space base.
1214
 
 * @param flags         Flags to be used for sharing. Bits can be only cleared.
1215
 
 *
1216
 
 * @return              Zero on success or a value from @ref errno.h on failure.
 
1491
 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
 
1492
 * calls so that the user doesn't have to remember the meaning of each IPC
 
1493
 * argument.
 
1494
 *
 
1495
 * @param callid Hash of the IPC_M_DATA_READ call to answer.
 
1496
 * @param src    Source address space base.
 
1497
 * @param flags  Flags to be used for sharing. Bits can be only cleared.
 
1498
 *
 
1499
 * @return Zero on success or a value from @ref errno.h on failure.
 
1500
 *
1217
1501
 */
1218
 
int async_share_in_finalize(ipc_callid_t callid, void *src, int flags)
 
1502
int async_share_in_finalize(ipc_callid_t callid, void *src, unsigned int flags)
1219
1503
{
1220
1504
        return ipc_share_in_finalize(callid, src, flags);
1221
1505
}
1222
1506
 
1223
 
/** Wrapper for making IPC_M_SHARE_OUT calls using the async framework.
1224
 
 *
1225
 
 * @param phoneid       Phone that will be used to contact the receiving side.
1226
 
 * @param src           Source address space area base address.
1227
 
 * @param flags         Flags to be used for sharing. Bits can be only cleared.
1228
 
 *
1229
 
 * @return              Zero on success or a negative error code from errno.h.
 
1507
/** Wrapper for IPC_M_SHARE_OUT calls using the async framework.
 
1508
 *
 
1509
 * @param phoneid Phone that will be used to contact the receiving side.
 
1510
 * @param src     Source address space area base address.
 
1511
 * @param flags   Flags to be used for sharing. Bits can be only cleared.
 
1512
 *
 
1513
 * @return Zero on success or a negative error code from errno.h.
 
1514
 *
1230
1515
 */
1231
 
int async_share_out_start(int phoneid, void *src, int flags)
 
1516
int async_share_out_start(int phoneid, void *src, unsigned int flags)
1232
1517
{
1233
1518
        return async_req_3_0(phoneid, IPC_M_SHARE_OUT, (sysarg_t) src, 0,
1234
1519
            (sysarg_t) flags);
1236
1521
 
1237
1522
/** Wrapper for receiving the IPC_M_SHARE_OUT calls using the async framework.
1238
1523
 *
1239
 
 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT calls
1240
 
 * so that the user doesn't have to remember the meaning of each IPC argument.
 
1524
 * This wrapper only makes it more comfortable to receive IPC_M_SHARE_OUT
 
1525
 * calls so that the user doesn't have to remember the meaning of each IPC
 
1526
 * argument.
1241
1527
 *
1242
1528
 * So far, this wrapper is to be used from within a connection fibril.
1243
1529
 *
1244
 
 * @param callid        Storage where the hash of the IPC_M_SHARE_OUT call will
1245
 
 *                      be stored.
1246
 
 * @param size          Storage where the source address space area size will be
1247
 
 *                      stored.
1248
 
 * @param flags         Storage where the sharing flags will be stored.
1249
 
 *
1250
 
 * @return              Non-zero on success, zero on failure.
 
1530
 * @param callid Storage for the hash of the IPC_M_SHARE_OUT call.
 
1531
 * @param size   Storage for the source address space area size.
 
1532
 * @param flags  Storage for the sharing flags.
 
1533
 *
 
1534
 * @return True on success, false on failure.
 
1535
 *
1251
1536
 */
1252
 
int async_share_out_receive(ipc_callid_t *callid, size_t *size, int *flags)
 
1537
bool async_share_out_receive(ipc_callid_t *callid, size_t *size, unsigned int *flags)
1253
1538
{
1254
 
        ipc_call_t data;
1255
 
        
1256
1539
        assert(callid);
1257
1540
        assert(size);
1258
1541
        assert(flags);
1259
 
 
 
1542
        
 
1543
        ipc_call_t data;
1260
1544
        *callid = async_get_call(&data);
 
1545
        
1261
1546
        if (IPC_GET_IMETHOD(data) != IPC_M_SHARE_OUT)
1262
 
                return 0;
 
1547
                return false;
 
1548
        
1263
1549
        *size = (size_t) IPC_GET_ARG2(data);
1264
 
        *flags = (int) IPC_GET_ARG3(data);
1265
 
        return 1;
 
1550
        *flags = (unsigned int) IPC_GET_ARG3(data);
 
1551
        return true;
1266
1552
}
1267
1553
 
1268
1554
/** Wrapper for answering the IPC_M_SHARE_OUT calls using the async framework.
1269
1555
 *
1270
 
 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT calls
1271
 
 * so that the user doesn't have to remember the meaning of each IPC argument.
1272
 
 *
1273
 
 * @param callid        Hash of the IPC_M_DATA_WRITE call to answer.
1274
 
 * @param dst           Destination address space area base address.    
1275
 
 *
1276
 
 * @return              Zero on success or a value from @ref errno.h on failure.
 
1556
 * This wrapper only makes it more comfortable to answer IPC_M_SHARE_OUT
 
1557
 * calls so that the user doesn't have to remember the meaning of each IPC
 
1558
 * argument.
 
1559
 *
 
1560
 * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
 
1561
 * @param dst    Destination address space area base address.
 
1562
 *
 
1563
 * @return Zero on success or a value from @ref errno.h on failure.
 
1564
 *
1277
1565
 */
1278
1566
int async_share_out_finalize(ipc_callid_t callid, void *dst)
1279
1567
{
1280
1568
        return ipc_share_out_finalize(callid, dst);
1281
1569
}
1282
1570
 
1283
 
 
1284
 
/** Wrapper for making IPC_M_DATA_READ calls using the async framework.
1285
 
 *
1286
 
 * @param phoneid       Phone that will be used to contact the receiving side.
1287
 
 * @param dst           Address of the beginning of the destination buffer.
1288
 
 * @param size          Size of the destination buffer.
1289
 
 *
1290
 
 * @return              Zero on success or a negative error code from errno.h.
 
1571
/** Wrapper for IPC_M_DATA_READ calls using the async framework.
 
1572
 *
 
1573
 * @param phoneid Phone that will be used to contact the receiving side.
 
1574
 * @param dst     Address of the beginning of the destination buffer.
 
1575
 * @param size    Size of the destination buffer.
 
1576
 * @param flags   Flags to control the data transfer.
 
1577
 *
 
1578
 * @return Zero on success or a negative error code from errno.h.
 
1579
 *
1291
1580
 */
1292
 
int async_data_read_start(int phoneid, void *dst, size_t size)
 
1581
int
 
1582
async_data_read_start_generic(int phoneid, void *dst, size_t size, int flags)
1293
1583
{
1294
 
        return async_req_2_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
1295
 
            (sysarg_t) size);
 
1584
        return async_req_3_0(phoneid, IPC_M_DATA_READ, (sysarg_t) dst,
 
1585
            (sysarg_t) size, (sysarg_t) flags);
1296
1586
}
1297
1587
 
1298
1588
/** Wrapper for receiving the IPC_M_DATA_READ calls using the async framework.
1299
1589
 *
1300
 
 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ calls
1301
 
 * so that the user doesn't have to remember the meaning of each IPC argument.
 
1590
 * This wrapper only makes it more comfortable to receive IPC_M_DATA_READ
 
1591
 * calls so that the user doesn't have to remember the meaning of each IPC
 
1592
 * argument.
1302
1593
 *
1303
1594
 * So far, this wrapper is to be used from within a connection fibril.
1304
1595
 *
1305
 
 * @param callid        Storage where the hash of the IPC_M_DATA_READ call will
1306
 
 *                      be stored.
1307
 
 * @param size          Storage where the maximum size will be stored. Can be
1308
 
 *                      NULL.
1309
 
 *
1310
 
 * @return              Non-zero on success, zero on failure.
 
1596
 * @param callid Storage for the hash of the IPC_M_DATA_READ.
 
1597
 * @param size   Storage for the maximum size. Can be NULL.
 
1598
 *
 
1599
 * @return True on success, false on failure.
 
1600
 *
1311
1601
 */
1312
 
int async_data_read_receive(ipc_callid_t *callid, size_t *size)
 
1602
bool async_data_read_receive(ipc_callid_t *callid, size_t *size)
1313
1603
{
 
1604
        assert(callid);
 
1605
        
1314
1606
        ipc_call_t data;
1315
 
        
1316
 
        assert(callid);
1317
 
 
1318
1607
        *callid = async_get_call(&data);
 
1608
        
1319
1609
        if (IPC_GET_IMETHOD(data) != IPC_M_DATA_READ)
1320
 
                return 0;
 
1610
                return false;
 
1611
        
1321
1612
        if (size)
1322
1613
                *size = (size_t) IPC_GET_ARG2(data);
1323
 
        return 1;
 
1614
        
 
1615
        return true;
1324
1616
}
1325
1617
 
1326
1618
/** Wrapper for answering the IPC_M_DATA_READ calls using the async framework.
1327
1619
 *
1328
 
 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ calls
1329
 
 * so that the user doesn't have to remember the meaning of each IPC argument.
1330
 
 *
1331
 
 * @param callid        Hash of the IPC_M_DATA_READ call to answer.
1332
 
 * @param src           Source address for the IPC_M_DATA_READ call.
1333
 
 * @param size          Size for the IPC_M_DATA_READ call. Can be smaller than
1334
 
 *                      the maximum size announced by the sender.
1335
 
 *
1336
 
 * @return              Zero on success or a value from @ref errno.h on failure.
 
1620
 * This wrapper only makes it more comfortable to answer IPC_M_DATA_READ
 
1621
 * calls so that the user doesn't have to remember the meaning of each IPC
 
1622
 * argument.
 
1623
 *
 
1624
 * @param callid Hash of the IPC_M_DATA_READ call to answer.
 
1625
 * @param src    Source address for the IPC_M_DATA_READ call.
 
1626
 * @param size   Size for the IPC_M_DATA_READ call. Can be smaller than
 
1627
 *               the maximum size announced by the sender.
 
1628
 *
 
1629
 * @return Zero on success or a value from @ref errno.h on failure.
 
1630
 *
1337
1631
 */
1338
1632
int async_data_read_finalize(ipc_callid_t callid, const void *src, size_t size)
1339
1633
{
1342
1636
 
1343
1637
/** Wrapper for forwarding any read request
1344
1638
 *
1345
 
 *
1346
1639
 */
1347
1640
int async_data_read_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
1348
1641
    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)
1374
1667
        return (int) rc;
1375
1668
}
1376
1669
 
1377
 
/** Wrapper for making IPC_M_DATA_WRITE calls using the async framework.
 
1670
/** Wrapper for IPC_M_DATA_WRITE calls using the async framework.
1378
1671
 *
1379
1672
 * @param phoneid Phone that will be used to contact the receiving side.
1380
1673
 * @param src     Address of the beginning of the source buffer.
1381
1674
 * @param size    Size of the source buffer.
 
1675
 * @param flags   Flags to control the data transfer.
1382
1676
 *
1383
1677
 * @return Zero on success or a negative error code from errno.h.
1384
1678
 *
1385
1679
 */
1386
 
int async_data_write_start(int phoneid, const void *src, size_t size)
 
1680
int
 
1681
async_data_write_start_generic(int phoneid, const void *src, size_t size,
 
1682
    int flags)
1387
1683
{
1388
 
        return async_req_2_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
1389
 
            (sysarg_t) size);
 
1684
        return async_req_3_0(phoneid, IPC_M_DATA_WRITE, (sysarg_t) src,
 
1685
            (sysarg_t) size, (sysarg_t) flags);
1390
1686
}
1391
1687
 
1392
1688
/** Wrapper for receiving the IPC_M_DATA_WRITE calls using the async framework.
1393
1689
 *
1394
 
 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE calls
1395
 
 * so that the user doesn't have to remember the meaning of each IPC argument.
 
1690
 * This wrapper only makes it more comfortable to receive IPC_M_DATA_WRITE
 
1691
 * calls so that the user doesn't have to remember the meaning of each IPC
 
1692
 * argument.
1396
1693
 *
1397
1694
 * So far, this wrapper is to be used from within a connection fibril.
1398
1695
 *
1399
 
 * @param callid Storage where the hash of the IPC_M_DATA_WRITE call will
1400
 
 *               be stored.
1401
 
 * @param size   Storage where the suggested size will be stored. May be
1402
 
 *               NULL
 
1696
 * @param callid Storage for the hash of the IPC_M_DATA_WRITE.
 
1697
 * @param size   Storage for the suggested size. May be NULL.
1403
1698
 *
1404
 
 * @return Non-zero on success, zero on failure.
 
1699
 * @return True on success, false on failure.
1405
1700
 *
1406
1701
 */
1407
 
int async_data_write_receive(ipc_callid_t *callid, size_t *size)
 
1702
bool async_data_write_receive(ipc_callid_t *callid, size_t *size)
1408
1703
{
 
1704
        assert(callid);
 
1705
        
1409
1706
        ipc_call_t data;
1410
 
        
1411
 
        assert(callid);
1412
 
        
1413
1707
        *callid = async_get_call(&data);
 
1708
        
1414
1709
        if (IPC_GET_IMETHOD(data) != IPC_M_DATA_WRITE)
1415
 
                return 0;
 
1710
                return false;
1416
1711
        
1417
1712
        if (size)
1418
1713
                *size = (size_t) IPC_GET_ARG2(data);
1419
1714
        
1420
 
        return 1;
 
1715
        return true;
1421
1716
}
1422
1717
 
1423
1718
/** Wrapper for answering the IPC_M_DATA_WRITE calls using the async framework.
1424
1719
 *
1425
 
 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE calls
1426
 
 * so that the user doesn't have to remember the meaning of each IPC argument.
 
1720
 * This wrapper only makes it more comfortable to answer IPC_M_DATA_WRITE
 
1721
 * calls so that the user doesn't have to remember the meaning of each IPC
 
1722
 * argument.
1427
1723
 *
1428
1724
 * @param callid Hash of the IPC_M_DATA_WRITE call to answer.
1429
1725
 * @param dst    Final destination address for the IPC_M_DATA_WRITE call.
1519
1815
 * @param retval Error value from @ref errno.h to be returned to the caller.
1520
1816
 *
1521
1817
 */
1522
 
void async_data_write_void(const int retval)
 
1818
void async_data_write_void(sysarg_t retval)
1523
1819
{
1524
1820
        ipc_callid_t callid;
1525
1821
        async_data_write_receive(&callid, NULL);
1528
1824
 
1529
1825
/** Wrapper for forwarding any data that is about to be received
1530
1826
 *
1531
 
 *
1532
1827
 */
1533
1828
int async_data_write_forward_fast(int phoneid, sysarg_t method, sysarg_t arg1,
1534
1829
    sysarg_t arg2, sysarg_t arg3, sysarg_t arg4, ipc_call_t *dataptr)