Changeset 2ba7810 in mainline
- Timestamp:
- 2006-03-16T12:24:20Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- b7dcabb
- Parents:
- d764ddc
- Location:
- generic
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/include/errno.h
rd764ddc r2ba7810 36 36 #define ELIMIT -3 /* Limit exceeded */ 37 37 #define EREFUSED -4 /* Connection refused */ 38 #define EFORWARD -5 /* Forward error */ 39 #define EPERM -6 /* Permission denied */ 38 40 39 41 #endif -
generic/include/ipc/ipc.h
rd764ddc r2ba7810 72 72 * These methods have special behaviour 73 73 */ 74 #define IPC_M_IAMCONNECTING 075 74 /** Protocol for CONNECT - TO - ME 76 75 * … … 78 77 * so that it can start initiating new messages. 79 78 * 80 * The protocol for negotiating is as follows:79 * The protocol for negotiating is: 81 80 * - sys_connecttome - sends a message IPC_M_CONNECTTOME 82 81 * - sys_wait_for_call - upon receipt tries to allocate new phone … … 86 85 * error is sent back to caller. Otherwise 87 86 * the call is accepted and the response is sent back. 88 * - the allocated phoneid is passed to userspace as89 * ARG3 of the call.87 * - the allocated phoneid is passed to userspace 88 * (on the receiving sid) as ARG3 of the call. 90 89 * - the caller obtains taskid of the called thread 91 90 */ 92 91 #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 */ 93 107 #define IPC_M_CONNECTMETO 2 108 /* Control messages that the server sends to the processes 109 * about their connections. 110 */ 94 111 95 112 96 113 /* Well-known methods */ 97 #define IPC_M_ FIRST_USER 512114 #define IPC_M_LAST_SYSTEM 511 98 115 #define IPC_M_PING 512 99 116 /* User methods */ … … 124 141 task_t *task; 125 142 126 mutex_t mutex; 127 condvar_t cv; 143 waitq_t wq; 128 144 129 145 link_t connected_phones; /**< Phones connected to this answerbox */ … … 138 154 link_t list; 139 155 answerbox_t *callee; 156 int busy; 140 157 } phone_t; 141 158 … … 146 163 extern void ipc_call_sync(phone_t *phone, call_t *request); 147 164 extern void ipc_phone_destroy(phone_t *phone); 148 extern void ipc_phone_init(phone_t *phone, answerbox_t *box); 165 extern void ipc_phone_init(phone_t *phone); 166 extern void ipc_phone_connect(phone_t *phone, answerbox_t *box); 149 167 extern void ipc_call_free(call_t *call); 150 168 extern call_t * ipc_call_alloc(void); 151 169 extern void ipc_answerbox_init(answerbox_t *box); 152 extern void ipc_phone_init(phone_t *phone, answerbox_t *box);153 170 extern void ipc_call_init(call_t *call); 171 extern void ipc_forward(call_t *call, answerbox_t *newbox,answerbox_t *oldbox); 154 172 155 173 extern answerbox_t *ipc_phone_0; -
generic/include/ipc/sysipc.h
rd764ddc r2ba7810 44 44 __native sys_ipc_wait_for_call(ipc_data_t *calldata, task_id_t *taskid, 45 45 __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 46 51 47 52 #endif -
generic/include/syscall/syscall.h
rd764ddc r2ba7810 41 41 SYS_IPC_ANSWER_FAST, 42 42 SYS_IPC_ANSWER, 43 SYS_IPC_FORWARD_FAST, 43 44 SYS_IPC_WAIT, 44 45 SYS_IPC_CONNECT_TO_ME, 46 SYS_IPC_CONNECT_ME_TO, 45 47 SYSCALL_END 46 48 } syscall_t; -
generic/src/ipc/ipc.c
rd764ddc r2ba7810 32 32 */ 33 33 34 #include <synch/ condvar.h>35 #include <synch/ mutex.h>34 #include <synch/spinlock.h> 35 #include <synch/waitq.h> 36 36 #include <ipc/ipc.h> 37 37 #include <errno.h> … … 85 85 void ipc_answerbox_init(answerbox_t *box) 86 86 { 87 mutex_initialize(&box->mutex);88 condvar_initialize(&box->cv);87 spinlock_initialize(&box->lock, "ipc_box_lock"); 88 waitq_initialize(&box->wq); 89 89 list_initialize(&box->connected_phones); 90 90 list_initialize(&box->calls); … … 94 94 } 95 95 96 /** Connect phone to answerbox */ 97 void 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 96 108 /** Initialize phone structure and connect phone to naswerbox 97 109 */ 98 void ipc_phone_init(phone_t *phone , answerbox_t *box)110 void ipc_phone_init(phone_t *phone) 99 111 { 100 112 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; 107 115 } 108 116 … … 114 122 ASSERT(box); 115 123 116 mutex_lock(&box->mutex);124 spinlock_lock(&box->lock); 117 125 list_remove(&phone->list); 118 mutex_unlock(&box->mutex);126 spinlock_unlock(&box->lock); 119 127 } 120 128 … … 138 146 * @param request Request to be sent 139 147 */ 140 void ipc_call(phone_t *phone, call_t * request)148 void ipc_call(phone_t *phone, call_t *call) 141 149 { 142 150 answerbox_t *box = phone->callee; … … 144 152 ASSERT(box); 145 153 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 */ 166 void 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); 150 176 } 151 177 … … 161 187 request->flags |= IPC_CALL_ANSWERED; 162 188 163 mutex_lock(&box->mutex);189 spinlock_lock(&box->lock); 164 190 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); 168 194 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); 171 197 } 172 198 … … 180 206 call_t *request; 181 207 182 mutex_lock(&box->mutex);208 spinlock_lock(&box->lock); 183 209 while (1) { 184 210 if (!list_empty(&box->answers)) { … … 195 221 if (!(flags & IPC_WAIT_NONBLOCKING)) { 196 222 /* 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); 198 226 continue; 199 227 } … … 202 230 break; 203 231 } 204 mutex_unlock(&box->mutex);232 spinlock_unlock(&box->lock); 205 233 return request; 206 234 } -
generic/src/ipc/sysipc.c
rd764ddc r2ba7810 41 41 * on phone, add counter + thread_kill?? 42 42 * 43 * - don't allow userspace app to send system messages 44 */ 43 */ 44 45 /** Return true if the method is a system method */ 46 static 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 */ 58 static 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 */ 67 static 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 } 45 73 46 74 /** Return pointer to phone identified by phoneid or NULL if non-existent */ … … 59 87 60 88 /** Allocate new phone slot in current TASK structure */ 61 static int phone_alloc( answerbox_t *callee)89 static int phone_alloc(void) 62 90 { 63 91 int i; … … 66 94 67 95 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; 70 98 break; 71 99 } … … 83 111 spinlock_lock(&TASK->lock); 84 112 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; 88 119 spinlock_unlock(&TASK->lock); 120 } 121 122 static void phone_connect(int phoneid, answerbox_t *box) 123 { 124 phone_t *phone = &TASK->phones[phoneid]; 125 126 ipc_phone_connect(phone, box); 89 127 } 90 128 … … 105 143 106 144 /** Interpret process answer as control information */ 107 static inline void answer_preprocess(call_t *answer, call_t *call)145 static inline void answer_preprocess(call_t *answer, ipc_data_t *olddata) 108 146 { 109 147 int phoneid; 110 148 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); 112 151 if (IPC_GET_RETVAL(answer->data)) { 113 152 /* The connection was not accepted */ 114 /* TODO...race for multi-threaded process */115 phoneid = IPC_GET_ARG3(call->data);116 153 phone_dealloc(phoneid); 154 } else { 155 /* The connection was accepted */ 156 phone_connect(phoneid,&answer->sender->answerbox); 117 157 } 118 158 } … … 139 179 140 180 if (IPC_GET_METHOD(call->data) == IPC_M_CONNECTTOME) { 141 phoneid = phone_alloc( &call->sender->answerbox);181 phoneid = phone_alloc(); 142 182 if (phoneid < 0) { /* Failed to allocate phone */ 143 183 IPC_SET_RETVAL(call->data, ELIMIT); … … 163 203 phone = get_phone(phoneid); 164 204 if (!phone) 165 return IPC_CALLRET_FATAL; 205 return ENOENT; 206 207 if (is_system_method(method)) 208 return EPERM; 166 209 167 210 ipc_call_init(&call); … … 185 228 phone = get_phone(phoneid); 186 229 if (!phone) 187 return IPC_CALLRET_FATAL;230 return ENOENT; 188 231 189 232 ipc_call_init(&call); 190 233 copy_from_uspace(&call.data, question, sizeof(call.data)); 234 235 if (is_system_method(IPC_GET_METHOD(call.data))) 236 return EPERM; 191 237 192 238 ipc_call_sync(phone, &call); … … 223 269 phone = get_phone(phoneid); 224 270 if (!phone) 271 return IPC_CALLRET_FATAL; 272 273 if (is_system_method(method)) 225 274 return IPC_CALLRET_FATAL; 226 275 … … 256 305 call = ipc_call_alloc(); 257 306 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 } 258 312 259 313 ipc_call(phone, call); 260 314 261 315 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; 262 359 } 263 360 … … 267 364 { 268 365 call_t *call; 269 call_t saved_call;366 ipc_data_t saved_data; 270 367 int preprocess = 0; 271 368 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; 276 372 277 373 if (answer_will_preprocess(call)) { 278 memcpy(&saved_ call.data, &call->data, sizeof(call->data));374 memcpy(&saved_data, &call->data, sizeof(call->data)); 279 375 preprocess = 1; 280 376 } … … 283 379 IPC_SET_ARG1(call->data, arg1); 284 380 IPC_SET_ARG2(call->data, arg2); 381 285 382 if (preprocess) 286 answer_preprocess(call, &saved_ call);383 answer_preprocess(call, &saved_data); 287 384 288 385 ipc_answer(&TASK->answerbox, call); … … 294 391 { 295 392 call_t *call; 296 call_t saved_call;393 ipc_data_t saved_data; 297 394 int preprocess = 0; 298 395 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; 303 399 304 400 if (answer_will_preprocess(call)) { 305 memcpy(&saved_ call.data, &call->data, sizeof(call->data));401 memcpy(&saved_data, &call->data, sizeof(call->data)); 306 402 preprocess = 1; 307 403 } … … 309 405 310 406 if (preprocess) 311 answer_preprocess(call, &saved_ call);407 answer_preprocess(call, &saved_data); 312 408 313 409 ipc_answer(&TASK->answerbox, call); … … 328 424 phone = get_phone(phoneid); 329 425 if (!phone) 330 return IPC_CALLRET_FATAL;426 return ENOENT; 331 427 332 428 ipc_call_init(&call); … … 344 440 } 345 441 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 346 469 /** Wait for incoming ipc call or answer 347 470 * … … 363 486 restart: 364 487 call = ipc_wait_for_call(&TASK->answerbox, flags); 488 printf("Received call %P from sender: %P\n", call, call->sender); 365 489 366 490 if (call->flags & IPC_CALL_ANSWERED) { -
generic/src/main/kinit.c
rd764ddc r2ba7810 144 144 145 145 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 149 150 printf("Userspace not started.\n"); 150 151 } -
generic/src/proc/task.c
rd764ddc r2ba7810 70 70 ipl_t ipl; 71 71 task_t *ta; 72 int i; 72 73 73 74 ta = (task_t *) malloc(sizeof(task_t), 0); … … 78 79 ta->as = as; 79 80 81 80 82 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]); 82 85 if (ipc_phone_0) 83 ipc_phone_ init(&ta->phones[0], ipc_phone_0);86 ipc_phone_connect(&ta->phones[0], ipc_phone_0); 84 87 atomic_set(&ta->active_calls, 0); 85 88 -
generic/src/syscall/syscall.c
rd764ddc r2ba7810 82 82 sys_ipc_answer_fast, 83 83 sys_ipc_answer, 84 sys_ipc_forward_fast, 84 85 sys_ipc_wait_for_call, 85 sys_ipc_connect_to_me 86 sys_ipc_connect_to_me, 87 sys_ipc_connect_me_to 86 88 };
Note:
See TracChangeset
for help on using the changeset viewer.