Changeset 2ba7810 in mainline for generic/src/ipc/sysipc.c


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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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) {
Note: See TracChangeset for help on using the changeset viewer.