Changeset 8b243f2 in mainline


Ignore:
Timestamp:
2007-06-17T19:34:36Z (17 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
bd72c3e9
Parents:
4680ef5
Message:

Greatly improve comments in the IPC layer.
Now I think I finally start to understand our IPC internals :-)

Files:
12 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/ipc/ipc.h

    r4680ef5 r8b243f2  
    3838/* Length of data being transfered with IPC call */
    3939/* - the uspace may not be able to utilize full length */
    40 #define IPC_CALL_LEN    4
     40#define IPC_CALL_LEN            4
    4141
    4242/** Maximum active async calls per thread */
    4343#ifdef CONFIG_DEBUG
    44 # define IPC_MAX_ASYNC_CALLS  4
     44#define IPC_MAX_ASYNC_CALLS     4
    4545#else
    46 # define IPC_MAX_ASYNC_CALLS  4000
     46#define IPC_MAX_ASYNC_CALLS     4000
    4747#endif
    4848
     
    6262#define IPC_CALL_NOTIF          (1 << 5)
    6363
    64 /* Flags of callid (the addresses are aligned at least to 4,
    65  * that is why we can use bottom 2 bits of the call address
    66  */
    67 /** Type of this msg is 'answer' */
     64/*
     65 * Bits used in call hashes.
     66 * The addresses are aligned at least to 4 that is why we can use the 2 least
     67 * significant bits of the call address.
     68 */
     69/** Type of this call is 'answer' */
    6870#define IPC_CALLID_ANSWERED     1
    69 /** Type of this msg is 'notification' */
     71/** Type of this call is 'notification' */
    7072#define IPC_CALLID_NOTIFICATION 2
    7173
    72 /* Return values from IPC_ASYNC */
     74/* Return values from sys_ipc_call_async(). */
    7375#define IPC_CALLRET_FATAL       -1
    7476#define IPC_CALLRET_TEMPORARY   -2
     
    112114 *                     - the caller obtains taskid of the called thread
    113115 */
    114 #define IPC_M_CONNECT_TO_ME     1
     116#define IPC_M_CONNECT_TO_ME     1
    115117/** Protocol for CONNECT - ME - TO
    116118 *
     
    131133 *
    132134 */
    133 #define IPC_M_CONNECT_ME_TO     2
     135#define IPC_M_CONNECT_ME_TO     2
    134136/** This message is sent to answerbox when the phone
    135137 * is hung up
    136138 */
    137 #define IPC_M_PHONE_HUNGUP      3
     139#define IPC_M_PHONE_HUNGUP      3
    138140
    139141/** Send as_area over IPC
     
    145147 * - ARG1 - dst as_area base adress
    146148 */
    147 #define IPC_M_AS_AREA_SEND      5
     149#define IPC_M_AS_AREA_SEND      5
    148150
    149151/** Get as_area over IPC
     
    157159 * - ARG2 - flags that will be used for sharing
    158160 */
    159 #define IPC_M_AS_AREA_RECV      6
     161#define IPC_M_AS_AREA_RECV      6
    160162
    161163
    162164/* Well-known methods */
    163 #define IPC_M_LAST_SYSTEM     511
    164 #define IPC_M_PING            512
     165#define IPC_M_LAST_SYSTEM       511
     166#define IPC_M_PING              512
    165167/* User methods */
    166 #define FIRST_USER_METHOD     1024
     168#define FIRST_USER_METHOD       1024
    167169
    168170#ifdef KERNEL
     
    204206        waitq_t wq;
    205207
    206         /** Phones connected to this answerbox */
     208        /** Phones connected to this answerbox. */
    207209        link_t connected_phones;
    208         /** Received calls */
     210        /** Received calls. */
    209211        link_t calls;                   
    210212        link_t dispatched_calls;        /* Should be hash table in the future */
    211213
    212         /** Answered calls */
     214        /** Answered calls. */
    213215        link_t answers;
    214216
    215217        SPINLOCK_DECLARE(irq_lock);
    216         /** Notifications from IRQ handlers */
     218        /** Notifications from IRQ handlers. */
    217219        link_t irq_notifs;
    218220        /** IRQs with notifications to this answerbox. */
     
    230232        int flags;
    231233
    232         /* Identification of the caller */
     234        /** Identification of the caller. */
    233235        struct task *sender;
    234         /* The caller box is different from sender->answerbox
    235          * for synchronous calls
    236          */
     236        /** The caller box is different from sender->answerbox for synchronous
     237         *  calls. */
    237238        answerbox_t *callerbox;
    238239
    239         /** Private data to internal IPC */
     240        /** Private data to internal IPC. */
    240241        unative_t priv;
    241242
    242         /** Data passed from/to userspace */
     243        /** Data passed from/to userspace. */
    243244        ipc_data_t data;
    244245} call_t;
  • kernel/generic/include/ipc/ipcrsc.h

    r4680ef5 r8b243f2  
    3636#define KERN_IPCRSC_H_
    3737
    38 call_t * get_call(unative_t callid);
    39 int phone_alloc(void);
    40 void phone_connect(int phoneid, answerbox_t *box);
    41 void phone_dealloc(int phoneid);
     38extern call_t * get_call(unative_t callid);
     39extern int phone_alloc(void);
     40extern void phone_connect(int phoneid, answerbox_t *box);
     41extern void phone_dealloc(int phoneid);
    4242
    4343#endif
  • kernel/generic/include/ipc/irq.h

    r4680ef5 r8b243f2  
    3737
    3838/** Maximum length of IPC IRQ program */
    39 #define IRQ_MAX_PROG_SIZE 10
     39#define IRQ_MAX_PROG_SIZE       10
    4040
    4141#include <ipc/ipc.h>
     
    4747    unative_t method, irq_code_t *ucode);
    4848extern void ipc_irq_send_notif(irq_t *irq);
    49 extern void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3);
     49extern void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2,
     50    unative_t a3);
    5051extern void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno);
    5152extern void ipc_irq_cleanup(answerbox_t *box);
  • kernel/generic/src/ipc/ipc.c

    r4680ef5 r8b243f2  
    3535/* Lock ordering
    3636 *
    37  * First the answerbox, then the phone
     37 * First the answerbox, then the phone.
    3838 */
    3939
     
    5454#include <ipc/irq.h>
    5555
    56 /* Open channel that is assigned automatically to new tasks */
     56/** Open channel that is assigned automatically to new tasks */
    5757answerbox_t *ipc_phone_0 = NULL;
    5858
    5959static slab_cache_t *ipc_call_slab;
    6060
    61 /* Initialize new call */
     61/** Initialize a call structure.
     62 *
     63 * @param call          Call structure to be initialized.
     64 */
    6265static void _ipc_call_init(call_t *call)
    6366{
    64         memsetb((uintptr_t)call, sizeof(*call), 0);
     67        memsetb((uintptr_t) call, sizeof(*call), 0);
    6568        call->callerbox = &TASK->answerbox;
    6669        call->sender = TASK;
    6770}
    6871
    69 /** Allocate & initialize call structure
     72/** Allocate and initialize a call structure.
    7073 *
    71  * The call is initialized, so that the reply will be directed
    72  * to TASK->answerbox
    73  *
    74  * @param flags Parameters for slab_alloc (ATOMIC, etc.)
    75  */
    76 call_t * ipc_call_alloc(int flags)
     74 * The call is initialized, so that the reply will be directed to
     75 * TASK->answerbox.
     76 *
     77 * @param flags         Parameters for slab_alloc (e.g FRAME_ATOMIC).
     78 *
     79 * @return              If flags permit it, return NULL, or initialized kernel
     80 *                      call structure.
     81 */
     82call_t *ipc_call_alloc(int flags)
    7783{
    7884        call_t *call;
     
    8490}
    8591
    86 /** Initialize allocated call */
     92/** Initialize a statically allocated call structure.
     93 *
     94 * @param call          Statically allocated kernel call structure to be
     95 *                      initialized.
     96 */
    8797void ipc_call_static_init(call_t *call)
    8898{
     
    91101}
    92102
    93 /** Deallocate call stracuture */
     103/** Deallocate a call stracuture.
     104 *
     105 * @param call          Call structure to be freed.
     106 */
    94107void ipc_call_free(call_t *call)
    95108{
     109        ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
    96110        slab_free(ipc_call_slab, call);
    97111}
    98112
    99 /** Initialize answerbox structure
     113/** Initialize an answerbox structure.
     114 *
     115 * @param box           Answerbox structure to be initialized.
    100116 */
    101117void ipc_answerbox_init(answerbox_t *box)
     
    113129}
    114130
    115 /** Connect phone to answerbox */
     131/** Connect a phone to an answerbox.
     132 *
     133 * @param phone         Initialized phone structure.
     134 * @param box           Initialized answerbox structure.
     135 */
    116136void ipc_phone_connect(phone_t *phone, answerbox_t *box)
    117137{
     
    128148}
    129149
    130 /** Initialize phone structure and connect phone to answerbox
     150/** Initialize a phone structure.
     151 *
     152 * @param phone         Phone structure to be initialized.
    131153 */
    132154void ipc_phone_init(phone_t *phone)
     
    138160}
    139161
    140 /** Helper function to facilitate synchronous calls */
     162/** Helper function to facilitate synchronous calls.
     163 *
     164 * @param phone         Destination kernel phone structure.
     165 * @param request       Call structure with request.
     166 */
    141167void ipc_call_sync(phone_t *phone, call_t *request)
    142168{
     
    145171        ipc_answerbox_init(&sync_box);
    146172
    147         /* We will receive data on special box */
     173        /* We will receive data in a special box. */
    148174        request->callerbox = &sync_box;
    149175
     
    152178}
    153179
    154 /** Answer message that was not dispatched and is not entered in
    155  * any queue
     180/** Answer a message which was not dispatched and is not listed in any queue.
     181 *
     182 * @param call          Call structure to be answered.
    156183 */
    157184static void _ipc_answer_free_call(call_t *call)
     
    167194}
    168195
    169 /** Answer message, that is in callee queue
    170  *
    171  * @param box Answerbox that is answering the message
    172  * @param call Modified request that is being sent back
     196/** Answer a message which is in a callee queue.
     197 *
     198 * @param box           Answerbox that is answering the message.
     199 * @param call          Modified request that is being sent back.
    173200 */
    174201void ipc_answer(answerbox_t *box, call_t *call)
     
    182209}
    183210
    184 /** Simulate sending back a message
     211/** Simulate sending back a message.
    185212 *
    186213 * Most errors are better handled by forming a normal backward
    187214 * message and sending it as a normal answer.
     215 *
     216 * @param phone         Phone structure the call should appear to come from.
     217 * @param call          Call structure to be answered.
     218 * @param err           Return value to be used for the answer.
    188219 */
    189220void ipc_backsend_err(phone_t *phone, call_t *call, unative_t err)
     
    195226}
    196227
    197 /* Unsafe unchecking ipc_call */
     228/** Unsafe unchecking version of ipc_call.
     229 *
     230 * @param phone         Phone structure the call comes from.
     231 * @param box           Destination answerbox structure.
     232 */
    198233static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call)
    199234{
    200         if (! (call->flags & IPC_CALL_FORWARDED)) {
     235        if (!(call->flags & IPC_CALL_FORWARDED)) {
    201236                atomic_inc(&phone->active_calls);
    202237                call->data.phone = phone;
     
    209244}
    210245
    211 /** Send a asynchronous request using phone to answerbox
    212  *
    213  * @param phone Phone connected to answerbox.
    214  * @param call Structure representing the call.
     246/** Send an asynchronous request using a phone to an answerbox.
     247 *
     248 * @param phone         Phone structure the call comes from and which is
     249 *                      connected to the destination answerbox.
     250 * @param call          Call structure with request.
     251 *
     252 * @return              Return 0 on success, ENOENT on error.
    215253 */
    216254int ipc_call(phone_t *phone, call_t *call)
     
    239277}
    240278
    241 /** Disconnect phone from answerbox
    242  *
    243  * This call leaves the phone in HUNGUP state. The change to 'free' is done
     279/** Disconnect phone from answerbox.
     280 *
     281 * This call leaves the phone in the HUNGUP state. The change to 'free' is done
    244282 * lazily later.
    245283 *
    246  * @param phone Phone to be hung up
     284 * @param phone         Phone structure to be hung up.
    247285 *             
    248  * @return 0 - phone disconnected, -1 - the phone was already disconnected
     286 * @return              Return 0 if the phone is disconnected.
     287 *                      Return -1 if the phone was already disconnected.
    249288 */
    250289int ipc_phone_hangup(phone_t *phone)
     
    254293       
    255294        spinlock_lock(&phone->lock);
    256         if (phone->state == IPC_PHONE_FREE || phone->state ==IPC_PHONE_HUNGUP \
    257             || phone->state == IPC_PHONE_CONNECTING) {
     295        if (phone->state == IPC_PHONE_FREE || phone->state == IPC_PHONE_HUNGUP ||
     296            phone->state == IPC_PHONE_CONNECTING) {
    258297                spinlock_unlock(&phone->lock);
    259298                return -1;
     
    280319}
    281320
    282 /** Forwards call from one answerbox to a new one
    283  *
    284  * @param call Call to be redirected.
    285  * @param newphone Phone to target answerbox.
    286  * @param oldbox Old answerbox
    287  * @return 0 on forward ok, error code, if there was error
     321/** Forwards call from one answerbox to another one.
     322 *
     323 * @param call          Call structure to be redirected.
     324 * @param newphone      Phone structure to target answerbox.
     325 * @param oldbox        Old answerbox structure.
     326 *
     327 * @return              Return 0 if forwarding succeeded or an error code if
     328 *                      there was error.
    288329 *
    289  * - the return value serves only as an information for the forwarder,
    290  *   the original caller is notified automatically with EFORWARD
     330 * The return value serves only as an information for the forwarder,
     331 * the original caller is notified automatically with EFORWARD.
    291332 */
    292333int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox)
     
    300341
    301342
    302 /** Wait for phone call
    303  *
    304  * @param box Answerbox expecting the call.
    305  * @param usec Timeout in microseconds. See documentation for waitq_sleep_timeout() for
    306  *             decription of its special meaning.
    307  * @param flags Select mode of sleep operation. See documentation for waitq_sleep_timeout()i
    308  *              for description of its special meaning.
    309  * @return Recived message address
    310  * - to distinguish between call and answer, look at call->flags
    311  */
    312 call_t * ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags)
     343/** Wait for a phone call.
     344 *
     345 * @param box           Answerbox expecting the call.
     346 * @param usec          Timeout in microseconds. See documentation for
     347 *                      waitq_sleep_timeout() for decription of its special
     348 *                      meaning.
     349 * @param flags         Select mode of sleep operation. See documentation for
     350 *                      waitq_sleep_timeout() for description of its special
     351 *                      meaning.
     352 * @return              Recived call structure or NULL.
     353 *
     354 * To distinguish between a call and an answer, have a look at call->flags.
     355 */
     356call_t *ipc_wait_for_call(answerbox_t *box, uint32_t usec, int flags)
    313357{
    314358        call_t *request;
     
    351395}
    352396
    353 /** Answer all calls from list with EHANGUP msg */
     397/** Answer all calls from list with EHANGUP answer.
     398 *
     399 * @param lst           Head of the list to be cleaned up.
     400 */
    354401static void ipc_cleanup_call_list(link_t *lst)
    355402{
     
    365412}
    366413
    367 /** Cleans up all IPC communication of the current task
     414/** Cleans up all IPC communication of the current task.
    368415 *
    369416 * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you
    370  * have to change it as well if you want to cleanup other current then current.
     417 * have to change it as well if you want to cleanup other tasks than TASK.
    371418 */
    372419void ipc_cleanup(void)
     
    378425
    379426        /* Disconnect all our phones ('ipc_phone_hangup') */
    380         for (i=0;i < IPC_MAX_PHONES; i++)
     427        for (i = 0; i < IPC_MAX_PHONES; i++)
    381428                ipc_phone_hangup(&TASK->phones[i]);
    382429
     
    414461                /* Locking not needed, no one else should modify
    415462                 * it, when we are in cleanup */
    416                 for (i=0;i < IPC_MAX_PHONES; i++) {
    417                         if (TASK->phones[i].state == IPC_PHONE_HUNGUP && \
     463                for (i = 0; i < IPC_MAX_PHONES; i++) {
     464                        if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
    418465                            atomic_get(&TASK->phones[i].active_calls) == 0)
    419466                                TASK->phones[i].state = IPC_PHONE_FREE;
     
    434481                        break;
    435482               
    436                 call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
    437                 ASSERT((call->flags & IPC_CALL_ANSWERED) || (call->flags & IPC_CALL_NOTIF));
    438                 ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
     483                call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT,
     484                    SYNCH_FLAGS_NONE);
     485                ASSERT((call->flags & IPC_CALL_ANSWERED) ||
     486                    (call->flags & IPC_CALL_NOTIF));
     487                ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
    439488               
    440489                atomic_dec(&TASK->active_calls);
     
    447496void ipc_init(void)
    448497{
    449         ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL, NULL, 0);
    450 }
    451 
    452 
    453 /** Kconsole - list answerbox contents */
     498        ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL,
     499            NULL, 0);
     500}
     501
     502
     503/** List answerbox contents.
     504 *
     505 * @param taskid        Task ID.
     506 */
    454507void ipc_print_task(task_id_t taskid)
    455508{
     
    469522        /* Print opened phones & details */
    470523        printf("PHONE:\n");
    471         for (i=0; i < IPC_MAX_PHONES;i++) {
     524        for (i = 0; i < IPC_MAX_PHONES; i++) {
    472525                spinlock_lock(&task->phones[i].lock);
    473526                if (task->phones[i].state != IPC_PHONE_FREE) {
    474                         printf("%d: ",i);
     527                        printf("%d: ", i);
    475528                        switch (task->phones[i].state) {
    476529                        case IPC_PHONE_CONNECTING:
  • kernel/generic/src/ipc/ipcrsc.c

    r4680ef5 r8b243f2  
    133133#include <debug.h>
    134134
    135 /** Find call_t * in call table according to callid
    136  *
    137  * TODO: Some speedup (hash table?)
    138  * @return NULL on not found, otherwise pointer to call structure
    139  */
    140 call_t * get_call(unative_t callid)
     135/** Find call_t * in call table according to callid.
     136 *
     137 * @todo Some speedup (hash table?)
     138 *
     139 * @param callid        Userspace hash of the call. Currently it is the call
     140 *                      structure kernel address.
     141 *
     142 * @return              NULL on not found, otherwise pointer to the call
     143 *                      structure.
     144 */
     145call_t *get_call(unative_t callid)
    141146{
    142147        link_t *lst;
     
    145150        spinlock_lock(&TASK->answerbox.lock);
    146151        for (lst = TASK->answerbox.dispatched_calls.next;
    147              lst != &TASK->answerbox.dispatched_calls; lst = lst->next) {
     152            lst != &TASK->answerbox.dispatched_calls; lst = lst->next) {
    148153                call = list_get_instance(lst, call_t, link);
    149                 if ((unative_t)call == callid) {
     154                if ((unative_t) call == callid) {
    150155                        result = call;
    151156                        break;
     
    156161}
    157162
    158 /** Allocate new phone slot in current TASK structure */
     163/** Allocate new phone slot in the current TASK structure.
     164 *
     165 * @return              New phone handle or -1 if the phone handle limit is
     166 *                      exceeded.
     167 */
    159168int phone_alloc(void)
    160169{
     
    163172        spinlock_lock(&TASK->lock);
    164173       
    165         for (i=0; i < IPC_MAX_PHONES; i++) {
    166                 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && \
     174        for (i = 0; i < IPC_MAX_PHONES; i++) {
     175                if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
    167176                    atomic_get(&TASK->phones[i].active_calls) == 0)
    168177                        TASK->phones[i].state = IPC_PHONE_FREE;
     
    180189}
    181190
     191/** Mark a phone structure free.
     192 *
     193 * @param phone         Phone structure to be marked free.
     194 */
    182195static void phone_deallocp(phone_t *phone)
    183196{
     
    188201}
    189202
    190 /** Free slot from a disconnected phone
    191  *
    192  * All already sent messages will be correctly processed
     203/** Free slot from a disconnected phone.
     204 *
     205 * All already sent messages will be correctly processed.
     206 *
     207 * @param phoneid       Phone handle of the phone to be freed.
    193208 */
    194209void phone_dealloc(int phoneid)
     
    197212}
    198213
    199 /** Connect phone to a given answerbox
    200  *
    201  * @param phoneid The slot that will be connected
     214/** Connect phone to a given answerbox.
     215 *
     216 * @param phoneid       Phone handle to be connected.
     217 * @param box           Answerbox to which to connect the phone handle.
    202218 *
    203219 * The procedure _enforces_ that the user first marks the phone
  • kernel/generic/src/ipc/irq.c

    r4680ef5 r8b243f2  
    6161/** Execute code associated with IRQ notification.
    6262 *
    63  * @param call Notification call.
    64  * @param code Top-half pseudocode.
     63 * @param call          Notification call.
     64 * @param code          Top-half pseudocode.
    6565 */
    6666static void code_execute(call_t *call, irq_code_t *code)
     
    7272                return;
    7373       
    74         for (i=0; i < code->cmdcount;i++) {
     74        for (i = 0; i < code->cmdcount; i++) {
    7575                switch (code->cmds[i].cmd) {
    7676                case CMD_MEM_READ_1:
    77                         dstval = *((uint8_t *)code->cmds[i].addr);
     77                        dstval = *((uint8_t *) code->cmds[i].addr);
    7878                        break;
    7979                case CMD_MEM_READ_2:
    80                         dstval = *((uint16_t *)code->cmds[i].addr);
     80                        dstval = *((uint16_t *) code->cmds[i].addr);
    8181                        break;
    8282                case CMD_MEM_READ_4:
    83                         dstval = *((uint32_t *)code->cmds[i].addr);
     83                        dstval = *((uint32_t *) code->cmds[i].addr);
    8484                        break;
    8585                case CMD_MEM_READ_8:
    86                         dstval = *((uint64_t *)code->cmds[i].addr);
     86                        dstval = *((uint64_t *) code->cmds[i].addr);
    8787                        break;
    8888                case CMD_MEM_WRITE_1:
    89                         *((uint8_t *)code->cmds[i].addr) = code->cmds[i].value;
     89                        *((uint8_t *) code->cmds[i].addr) = code->cmds[i].value;
    9090                        break;
    9191                case CMD_MEM_WRITE_2:
    92                         *((uint16_t *)code->cmds[i].addr) = code->cmds[i].value;
     92                        *((uint16_t *) code->cmds[i].addr) = code->cmds[i].value;
    9393                        break;
    9494                case CMD_MEM_WRITE_4:
    95                         *((uint32_t *)code->cmds[i].addr) = code->cmds[i].value;
     95                        *((uint32_t *) code->cmds[i].addr) = code->cmds[i].value;
    9696                        break;
    9797                case CMD_MEM_WRITE_8:
    98                         *((uint64_t *)code->cmds[i].addr) = code->cmds[i].value;
     98                        *((uint64_t *) code->cmds[i].addr) = code->cmds[i].value;
    9999                        break;
    100100#if defined(ia32) || defined(amd64)
    101101                case CMD_PORT_READ_1:
    102                         dstval = inb((long)code->cmds[i].addr);
     102                        dstval = inb((long) code->cmds[i].addr);
    103103                        break;
    104104                case CMD_PORT_WRITE_1:
    105                         outb((long)code->cmds[i].addr, code->cmds[i].value);
     105                        outb((long) code->cmds[i].addr, code->cmds[i].value);
    106106                        break;
    107107#endif
     
    125125}
    126126
     127/** Free top-half pseudocode.
     128 *
     129 * @param code          Pointer to the top-half pseudocode.
     130 */
    127131static void code_free(irq_code_t *code)
    128132{
     
    133137}
    134138
    135 static irq_code_t * code_from_uspace(irq_code_t *ucode)
     139/** Copy top-half pseudocode from userspace into the kernel.
     140 *
     141 * @param ucode         Userspace address of the top-half pseudocode.
     142 *
     143 * @return              Kernel address of the copied pseudocode.
     144 */
     145static irq_code_t *code_from_uspace(irq_code_t *ucode)
    136146{
    137147        irq_code_t *code;
     
    151161        }
    152162        ucmds = code->cmds;
    153         code->cmds = malloc(sizeof(code->cmds[0]) * (code->cmdcount), 0);
    154         rc = copy_from_uspace(code->cmds, ucmds, sizeof(code->cmds[0]) * (code->cmdcount));
     163        code->cmds = malloc(sizeof(code->cmds[0]) * code->cmdcount, 0);
     164        rc = copy_from_uspace(code->cmds, ucmds,
     165            sizeof(code->cmds[0]) * code->cmdcount);
    155166        if (rc != 0) {
    156167                free(code->cmds);
     
    164175/** Unregister task from IRQ notification.
    165176 *
    166  * @param box Answerbox associated with the notification.
    167  * @param inr IRQ numbe.
    168  * @param devno Device number.
     177 * @param box           Answerbox associated with the notification.
     178 * @param inr           IRQ number.
     179 * @param devno         Device number.
    169180 */
    170181void ipc_irq_unregister(answerbox_t *box, inr_t inr, devno_t devno)
     
    196207/** Register an answerbox as a receiving end for IRQ notifications.
    197208 *
    198  * @param box Receiving answerbox.
    199  * @param inr IRQ number.
    200  * @param devno Device number.
    201  * @param method Method to be associated with the notification.
    202  * @param ucode Uspace pointer to top-half pseudocode.
    203  *
    204  * @return EBADMEM, ENOENT or EEXISTS on failure or 0 on success.
    205  */
    206 int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno, unative_t method, irq_code_t *ucode)
     209 * @param box           Receiving answerbox.
     210 * @param inr           IRQ number.
     211 * @param devno         Device number.
     212 * @param method        Method to be associated with the notification.
     213 * @param ucode         Uspace pointer to top-half pseudocode.
     214 *
     215 * @return              EBADMEM, ENOENT or EEXISTS on failure or 0 on success.
     216 */
     217int ipc_irq_register(answerbox_t *box, inr_t inr, devno_t devno,
     218    unative_t method, irq_code_t *ucode)
    207219{
    208220        ipl_t ipl;
     
    214226                if (!code)
    215227                        return EBADMEM;
    216         } else
     228        } else {
    217229                code = NULL;
     230        }
    218231
    219232        ipl = interrupts_disable();
     
    248261}
    249262
    250 /** Add call to proper answerbox queue.
     263/** Add a call to the proper answerbox queue.
    251264 *
    252265 * Assume irq->lock is locked.
    253266 *
     267 * @param irq           IRQ structure referencing the target answerbox.
     268 * @param call          IRQ notification call.
    254269 */
    255270static void send_call(irq_t *irq, call_t *call)
     
    262277}
    263278
    264 /** Send notification message
    265  *
     279/** Send notification message.
     280 *
     281 * @param irq           IRQ structure.
     282 * @param a1            Driver-specific payload argument.
     283 * @param a2            Driver-specific payload argument.
     284 * @param a3            Driver-specific payload argument.
    266285 */
    267286void ipc_irq_send_msg(irq_t *irq, unative_t a1, unative_t a2, unative_t a3)
     
    290309}
    291310
    292 /** Notify task that an irq had occurred.
     311/** Notify a task that an IRQ had occurred.
    293312 *
    294313 * We expect interrupts to be disabled and the irq->lock already held.
     314 *
     315 * @param irq           IRQ structure.
    295316 */
    296317void ipc_irq_send_notif(irq_t *irq)
     
    324345 * send notifications to it.
    325346 *
    326  * @param box Answerbox for which we want to carry out the cleanup.
     347 * @param box           Answerbox for which we want to carry out the cleanup.
    327348 */
    328349void ipc_irq_cleanup(answerbox_t *box)
  • kernel/generic/src/ipc/sysipc.c

    r4680ef5 r8b243f2  
    5050#include <print.h>
    5151
    52 #define GET_CHECK_PHONE(phone, phoneid, err) { \
    53       if (phoneid > IPC_MAX_PHONES) { err; } \
    54       phone = &TASK->phones[phoneid]; \
    55 }
    56 
    57 #define STRUCT_TO_USPACE(dst, src) copy_to_uspace(dst, src, sizeof(*(src)))
    58 
    59 /** Return true if the method is a system method */
     52#define GET_CHECK_PHONE(phone, phoneid, err) \
     53{ \
     54        if (phoneid > IPC_MAX_PHONES) { \
     55                err; \
     56        } \
     57        phone = &TASK->phones[phoneid]; \
     58}
     59
     60#define STRUCT_TO_USPACE(dst, src)      copy_to_uspace(dst, src, sizeof(*(src)))
     61
     62/** Decide if the method is a system method.
     63 *
     64 * @param method        Method to be decided.
     65 *
     66 * @return              Return 1 if the method is a system method.
     67 *                      Otherwise return 0.
     68 */
    6069static inline int is_system_method(unative_t method)
    6170{
     
    6574}
    6675
    67 /** Return true if the message with this method is forwardable
     76/** Decide if the message with this method is forwardable.
    6877 *
    6978 * - some system messages may be forwarded, for some of them
    7079 *   it is useless
     80 *
     81 * @param method        Method to be decided.
     82 *
     83 * @return              Return 1 if the method is forwardable.
     84 *                      Otherwise return 0.
    7185 */
    7286static inline int is_forwardable(unative_t method)
     
    7892}
    7993
    80 /****************************************************/
    81 /* Functions that preprocess answer before sending
    82  * it to the recepient
    83  */
    84 
    85 /** Return true if the caller (ipc_answer) should save
    86  * the old call contents for answer_preprocess
     94
     95/***********************************************************************
     96 * Functions that preprocess answer before sending it to the recepient.
     97 ***********************************************************************/
     98
     99/** Decide if the caller (e.g. ipc_answer()) should save the old call contents
     100 * for answer_preprocess().
     101 *
     102 * @param call          Call structure to be decided.
     103 *
     104 * @return              Return 1 if the old call contents should be saved.
     105 *                      Return 0 otherwise.
    87106 */
    88107static inline int answer_need_old(call_t *call)
     
    99118}
    100119
    101 /** Interpret process answer as control information
    102  *
    103  * This function is called directly after sys_ipc_answer
     120/** Interpret process answer as control information.
     121 *
     122 * This function is called directly after sys_ipc_answer().
     123 *
     124 * @param answer        Call structure with the answer.
     125 * @param olddata       Saved data of the request.
     126 *
     127 * @return              Return 0 on success or an error code.
    104128 */
    105129static inline int answer_preprocess(call_t *answer, ipc_data_t *olddata)
     
    132156                        /* The connection was accepted */
    133157                        phone_connect(phoneid, &answer->sender->answerbox);
    134                         /* Set 'phone identification' as arg3 of response */
     158                        /* Set 'phone hash' as arg3 of response */
    135159                        IPC_SET_ARG3(answer->data,
    136160                            (unative_t) &TASK->phones[phoneid]);
     
    182206}
    183207
    184 /** Called before the request is sent
    185  *
    186  * @return 0 - no error, -1 - report error to user
     208/** Called before the request is sent.
     209 *
     210 * @param call          Call structure with the request.
     211 *
     212 * @return              Return 0 on success, ELIMIT or EPERM on error.
    187213 */
    188214static int request_preprocess(call_t *call)
     
    203229        case IPC_M_AS_AREA_SEND:
    204230                size = as_get_size(IPC_GET_ARG1(call->data));
    205                 if (!size) {
     231                if (!size)
    206232                        return EPERM;
    207                 }
    208233                IPC_SET_ARG2(call->data, size);
    209234                break;
     
    214239}
    215240
    216 /****************************************************/
    217 /* Functions called to process received call/answer
    218  * before passing to uspace
    219  */
    220 
    221 /** Do basic kernel processing of received call answer */
     241/*******************************************************************************
     242 * Functions called to process received call/answer before passing it to uspace.
     243 *******************************************************************************/
     244
     245/** Do basic kernel processing of received call answer.
     246 *
     247 * @param call          Call structure with the answer.
     248 */
    222249static void process_answer(call_t *call)
    223250{
     
    234261}
    235262
    236 /** Do basic kernel processing of received call request
    237  *
    238  * @return 0 - the call should be passed to userspace, 1 - ignore call
     263/** Do basic kernel processing of received call request.
     264 *
     265 * @param box           Destination answerbox structure.
     266 * @param call          Call structure with the request.
     267 *
     268 * @return              Return 0 if the call should be passed to userspace.
     269 *                      Return -1 if the call should be ignored.
    239270 */
    240271static int process_request(answerbox_t *box, call_t *call)
     
    246277                if (phoneid < 0) { /* Failed to allocate phone */
    247278                        IPC_SET_RETVAL(call->data, ELIMIT);
    248                         ipc_answer(box,call);
     279                        ipc_answer(box, call);
    249280                        return -1;
    250281                }
     
    254285}
    255286
    256 /** Send a call over IPC, wait for reply, return to user
    257  *
    258  * @return Call identification, returns -1 on fatal error,
    259            -2 on 'Too many async request, handle answers first
     287/** Make a fast call over IPC, wait for reply and return to user.
     288 *
     289 * This function can handle only one argument of payload, but is faster than
     290 * the generic function (i.e. sys_ipc_call_sync()).
     291 *
     292 * @param phoneid       Phone handle for the call.
     293 * @param method        Method of the call.
     294 * @param arg1          Service-defined payload argument.
     295 * @param data          Address of userspace structure where the reply call will
     296 *                      be stored.
     297 *
     298 * @return              Returns 0 on success.
     299 *                      Return ENOENT if there is no such phone handle.
    260300 */
    261301unative_t sys_ipc_call_sync_fast(unative_t phoneid, unative_t method,
     
    272312        IPC_SET_ARG1(call.data, arg1);
    273313
    274         if (!(res=request_preprocess(&call))) {
     314        if (!(res = request_preprocess(&call))) {
    275315                ipc_call_sync(phone, &call);
    276316                process_answer(&call);
    277         } else
     317        } else {
    278318                IPC_SET_RETVAL(call.data, res);
     319        }
    279320        STRUCT_TO_USPACE(&data->args, &call.data.args);
    280321
     
    282323}
    283324
    284 /** Synchronous IPC call allowing to send whole message */
     325/** Make a synchronous IPC call allowing to transmit the entire payload.
     326 *
     327 * @param phoneid       Phone handle for the call.
     328 * @param question      Userspace address of call data with the request.
     329 * @param reply         Userspace address of call data where to store the answer.
     330 *
     331 * @return              Zero on success or an error code.
     332 */
    285333unative_t sys_ipc_call_sync(unative_t phoneid, ipc_data_t *question,
    286334    ipc_data_t *reply)
     
    299347        GET_CHECK_PHONE(phone, phoneid, return ENOENT);
    300348
    301         if (!(res=request_preprocess(&call))) {
     349        if (!(res = request_preprocess(&call))) {
    302350                ipc_call_sync(phone, &call);
    303351                process_answer(&call);
     
    312360}
    313361
    314 /** Check that the task did not exceed allowed limit
    315  *
    316  * @return 0 - Limit OK,   -1 - limit exceeded
     362/** Check that the task did not exceed the allowed limit of asynchronous calls.
     363 *
     364 * @return              Return 0 if limit not reached or -1 if limit exceeded.
    317365 */
    318366static int check_call_limit(void)
     
    325373}
    326374
    327 /** Send an asynchronous call over ipc
    328  *
    329  * @return Call identification, returns -1 on fatal error,
    330            -2 on 'Too many async request, handle answers first
     375/** Make a fast asynchronous call over IPC.
     376 *
     377 * This function can only handle two arguments of payload, but is faster than
     378 * the generic function sys_ipc_call_async().
     379 *
     380 * @param phoneid       Phone handle for the call.
     381 * @param method        Method of the call.
     382 * @param arg1          Service-defined payload argument.
     383 * @param arg2          Service-defined payload argument.
     384 *
     385 * @return              Return call hash on success.
     386 *                      Return IPC_CALLRET_FATAL in case of a fatal error and
     387 *                      IPC_CALLRET_TEMPORARY if there are too many pending
     388 *                      asynchronous requests; answers should be handled first.
    331389 */
    332390unative_t sys_ipc_call_async_fast(unative_t phoneid, unative_t method,
     
    356414}
    357415
    358 /** Synchronous IPC call allowing to send whole message
    359  *
    360  * @return The same as sys_ipc_call_async
     416/** Make an asynchronous IPC call allowing to transmit the entire payload.
     417 *
     418 * @param phoneid       Phone handle for the call.
     419 * @param data          Userspace address of call data with the request.
     420 *
     421 * @return              See sys_ipc_call_async_fast().
    361422 */
    362423unative_t sys_ipc_call_async(unative_t phoneid, ipc_data_t *data)
     
    387448}
    388449
    389 /** Forward received call to another destination
    390  *
    391  * The arg1 and arg2 are changed in the forwarded message
     450/** Forward a received call to another destination.
     451 *
     452 * @param callid        Hash of the call to forward.
     453 * @param phoneid       Phone handle to use for forwarding.
     454 * @param method        New method to use for the forwarded call.
     455 * @param arg1          New value of the first argument for the forwarded call.
     456 *
     457 * @return              Return 0 on succes, otherwise return an error code.
     458 *
     459 * In case the original method is a system method, ARG1 and ARG2 are overwritten
     460 * in the forwarded message with the new method and the new arg1, respectively.
     461 * Otherwise the METHOD and ARG1 are rewritten with the new method and arg1,
     462 * respectively.
    392463 *
    393464 * Warning: If implementing non-fast version, make sure that
    394  *          arg3 is not rewritten for certain system IPC
     465 *          ARG3 is not rewritten for certain system IPC
    395466 */
    396467unative_t sys_ipc_forward_fast(unative_t callid, unative_t phoneid,
     
    435506}
    436507
    437 /** Send IPC answer */
     508/** Answer an IPC call - fast version.
     509 *
     510 * This function can handle only two return arguments of payload, but is faster
     511 * than the generic sys_ipc_answer().
     512 *
     513 * @param callid        Hash of the call to be answered.
     514 * @param retval        Return value of the answer.
     515 * @param arg1          Service-defined return value.
     516 * @param arg2          Service-defined return value.
     517 *
     518 * @return              Return 0 on success, otherwise return an error code.   
     519 */
    438520unative_t sys_ipc_answer_fast(unative_t callid, unative_t retval,
    439521    unative_t arg1, unative_t arg2)
     
    466548}
    467549
    468 /** Send IPC answer */
     550/** Answer an IPC call.
     551 *
     552 * @param callid        Hash of the call to be answered.
     553 * @param data          Userspace address of call data with the answer.
     554 *
     555 * @return              Return 0 on success, otherwise return an error code.
     556 */
    469557unative_t sys_ipc_answer(unative_t callid, ipc_data_t *data)
    470558{
     
    498586}
    499587
    500 /** Hang up the phone
    501  *
     588/** Hang up a phone.
     589 *
     590 * @param               Phone handle of the phone to be hung up.
     591 *
     592 * @return              Return 0 on success or an error code.
    502593 */
    503594unative_t sys_ipc_hangup(int phoneid)
     
    513604}
    514605
    515 /** Wait for incoming ipc call or answer
     606/** Wait for an incoming IPC call or an answer.
    516607 *
    517608 * @param calldata      Pointer to buffer where the call/answer data is stored.
     
    520611 *                      for explanation.
    521612 *
    522  * @return Callid, if callid & 1, then the call is answer
     613 * @return              Hash of the call.
     614 *                      If IPC_CALLID_NOTIFICATION bit is set in the hash, the
     615 *                      call is a notification. IPC_CALLID_ANSWERED denotes an
     616 *                      answer.
    523617 */
    524618unative_t sys_ipc_wait_for_call(ipc_data_t *calldata, uint32_t usec, int flags)
     
    542636                ipc_call_free(call);
    543637               
    544                 return ((unative_t)call) | IPC_CALLID_NOTIFICATION;
     638                return ((unative_t) call) | IPC_CALLID_NOTIFICATION;
    545639        }
    546640
     
    560654                ipc_call_free(call);
    561655
    562                 return ((unative_t)call) | IPC_CALLID_ANSWERED;
     656                return ((unative_t) call) | IPC_CALLID_ANSWERED;
    563657        }
    564658
     
    574668}
    575669
    576 /** Connect irq handler to task.
    577  *
    578  * @param inr IRQ number.
    579  * @param devno Device number.
    580  * @param method Method to be associated with the notification.
    581  * @param ucode Uspace pointer to the top-half pseudocode.
    582  *
    583  * @return EPERM or a return code returned by ipc_irq_register().
     670/** Connect an IRQ handler to a task.
     671 *
     672 * @param inr           IRQ number.
     673 * @param devno         Device number.
     674 * @param method        Method to be associated with the notification.
     675 * @param ucode         Uspace pointer to the top-half pseudocode.
     676 *
     677 * @return              EPERM or a return code returned by ipc_irq_register().
    584678 */
    585679unative_t sys_ipc_register_irq(inr_t inr, devno_t devno, unative_t method,
     
    592686}
    593687
    594 /** Disconnect irq handler from task.
    595  *
    596  * @param inr IRQ number.
    597  * @param devno Device number.
     688/** Disconnect an IRQ handler from a task.
     689 *
     690 * @param inr           IRQ number.
     691 * @param devno         Device number.
     692 *
     693 * @return              Zero on success or EPERM on error..
    598694 */
    599695unative_t sys_ipc_unregister_irq(inr_t inr, devno_t devno)
  • uspace/libc/generic/ipc.c

    r4680ef5 r8b243f2  
    5252#include <psthread.h>
    5353
    54 /** Structure used for keeping track of sent async msgs
    55  * and queing unsent msgs
    56  *
     54/** Structure used for keeping track of sent asynchronous calls and queing
     55 * unsent calls.
    5756 */
    5857typedef struct {
     
    6766                        int phoneid;
    6867                } msg;
    69         }u;
    70         pstid_t ptid;   /**< Thread waiting for sending this msg */
     68        } u;
     69        pstid_t ptid;   /**< Pseudothread waiting for sending this call. */
    7170} async_call_t;
    7271
    7372LIST_INITIALIZE(dispatched_calls);
    7473
    75 /* queued_calls is protcted by async_futex, because if the
    76  * call cannot be sent into kernel, async framework is used
    77  * automatically
    78  */
    79 LIST_INITIALIZE(queued_calls); /**< List of async calls that were not accepted
    80                                 *   by kernel */
     74/** List of asynchronous calls that were not accepted by kernel.
     75 *
     76 * It is protected by async_futex, because if the call cannot be sent into the
     77 * kernel, the async framework is used automatically.
     78 */
     79LIST_INITIALIZE(queued_calls);
    8180
    8281static atomic_t ipc_futex = FUTEX_INITIALIZER;
    8382
    84 int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1,
    85                   ipcarg_t *result)
     83/** Make a fast synchronous call.
     84 *
     85 * Only one payload argument can be passed using this function. However, this
     86 * function is faster than the generic ipc_call_sync_3().
     87 *
     88 * @param phoneid       Phone handle for the call.
     89 * @param method        Requested method.
     90 * @param arg1          Service-defined payload argument.
     91 * @param result        If non-NULL, the return ARG1 will be stored there.
     92 *
     93 * @return              Negative values represent errors returned by IPC.
     94 *                      Otherwise the RETVAL of the answer is returned.
     95 */
     96int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t *result)
    8697{
    8798        ipc_call_t resdata;
     
    89100       
    90101        callres = __SYSCALL4(SYS_IPC_CALL_SYNC_FAST, phoneid, method, arg1,
    91                              (sysarg_t)&resdata);
     102            (sysarg_t) &resdata);
    92103        if (callres)
    93104                return callres;
     
    97108}
    98109
    99 int ipc_call_sync_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
    100                     ipcarg_t arg2, ipcarg_t arg3,
    101                     ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3)
     110/** Make a synchronous call transmitting 3 arguments of payload.
     111 *
     112 * @param phoneid       Phone handle for the call.
     113 * @param method        Requested method.
     114 * @param arg1          Service-defined payload argument.
     115 * @param arg2          Service-defined payload argument.
     116 * @param arg3          Service-defined payload argument.
     117 * @param result1       If non-NULL, storage for the first return argument.
     118 * @param result2       If non-NULL, storage for the second return argument.
     119 * @param result3       If non-NULL, storage for the third return argument.
     120 *
     121 * @return              Negative value means IPC error.
     122 *                      Otherwise the RETVAL of the answer.
     123 */
     124int ipc_call_sync_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,
     125    ipcarg_t arg3, ipcarg_t *result1, ipcarg_t *result2, ipcarg_t *result3)
    102126{
    103127        ipc_call_t data;
     
    109133        IPC_SET_ARG3(data, arg3);
    110134
    111         callres = __SYSCALL3(SYS_IPC_CALL_SYNC, phoneid, (sysarg_t)&data,
    112                              (sysarg_t)&data);
     135        callres = __SYSCALL3(SYS_IPC_CALL_SYNC, phoneid, (sysarg_t) &data,
     136            (sysarg_t) &data);
    113137        if (callres)
    114138                return callres;
     
    123147}
    124148
    125 /** Syscall to send asynchronous message */
    126 static  ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data)
    127 {
    128         return __SYSCALL2(SYS_IPC_CALL_ASYNC, phoneid, (sysarg_t)data);
    129 }
    130 
    131 /** Prolog to ipc_async_send functions */
    132 static inline async_call_t *ipc_prepare_async(void *private, ipc_async_callback_t callback)
     149/** Syscall to send asynchronous message.
     150 *
     151 * @param phoneid       Phone handle for the call.
     152 * @param data          Call data with the request.
     153 *
     154 * @return              Hash of the call or an error code.
     155 */
     156static ipc_callid_t _ipc_call_async(int phoneid, ipc_call_t *data)
     157{
     158        return __SYSCALL2(SYS_IPC_CALL_ASYNC, phoneid, (sysarg_t) data);
     159}
     160
     161/** Prolog to ipc_call_async_*() functions.
     162 *
     163 * @param private       Argument for the answer/error callback.
     164 * @param callback      Answer/error callback.
     165 *
     166 * @return              New, partially initialized async_call structure or NULL.
     167 */
     168static inline async_call_t *ipc_prepare_async(void *private,
     169    ipc_async_callback_t callback)
    133170{
    134171        async_call_t *call;
     
    146183}
    147184
    148 /** Epilogue of ipc_async_send functions */
    149 static inline void ipc_finish_async(ipc_callid_t callid, int phoneid,
    150                                     async_call_t *call, int can_preempt)
     185/** Epilogue of ipc_call_async_*() functions.
     186 *
     187 * @param callid        Value returned by the SYS_IPC_CALL_ASYNC_* syscall.
     188 * @param phoneid       Phone handle through which the call was made.
     189 * @param call          async_call structure returned by ipc_prepare_async().
     190 * @param can_preempt   If non-zero, the current pseudo thread can be preempted
     191 *                      in this call.
     192 */
     193static inline void ipc_finish_async(ipc_callid_t callid, int phoneid,
     194    async_call_t *call, int can_preempt)
    151195{
    152196        if (!call) { /* Nothing to do regardless if failed or not */
     
    183227        }
    184228        call->u.callid = callid;
    185         /* Add call to list of dispatched calls */
     229        /* Add call to the list of dispatched calls */
    186230        list_append(&call->list, &dispatched_calls);
    187231        futex_up(&ipc_futex);
     
    189233}
    190234
    191 /** Send asynchronous message
    192  *
    193  * - if fatal error, call callback handler with proper error code
    194  * - if message cannot be temporarily sent, add to queue
     235/** Make a fast asynchronous call.
     236 *
     237 * This function can only handle two arguments of payload. It is, however,
     238 * faster than the more generic ipc_call_async_3().
     239 *
     240 * Note that this function is a void function.
     241 * During normal opertation, answering this call will trigger the callback.
     242 * In case of fatal error, call the callback handler with the proper error code.
     243 * If the call cannot be temporarily made, queue it.
     244 *
     245 * @param phoneid       Phone handle for the call.
     246 * @param method        Requested method.
     247 * @param arg1          Service-defined payload argument.
     248 * @param arg2          Service-defined payload argument.
     249 * @param private       Argument to be passed to the answer/error callback.
     250 * @param callback      Answer or error callback.
     251 * @param can_preempt   If non-zero, the current pseudo thread will be preempted
     252 *                      in case the kernel temporarily refuses to accept more
     253 *                      asynchronous calls.
    195254 */
    196255void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1,
    197                       ipcarg_t arg2, void *private,
    198                       ipc_async_callback_t callback, int can_preempt)
     256    ipcarg_t arg2, void *private, ipc_async_callback_t callback,
     257    int can_preempt)
    199258{
    200259        async_call_t *call = NULL;
     
    207266        }
    208267
    209         /* We need to make sure that we get callid before
    210          * another thread accesses the queue again */
     268        /*
     269         * We need to make sure that we get callid before another thread
     270         * accesses the queue again.
     271         */
    211272        futex_down(&ipc_futex);
    212         callid = __SYSCALL4(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1, arg2);
     273        callid = __SYSCALL4(SYS_IPC_CALL_ASYNC_FAST, phoneid, method, arg1,
     274            arg2);
    213275
    214276        if (callid == IPC_CALLRET_TEMPORARY) {
     
    225287}
    226288
    227 /** Send asynchronous message
    228  *
    229  * - if fatal error, call callback handler with proper error code
    230  * - if message cannot be temporarily sent, add to queue
     289/** Make an asynchronous call transmitting the entire payload.
     290 *
     291 * Note that this function is a void function.
     292 * During normal opertation, answering this call will trigger the callback.
     293 * In case of fatal error, call the callback handler with the proper error code.
     294 * If the call cannot be temporarily made, queue it.
     295 *
     296 * @param phoneid       Phone handle for the call.
     297 * @param method        Requested method.
     298 * @param arg1          Service-defined payload argument.
     299 * @param arg2          Service-defined payload argument.
     300 * @param arg3          Service-defined payload argument.
     301 * @param private       Argument to be passed to the answer/error callback.
     302 * @param callback      Answer or error callback.
     303 * @param can_preempt   If non-zero, the current pseudo thread will be preempted
     304 *                      in case the kernel temporarily refuses to accept more
     305 *                      asynchronous calls.
     306 *
    231307 */
    232308void ipc_call_async_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
    233                       ipcarg_t arg2, ipcarg_t arg3, void *private,
    234                       ipc_async_callback_t callback, int can_preempt)
     309    ipcarg_t arg2, ipcarg_t arg3, void *private, ipc_async_callback_t callback,
     310    int can_preempt)
    235311{
    236312        async_call_t *call;
     
    245321        IPC_SET_ARG2(call->u.msg.data, arg2);
    246322        IPC_SET_ARG3(call->u.msg.data, arg3);
    247         /* We need to make sure that we get callid before
    248          * another thread accesses the queue again */
     323        /*
     324         * We need to make sure that we get callid before another thread accesses
     325         * the queue again.
     326         */
    249327        futex_down(&ipc_futex);
    250328        callid = _ipc_call_async(phoneid, &call->u.msg.data);
     
    254332
    255333
    256 /** Send a fast answer to a received call.
    257  *
    258  * The fast answer makes use of passing retval and first two arguments in registers.
    259  * If you need to return more, use the ipc_answer() instead.
    260  *
    261  * @param callid ID of the call being answered.
    262  * @param retval Return value.
    263  * @param arg1 First return argument.
    264  * @param arg2 Second return argument.
    265  *
    266  * @return Zero on success or a value from @ref errno.h on failure.
     334/** Answer a received call - fast version.
     335 *
     336 * The fast answer makes use of passing retval and first two arguments in
     337 * registers. If you need to return more, use the ipc_answer() instead.
     338 *
     339 * @param callid        Hash of the call being answered.
     340 * @param retval        Return value.
     341 * @param arg1          First return argument.
     342 * @param arg2          Second return argument.
     343 *
     344 * @return              Zero on success or a value from @ref errno.h on failure.
    267345 */
    268346ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
    269                 ipcarg_t arg2)
     347    ipcarg_t arg2)
    270348{
    271349        return __SYSCALL4(SYS_IPC_ANSWER_FAST, callid, retval, arg1, arg2);
    272350}
    273351
    274 /** Send a full answer to a received call.
    275  *
    276  * @param callid ID of the call being answered.
    277  * @param call Call data. Must be already initialized by the responder.
    278  *
    279  * @return Zero on success or a value from @ref errno.h on failure.
     352/** Answer a received call - full version.
     353 *
     354 * @param callid        Hash of the call being answered.
     355 * @param call          Call structure with the answer.
     356 *                      Must be already initialized by the responder.
     357 *
     358 * @return              Zero on success or a value from @ref errno.h on failure.
    280359 */
    281360ipcarg_t ipc_answer(ipc_callid_t callid, ipc_call_t *call)
     
    285364
    286365
    287 /** Try to dispatch queed calls from async queue */
     366/** Try to dispatch queued calls from the async queue. */
    288367static void try_dispatch_queued_calls(void)
    289368{
     
    291370        ipc_callid_t callid;
    292371
    293         /* TODO: integrate intelligently ipc_futex, so that it
    294          * is locked during ipc_call_async, until it is added
    295          * to dispatched_calls
     372        /** @todo
     373         * Integrate intelligently ipc_futex, so that it is locked during
     374         * ipc_call_async_*(), until it is added to dispatched_calls.
    296375         */
    297376        futex_down(&async_futex);
    298377        while (!list_empty(&queued_calls)) {
    299                 call = list_get_instance(queued_calls.next, async_call_t,
    300                                          list);
    301 
    302                 callid = _ipc_call_async(call->u.msg.phoneid,
    303                                          &call->u.msg.data);
     378                call = list_get_instance(queued_calls.next, async_call_t, list);
     379                callid = _ipc_call_async(call->u.msg.phoneid, &call->u.msg.data);
    304380                if (callid == IPC_CALLRET_TEMPORARY) {
    305381                        break;
     
    326402}
    327403
    328 /** Handle received answer
    329  *
    330  * TODO: Make it use hash table
    331  *
    332  * @param callid Callid (with first bit set) of the answered call
     404/** Handle a received answer.
     405 *
     406 * Find the hash of the answer and call the answer callback.
     407 *
     408 * @todo Make it use hash table.
     409 *
     410 * @param callid        Hash of the received answer.
     411 *                      The answer has the same hash as the request OR'ed with
     412 *                      the IPC_CALLID_ANSWERED bit.
     413 * @param data          Call data of the answer.
    333414 */
    334415static void handle_answer(ipc_callid_t callid, ipc_call_t *data)
     
    341422        futex_down(&ipc_futex);
    342423        for (item = dispatched_calls.next; item != &dispatched_calls;
    343              item = item->next) {
     424            item = item->next) {
    344425                call = list_get_instance(item, async_call_t, list);
    345426                if (call->u.callid == callid) {
     
    348429                        if (call->callback)
    349430                                call->callback(call->private,
    350                                                IPC_GET_RETVAL(*data),
    351                                                data);
     431                                    IPC_GET_RETVAL(*data), data);
    352432                        free(call);
    353433                        return;
     
    355435        }
    356436        futex_up(&ipc_futex);
    357         /* We may get here after async_msg, which doesn't register any callback */
    358 }
    359 
    360 
    361 /** One cycle of ipc wait for call call
    362  *
    363  * - dispatch ASYNC reoutines in the background
    364  * @param call Space where the message is stored
    365  * @param usec Timeout in microseconds
    366  * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking)
    367  * @return Callid of the answer.
     437}
     438
     439
     440/** Wait for a first call to come.
     441 *
     442 * @param call          Storage where the incoming call data will be stored.
     443 * @param usec          Timeout in microseconds
     444 * @param flags         Flags passed to SYS_IPC_WAIT (blocking, nonblocking).
     445 *
     446 * @return              Hash of the call. Note that certain bits have special
     447 *                      meaning. IPC_CALLID_ANSWERED will be set in an answer
     448 *                      and IPC_CALLID_NOTIFICATION is used for notifications.
     449 *                     
    368450 */
    369451ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags)
     
    383465/** Wait some time for an IPC call.
    384466 *
    385  * - dispatch ASYNC reoutines in the background
    386  *
    387  * @param call Space where the message is stored
    388  * @param usec Timeout in microseconds.
    389  * @return Callid of the answer.
     467 * The call will return after an answer is received.
     468 *
     469 * @param call          Storage where the incoming call data will be stored.
     470 * @param usec          Timeout in microseconds.
     471 *
     472 * @return              Hash of the answer.
    390473 */
    391474ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *call, uint32_t usec)
     
    402485/** Check if there is an IPC call waiting to be picked up.
    403486 *
    404  * - dispatch ASYNC reoutines in the background
    405  *
    406  * @param call Space where the message is stored
    407  * @return Callid of the answer.
     487 * @param call          Storage where the incoming call will be stored.
     488 * @return              Hash of the answer.
    408489 */
    409490ipc_callid_t ipc_trywait_for_call(ipc_call_t *call)
     
    412493
    413494        do {
    414                 callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NON_BLOCKING);
     495                callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT,
     496                    SYNCH_FLAGS_NON_BLOCKING);
    415497        } while (callid & IPC_CALLID_ANSWERED);
    416498
     
    420502/** Ask destination to do a callback connection.
    421503 *
    422  * @param phoneid       Phone ID used for contacting the other side.
     504 * @param phoneid       Phone handle used for contacting the other side.
     505 * @param arg1          Service-defined argument.
     506 * @param arg2          Service-defined argument.
     507 * @param phonehash     Storage where the library will store an opaque
     508 *                      identifier of the phone that will be used for incoming
     509 *                      calls. This identifier can be used for connection
     510 *                      tracking.
     511 *
     512 * @return              Zero on success or a negative error code.
     513 */
     514int ipc_connect_to_me(int phoneid, int arg1, int arg2, ipcarg_t *phonehash)
     515{
     516        return ipc_call_sync_3(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2, 0, 0, 0,
     517            phonehash);
     518}
     519
     520/** Ask through phone for a new connection to some service.
     521 *
     522 * @param phoneid       Phone handle used for contacting the other side.
    423523 * @param arg1          User defined argument.
    424524 * @param arg2          User defined argument.
    425  * @param phonehash     Pointer to a place where the library will store an opaque
    426  *                      identifier of the phone that will be used for incoming
    427  *                      calls.
    428  * @return Zero on success or a negative error code.
    429  */
    430 int ipc_connect_to_me(int phoneid, int arg1, int arg2, ipcarg_t *phonehash)
    431 {
    432         return ipc_call_sync_3(phoneid, IPC_M_CONNECT_TO_ME, arg1, arg2, 0, 0, 0,
    433             phonehash);
    434 }
    435 
    436 /** Ask through phone for a new connection to some service.
    437  *
    438  * @param phoneid       Phone ID used for contacting the other side.
    439  * @param arg1          User defined argument.
    440  * @param arg2          User defined argument.
    441  *
    442  * @return New phone ID on success or a negative error code.
     525 *
     526 * @return              New phone handle on success or a negative error code.
    443527 */
    444528int ipc_connect_me_to(int phoneid, int arg1, int arg2)
     
    454538}
    455539
    456 /* Hang up specified phone */
     540/** Hang up a phone.
     541 *
     542 * @param phoneid       Handle of the phone to be hung up.
     543 *
     544 * @return              Zero on success or a negative error code.
     545 */
    457546int ipc_hangup(int phoneid)
    458547{
     
    462551/** Register IRQ notification.
    463552 *
    464  * @param inr IRQ number.
    465  * @param devno Device number of the device generating inr.
    466  * @param method Use this method for notifying me.
    467  * @param ucode Top-half pseudocode handler.
    468  *
    469  * @return Value returned by the kernel.
     553 * @param inr           IRQ number.
     554 * @param devno         Device number of the device generating inr.
     555 * @param method        Use this method for notifying me.
     556 * @param ucode         Top-half pseudocode handler.
     557 *
     558 * @return              Value returned by the kernel.
    470559 */
    471560int ipc_register_irq(int inr, int devno, int method, irq_code_t *ucode)
    472561{
    473         return __SYSCALL4(SYS_IPC_REGISTER_IRQ, inr, devno, method, (sysarg_t) ucode);
     562        return __SYSCALL4(SYS_IPC_REGISTER_IRQ, inr, devno, method,
     563            (sysarg_t) ucode);
    474564}
    475565
    476566/** Unregister IRQ notification.
    477567 *
    478  * @param inr IRQ number.
    479  * @param devno Device number of the device generating inr.
    480  *
    481  * @return Value returned by the kernel.
     568 * @param inr           IRQ number.
     569 * @param devno         Device number of the device generating inr.
     570 *
     571 * @return              Value returned by the kernel.
    482572 */
    483573int ipc_unregister_irq(int inr, int devno)
     
    486576}
    487577
     578/** Forward a received call to another destination.
     579 *
     580 * @param callid        Hash of the call to forward.
     581 * @param phoneid       Phone handle to use for forwarding.
     582 * @param method        New method for the forwarded call.
     583 * @param arg1          New value of the first argument for the forwarded call.
     584 *
     585 * @return              Zero on success or an error code.
     586 *
     587 * For non-system methods, the old method and arg1 are rewritten by the new
     588 * values. For system methods, the new method and arg1 are written to the old
     589 * arg1 and arg2, respectivelly.
     590 */
    488591int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, ipcarg_t arg1)
    489592{
  • uspace/libc/include/ipc/ipc.h

    r4680ef5 r8b243f2  
    5050
    5151typedef void (* ipc_async_callback_t)(void *private, int retval,
    52                                       ipc_call_t *data);
     52    ipc_call_t *data);
    5353
    54 #define ipc_call_sync_2(phoneid, method, arg1, arg2, res1, res2) ipc_call_sync_3((phoneid), (method), (arg1), (arg2), 0, (res1), (res2), 0)
     54#define ipc_call_sync_2(phoneid, method, arg1, arg2, res1, res2) \
     55        ipc_call_sync_3((phoneid), (method), (arg1), (arg2), 0, (res1), (res2), \
     56            0)
    5557extern int ipc_call_sync_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
    56                            ipcarg_t arg2, ipcarg_t arg3,
    57                            ipcarg_t *result1, ipcarg_t *result2,
    58                            ipcarg_t *result3);
    59 
     58    ipcarg_t arg2, ipcarg_t arg3, ipcarg_t *result1, ipcarg_t *result2,
     59    ipcarg_t *result3);
    6060
    6161extern int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1,
    62                          ipcarg_t *result);
     62    ipcarg_t *result);
     63
    6364extern ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags);
    6465extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *data, uint32_t usec);
     
    6970extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *data);
    7071
    71 extern ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval, ipcarg_t arg1,
    72                           ipcarg_t arg2);
     72extern ipcarg_t ipc_answer_fast(ipc_callid_t callid, ipcarg_t retval,
     73    ipcarg_t arg1, ipcarg_t arg2);
    7374extern ipcarg_t ipc_answer(ipc_callid_t callid, ipc_call_t *call);
    7475
    75 #define ipc_call_async(phoneid,method,arg1,private, callback,can_preempt) (ipc_call_async_2(phoneid, method, arg1, 0, private, callback, can_preempt))
     76#define ipc_call_async(phoneid, method, arg1, private, callback, can_preempt) \
     77        (ipc_call_async_2(phoneid, method, arg1, 0, private, callback, \
     78            can_preempt))
    7679extern void ipc_call_async_2(int phoneid, ipcarg_t method, ipcarg_t arg1,
    77                       ipcarg_t arg2, void *private,
    78                       ipc_async_callback_t callback, int can_preempt);
     80    ipcarg_t arg2, void *private, ipc_async_callback_t callback,
     81    int can_preempt);
    7982extern void ipc_call_async_3(int phoneid, ipcarg_t method, ipcarg_t arg1,
    80                              ipcarg_t arg2, ipcarg_t arg3, void *private,
    81                              ipc_async_callback_t callback, int can_preempt);
     83    ipcarg_t arg2, ipcarg_t arg3, void *private, ipc_async_callback_t callback,
     84    int can_preempt);
    8285
    8386extern int ipc_connect_to_me(int phoneid, int arg1, int arg2, ipcarg_t *phone);
     
    8689extern int ipc_register_irq(int inr, int devno, int method, irq_code_t *code);
    8790extern int ipc_unregister_irq(int inr, int devno);
    88 extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, ipcarg_t arg1);
     91extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method,
     92    ipcarg_t arg1);
    8993
    9094#endif
  • uspace/ns/ns.c

    r4680ef5 r8b243f2  
    156156 *
    157157 * @param service Service to be registered.
    158  * @param phone phone Phone to be used for connections to the service.
     158 * @param phone Phone to be used for connections to the service.
    159159 * @param call Pointer to call structure.
    160160 *
  • uspace/pci/pci.c

    r4680ef5 r8b243f2  
    22 * HelenOS PCI driver.
    33 *
    4  * Copyright (c) 1997-2003 Martin Mares
     4 * (Based on public domain libpci example.c written by Martin Mares.)
    55 * Copyright (c) 2006 Jakub Jermar
    6  *
    7  * (Based on libpci example.c written by Martin Mares.)
    86 *
    97 * Can be freely distributed and used under the terms of the GNU GPL.
  • uspace/rd/rd.c

    r4680ef5 r8b243f2  
    6767                callid = async_get_call(&call);
    6868                switch (IPC_GET_METHOD(call)) {
    69                         case IPC_M_PHONE_HUNGUP:
    70                                 ipc_answer_fast(callid, 0,0,0);
    71                                 return;
    72                         case IPC_M_AS_AREA_SEND:
    73                                 ipc_answer_fast(callid, 0, (uintptr_t)fs_addr, 0);
    74                                 continue;
    75                         case RD_READ_BLOCK:                     
    76                                 offset = IPC_GET_ARG1(call);
    77                                 memcpy((void *)fs_addr, rd_addr+offset, BLOCK_SIZE);
    78                                 retval = EOK;
    79                                 break;
    80                         default:
    81                                 retval = EINVAL;
     69                case IPC_M_PHONE_HUNGUP:
     70                        ipc_answer_fast(callid, 0, 0, 0);
     71                        return;
     72                case IPC_M_AS_AREA_SEND:
     73                        ipc_answer_fast(callid, 0, (uintptr_t) fs_addr, 0);
     74                        continue;
     75                case RD_READ_BLOCK:                     
     76                        offset = IPC_GET_ARG1(call);
     77                        memcpy((void *) fs_addr, rd_addr + offset, BLOCK_SIZE);
     78                        retval = EOK;
     79                        break;
     80                default:
     81                        retval = EINVAL;
    8282                }
    8383                ipc_answer_fast(callid, retval, 0, 0);
    84         }       
     84        }
    8585}
    8686
     
    9191
    9292        size_t rd_size = sysinfo_value("rd.size");
    93         void * rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
     93        void *rd_ph_addr = (void *) sysinfo_value("rd.address.physical");
    9494       
    9595        if (rd_size == 0)
     
    9999       
    100100        flags = AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE;
    101         retval = physmem_map(rd_ph_addr, rd_addr, ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
     101        retval = physmem_map(rd_ph_addr, rd_addr,
     102            ALIGN_UP(rd_size, PAGE_SIZE) >> PAGE_WIDTH, flags);
    102103
    103104        if (retval < 0)
Note: See TracChangeset for help on using the changeset viewer.