Changeset 2ba7810 in mainline


Ignore:
Timestamp:
2006-03-16T12:24:20Z (19 years ago)
Author:
Ondrej Palkovsky <ondrap@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b7dcabb
Parents:
d764ddc
Message:

Changed ipc to use spinlocks instead of mutexes again.
Fixed loading inits to set nameservice as the first loaded process.
Lot of TODO in ipc done.

Location:
generic
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • generic/include/errno.h

    rd764ddc r2ba7810  
    3636#define ELIMIT     -3  /* Limit exceeded */
    3737#define EREFUSED   -4  /* Connection refused */
     38#define EFORWARD   -5  /* Forward error */
     39#define EPERM      -6  /* Permission denied */
    3840
    3941#endif
  • generic/include/ipc/ipc.h

    rd764ddc r2ba7810  
    7272 * These methods have special behaviour
    7373 */
    74 #define IPC_M_IAMCONNECTING   0
    7574/** Protocol for CONNECT - TO - ME
    7675 *
     
    7877 * so that it can start initiating new messages.
    7978 *
    80  * The protocol for negotiating is as follows:
     79 * The protocol for negotiating is:
    8180 * - sys_connecttome - sends a message IPC_M_CONNECTTOME
    8281 * - sys_wait_for_call - upon receipt tries to allocate new phone
     
    8685 *                       error is sent back to caller. Otherwise
    8786 *                       the call is accepted and the response is sent back.
    88  *                     - the allocated phoneid is passed to userspace as
    89  *                       ARG3 of the call.
     87 *                     - the allocated phoneid is passed to userspace
     88 *                       (on the receiving sid) as ARG3 of the call.
    9089 *                     - the caller obtains taskid of the called thread
    9190 */
    9291#define IPC_M_CONNECTTOME     1
     92/** Protocol for CONNECT - ME - TO
     93 *
     94 * Calling process asks the callee to create for him a new connection.
     95 * E.g. the caller wants a name server to connect him to print server.
     96 *
     97 * The protocol for negotiating is:
     98 * - sys_connect_me_to - send a synchronous message to name server
     99 *                       indicating that it wants to be connected to some
     100 *                       service
     101 *   recepient         -  if ipc_answer == 0, then accept connection
     102 *                     -  otherwise connection refused
     103 *                     -  recepient may forward message. Forwarding
     104 *                        system message
     105 *
     106 */
    93107#define IPC_M_CONNECTMETO     2
     108/* Control messages that the server sends to the processes
     109 * about their connections.
     110 */
    94111
    95112
    96113/* Well-known methods */
    97 #define IPC_M_FIRST_USER      512
     114#define IPC_M_LAST_SYSTEM     511
    98115#define IPC_M_PING            512
    99116/* User methods */
     
    124141        task_t *task;
    125142
    126         mutex_t mutex;
    127         condvar_t cv;
     143        waitq_t wq;
    128144
    129145        link_t connected_phones; /**< Phones connected to this answerbox */
     
    138154        link_t list;
    139155        answerbox_t *callee;
     156        int busy;
    140157} phone_t;
    141158
     
    146163extern void ipc_call_sync(phone_t *phone, call_t *request);
    147164extern void ipc_phone_destroy(phone_t *phone);
    148 extern void ipc_phone_init(phone_t *phone, answerbox_t *box);
     165extern void ipc_phone_init(phone_t *phone);
     166extern void ipc_phone_connect(phone_t *phone, answerbox_t *box);
    149167extern void ipc_call_free(call_t *call);
    150168extern call_t * ipc_call_alloc(void);
    151169extern void ipc_answerbox_init(answerbox_t *box);
    152 extern void ipc_phone_init(phone_t *phone, answerbox_t *box);
    153170extern void ipc_call_init(call_t *call);
     171extern void ipc_forward(call_t *call, answerbox_t *newbox,answerbox_t *oldbox);
    154172
    155173extern answerbox_t *ipc_phone_0;
  • generic/include/ipc/sysipc.h

    rd764ddc r2ba7810  
    4444__native sys_ipc_wait_for_call(ipc_data_t *calldata, task_id_t *taskid,
    4545                               __native flags);
     46__native sys_ipc_connect_me_to(__native phoneid, __native arg1,
     47                               __native arg2);
     48__native sys_ipc_forward_fast(__native callid, __native phoneid,
     49                              __native method, __native arg1);
     50
    4651
    4752#endif
  • generic/include/syscall/syscall.h

    rd764ddc r2ba7810  
    4141        SYS_IPC_ANSWER_FAST,
    4242        SYS_IPC_ANSWER,
     43        SYS_IPC_FORWARD_FAST,
    4344        SYS_IPC_WAIT,
    4445        SYS_IPC_CONNECT_TO_ME,
     46        SYS_IPC_CONNECT_ME_TO,
    4547        SYSCALL_END
    4648} syscall_t;
  • generic/src/ipc/ipc.c

    rd764ddc r2ba7810  
    3232 */
    3333
    34 #include <synch/condvar.h>
    35 #include <synch/mutex.h>
     34#include <synch/spinlock.h>
     35#include <synch/waitq.h>
    3636#include <ipc/ipc.h>
    3737#include <errno.h>
     
    8585void ipc_answerbox_init(answerbox_t *box)
    8686{
    87         mutex_initialize(&box->mutex);
    88         condvar_initialize(&box->cv);
     87        spinlock_initialize(&box->lock, "ipc_box_lock");
     88        waitq_initialize(&box->wq);
    8989        list_initialize(&box->connected_phones);
    9090        list_initialize(&box->calls);
     
    9494}
    9595
     96/** Connect phone to answerbox */
     97void ipc_phone_connect(phone_t *phone, answerbox_t *box)
     98{
     99        ASSERT(!phone->callee);
     100        phone->busy = 1;
     101        phone->callee = box;
     102
     103        spinlock_lock(&box->lock);
     104        list_append(&phone->list, &box->connected_phones);
     105        spinlock_unlock(&box->lock);
     106}
     107
    96108/** Initialize phone structure and connect phone to naswerbox
    97109 */
    98 void ipc_phone_init(phone_t *phone, answerbox_t *box)
     110void ipc_phone_init(phone_t *phone)
    99111{
    100112        spinlock_initialize(&phone->lock, "phone_lock");
    101        
    102         phone->callee = box;
    103 
    104         mutex_lock(&box->mutex);
    105         list_append(&phone->list, &box->connected_phones);
    106         mutex_unlock(&box->mutex);
     113        phone->callee = NULL;
     114        phone->busy = 0;
    107115}
    108116
     
    114122        ASSERT(box);
    115123
    116         mutex_lock(&box->mutex);
     124        spinlock_lock(&box->lock);
    117125        list_remove(&phone->list);
    118         mutex_unlock(&box->mutex);
     126        spinlock_unlock(&box->lock);
    119127}
    120128
     
    138146 * @param request Request to be sent
    139147 */
    140 void ipc_call(phone_t *phone, call_t *request)
     148void ipc_call(phone_t *phone, call_t *call)
    141149{
    142150        answerbox_t *box = phone->callee;
     
    144152        ASSERT(box);
    145153
    146         mutex_lock(&box->mutex);
    147         list_append(&request->list, &box->calls);
    148         mutex_unlock(&box->mutex);
    149         condvar_signal(&box->cv);
     154        spinlock_lock(&box->lock);
     155        list_append(&call->list, &box->calls);
     156        spinlock_unlock(&box->lock);
     157        waitq_wakeup(&box->wq, 0);
     158}
     159
     160/** Forwards call from one answerbox to a new one
     161 *
     162 * @param request Request to be forwarded
     163 * @param newbox Target answerbox
     164 * @param oldbox Old answerbox
     165 */
     166void ipc_forward(call_t *call, answerbox_t *newbox, answerbox_t *oldbox)
     167{
     168        spinlock_lock(&oldbox->lock);
     169        list_remove(&call->list);
     170        spinlock_unlock(&oldbox->lock);
     171
     172        spinlock_lock(&newbox->lock);
     173        list_append(&call->list, &newbox->calls);
     174        spinlock_lock(&newbox->lock);
     175        waitq_wakeup(&newbox->wq, 0);
    150176}
    151177
     
    161187        request->flags |= IPC_CALL_ANSWERED;
    162188
    163         mutex_lock(&box->mutex);
     189        spinlock_lock(&box->lock);
    164190        list_remove(&request->list);
    165         mutex_unlock(&box->mutex);
    166 
    167         mutex_lock(&callerbox->mutex);
     191        spinlock_unlock(&box->lock);
     192
     193        spinlock_lock(&callerbox->lock);
    168194        list_append(&request->list, &callerbox->answers);
    169         mutex_unlock(&callerbox->mutex);
    170         condvar_signal(&callerbox->cv);
     195        spinlock_unlock(&callerbox->lock);
     196        waitq_wakeup(&callerbox->wq, 0);
    171197}
    172198
     
    180206        call_t *request;
    181207
    182         mutex_lock(&box->mutex);
     208        spinlock_lock(&box->lock);
    183209        while (1) {
    184210                if (!list_empty(&box->answers)) {
     
    195221                        if (!(flags & IPC_WAIT_NONBLOCKING)) {
    196222                                /* Wait for event to appear */
    197                                 condvar_wait(&box->cv, &box->mutex);
     223                                spinlock_unlock(&box->lock);
     224                                waitq_sleep(&box->wq);
     225                                spinlock_lock(&box->lock);
    198226                                continue;
    199227                        }
     
    202230                break;
    203231        }
    204         mutex_unlock(&box->mutex);
     232        spinlock_unlock(&box->lock);
    205233        return request;
    206234}
  • generic/src/ipc/sysipc.c

    rd764ddc r2ba7810  
    4141 * on phone, add counter + thread_kill??
    4242 *
    43  * - don't allow userspace app to send system messages
    44  */
     43 */
     44
     45/** Return true if the method is a system method */
     46static inline int is_system_method(__native method)
     47{
     48        if (method <= IPC_M_LAST_SYSTEM)
     49                return 1;
     50        return 0;
     51}
     52
     53/** Return true if the message with this method is forwardable
     54 *
     55 * - some system messages may be forwarded, for some of them
     56 *   it is useless
     57 */
     58static inline int is_forwardable(__native method)
     59{
     60        return 1;
     61}
     62
     63/** Find call_t * in call table according to callid
     64 *
     65 * @return NULL on not found, otherwise pointer to call structure
     66 */
     67static inline call_t * get_call(__native callid)
     68{
     69        /* TODO: Traverse list of dispatched calls and find one */
     70        /* TODO: locking of call, ripping it from dispatched calls etc.  */
     71        return (call_t *) callid;
     72}
    4573
    4674/** Return pointer to phone identified by phoneid or NULL if non-existent */
     
    5987
    6088/** Allocate new phone slot in current TASK structure */
    61 static int phone_alloc(answerbox_t *callee)
     89static int phone_alloc(void)
    6290{
    6391        int i;
     
    6694       
    6795        for (i=0; i < IPC_MAX_PHONES; i++) {
    68                 if (!TASK->phones[i].callee) {
    69                         TASK->phones[i].callee = callee;
     96                if (!TASK->phones[i].busy) {
     97                        TASK->phones[i].busy = 1;
    7098                        break;
    7199                }
     
    83111        spinlock_lock(&TASK->lock);
    84112
    85         ASSERT(TASK->phones[phoneid].callee);
    86 
    87         TASK->phones[phoneid].callee = NULL;
     113        ASSERT(TASK->phones[phoneid].busy);
     114
     115        if (TASK->phones[phoneid].callee)
     116                ipc_phone_destroy(&TASK->phones[phoneid]);
     117
     118        TASK->phones[phoneid].busy = 0;
    88119        spinlock_unlock(&TASK->lock);
     120}
     121
     122static void phone_connect(int phoneid, answerbox_t *box)
     123{
     124        phone_t *phone = &TASK->phones[phoneid];
     125       
     126        ipc_phone_connect(phone, box);
    89127}
    90128
     
    105143
    106144/** Interpret process answer as control information */
    107 static inline void answer_preprocess(call_t *answer, call_t *call)
     145static inline void answer_preprocess(call_t *answer, ipc_data_t *olddata)
    108146{
    109147        int phoneid;
    110148
    111         if (IPC_GET_METHOD(call->data) == IPC_M_CONNECTTOME) {
     149        if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECTTOME) {
     150                phoneid = IPC_GET_ARG3(*olddata);
    112151                if (IPC_GET_RETVAL(answer->data)) {
    113152                        /* The connection was not accepted */
    114                         /* TODO...race for multi-threaded process */
    115                         phoneid = IPC_GET_ARG3(call->data);
    116153                        phone_dealloc(phoneid);
     154                } else {
     155                        /* The connection was accepted */
     156                        phone_connect(phoneid,&answer->sender->answerbox);
    117157                }
    118158        }
     
    139179
    140180        if (IPC_GET_METHOD(call->data) == IPC_M_CONNECTTOME) {
    141                 phoneid = phone_alloc(&call->sender->answerbox);
     181                phoneid = phone_alloc();
    142182                if (phoneid < 0) { /* Failed to allocate phone */
    143183                        IPC_SET_RETVAL(call->data, ELIMIT);
     
    163203        phone = get_phone(phoneid);
    164204        if (!phone)
    165                 return IPC_CALLRET_FATAL;
     205                return ENOENT;
     206
     207        if (is_system_method(method))
     208                return EPERM;
    166209
    167210        ipc_call_init(&call);
     
    185228        phone = get_phone(phoneid);
    186229        if (!phone)
    187                 return IPC_CALLRET_FATAL;
     230                return ENOENT;
    188231
    189232        ipc_call_init(&call);
    190233        copy_from_uspace(&call.data, question, sizeof(call.data));
     234
     235        if (is_system_method(IPC_GET_METHOD(call.data)))
     236                return EPERM;
    191237       
    192238        ipc_call_sync(phone, &call);
     
    223269        phone = get_phone(phoneid);
    224270        if (!phone)
     271                return IPC_CALLRET_FATAL;
     272
     273        if (is_system_method(method))
    225274                return IPC_CALLRET_FATAL;
    226275
     
    256305        call = ipc_call_alloc();
    257306        copy_from_uspace(&call->data, data, sizeof(call->data));
     307
     308        if (is_system_method(IPC_GET_METHOD(call->data))) {
     309                ipc_call_free(call);
     310                return EPERM;
     311        }
    258312       
    259313        ipc_call(phone, call);
    260314
    261315        return (__native) call;
     316}
     317
     318/** Forward received call to another destination
     319 *
     320 * The arg1 and arg2 are changed in the forwarded message
     321 */
     322__native sys_ipc_forward_fast(__native callid, __native phoneid,
     323                              __native method, __native arg1)
     324{
     325        call_t *call;
     326        phone_t *phone;
     327
     328        call = get_call(callid);
     329        if (!call)
     330                return ENOENT;
     331
     332        phone = get_phone(phoneid);
     333        if (!phone) {
     334                IPC_SET_RETVAL(call->data, EFORWARD);
     335                ipc_answer(&TASK->answerbox, call);
     336                return ENOENT;
     337        }
     338
     339        if (!is_forwardable(IPC_GET_METHOD(call->data))) {
     340                IPC_SET_RETVAL(call->data, EFORWARD);
     341                ipc_answer(&TASK->answerbox, call);
     342                return EPERM;
     343        }
     344
     345        /* Userspace is not allowed to change method of system methods
     346         * on forward, allow changing ARG1 and ARG2 by means of method and arg1
     347         */
     348        if (is_system_method(IPC_GET_METHOD(call->data))) {
     349                IPC_SET_ARG1(call->data, method);
     350                IPC_SET_ARG2(call->data, arg1);
     351        } else {
     352                IPC_SET_METHOD(call->data, method);
     353                IPC_SET_ARG1(call->data, arg1);
     354        }
     355
     356        ipc_forward(call, phone->callee, &TASK->answerbox);
     357
     358        return 0;
    262359}
    263360
     
    267364{
    268365        call_t *call;
    269         call_t saved_call;
     366        ipc_data_t saved_data;
    270367        int preprocess = 0;
    271368
    272         /* Check that the user is not sending us answer callid */
    273         ASSERT(! (callid & 1));
    274         /* TODO: Check that the callid is in the dispatch table */
    275         call = (call_t *) callid;
     369        call = get_call(callid);
     370        if (!call)
     371                return ENOENT;
    276372
    277373        if (answer_will_preprocess(call)) {
    278                 memcpy(&saved_call.data, &call->data, sizeof(call->data));
     374                memcpy(&saved_data, &call->data, sizeof(call->data));
    279375                preprocess = 1;
    280376        }
     
    283379        IPC_SET_ARG1(call->data, arg1);
    284380        IPC_SET_ARG2(call->data, arg2);
     381
    285382        if (preprocess)
    286                 answer_preprocess(call, &saved_call);
     383                answer_preprocess(call, &saved_data);
    287384
    288385        ipc_answer(&TASK->answerbox, call);
     
    294391{
    295392        call_t *call;
    296         call_t saved_call;
     393        ipc_data_t saved_data;
    297394        int preprocess = 0;
    298395
    299         /* Check that the user is not sending us answer callid */
    300         ASSERT(! (callid & 1));
    301         /* TODO: Check that the callid is in the dispatch table */
    302         call = (call_t *) callid;
     396        call = get_call(callid);
     397        if (!call)
     398                return ENOENT;
    303399
    304400        if (answer_will_preprocess(call)) {
    305                 memcpy(&saved_call.data, &call->data, sizeof(call->data));
     401                memcpy(&saved_data, &call->data, sizeof(call->data));
    306402                preprocess = 1;
    307403        }
     
    309405
    310406        if (preprocess)
    311                 answer_preprocess(call, &saved_call);
     407                answer_preprocess(call, &saved_data);
    312408       
    313409        ipc_answer(&TASK->answerbox, call);
     
    328424        phone = get_phone(phoneid);
    329425        if (!phone)
    330                 return IPC_CALLRET_FATAL;
     426                return ENOENT;
    331427
    332428        ipc_call_init(&call);
     
    344440}
    345441
     442/** Ask target process to connect me somewhere
     443 *
     444 * @return phoneid - on success, error otherwise
     445 */
     446__native sys_ipc_connect_me_to(__native phoneid, __native arg1,
     447                               __native arg2)
     448{
     449        call_t call;
     450        phone_t *phone;
     451
     452        phone = get_phone(phoneid);
     453        if (!phone)
     454                return ENOENT;
     455
     456        ipc_call_init(&call);
     457        IPC_SET_METHOD(call.data, IPC_M_CONNECTMETO);
     458        IPC_SET_ARG1(call.data, arg1);
     459        IPC_SET_ARG2(call.data, arg2);
     460
     461        ipc_call_sync(phone, &call);
     462        if (!IPC_GET_RETVAL(call.data)) {
     463                /* Everybody accepted, we should be connected by now */
     464        }
     465
     466        return 0;
     467}
     468
    346469/** Wait for incoming ipc call or answer
    347470 *
     
    363486restart:       
    364487        call = ipc_wait_for_call(&TASK->answerbox, flags);
     488        printf("Received call %P from sender: %P\n", call, call->sender);
    365489
    366490        if (call->flags & IPC_CALL_ANSWERED) {
  • generic/src/main/kinit.c

    rd764ddc r2ba7810  
    144144
    145145                utask = task_run_program((void *) init.tasks[i].addr);
    146                 if (utask)
    147                         ipc_phone_0 = &utask->answerbox;
    148                 else
     146                if (utask) {
     147                        if (!ipc_phone_0)
     148                                ipc_phone_0 = &utask->answerbox;
     149                } else
    149150                        printf("Userspace not started.\n");
    150151        }
  • generic/src/proc/task.c

    rd764ddc r2ba7810  
    7070        ipl_t ipl;
    7171        task_t *ta;
     72        int i;
    7273       
    7374        ta = (task_t *) malloc(sizeof(task_t), 0);
     
    7879        ta->as = as;
    7980
     81       
    8082        ipc_answerbox_init(&ta->answerbox);
    81         memsetb((__address)&ta->phones, sizeof(ta->phones[0])*IPC_MAX_PHONES, 0);
     83        for (i=0; i < IPC_MAX_PHONES;i++)
     84                ipc_phone_init(&ta->phones[i]);
    8285        if (ipc_phone_0)
    83                 ipc_phone_init(&ta->phones[0], ipc_phone_0);
     86                ipc_phone_connect(&ta->phones[0], ipc_phone_0);
    8487        atomic_set(&ta->active_calls, 0);
    8588       
  • generic/src/syscall/syscall.c

    rd764ddc r2ba7810  
    8282        sys_ipc_answer_fast,
    8383        sys_ipc_answer,
     84        sys_ipc_forward_fast,
    8485        sys_ipc_wait_for_call,
    85         sys_ipc_connect_to_me
     86        sys_ipc_connect_to_me,
     87        sys_ipc_connect_me_to
    8688};
Note: See TracChangeset for help on using the changeset viewer.