Changeset 7c7aae16 in mainline
- Timestamp:
- 2006-03-19T19:42:00Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ad64a2d
- Parents:
- 9f22213
- Location:
- generic
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/include/ipc/ipc.h
r9f22213 r7c7aae16 40 40 #define IPC_CALL_ANSWERED (1<<0) /**< This is answer to a call */ 41 41 #define IPC_CALL_STATIC_ALLOC (1<<1) /**< This call will not be freed on error */ 42 #define IPC_CALL_DISPATCHED (1<<2) /**< Call is in dispatch queue */ 43 #define IPC_CALL_DISCARD_ANSWER (1<<3) /**< Answer will not be passed to 42 #define IPC_CALL_DISCARD_ANSWER (1<<2) /**< Answer will not be passed to 44 43 * userspace, will be discarded */ 45 #define IPC_CALL_FORWARDED (1<<4) /* Call was forwarded */ 44 #define IPC_CALL_FORWARDED (1<<3) /* Call was forwarded */ 45 #define IPC_CALL_CONN_ME_TO (1<<4) /* Identify connect_me_to */ 46 46 47 47 /* Flags for ipc_wait_for_call */ … … 183 183 answerbox_t *callerbox; 184 184 185 ipc_data_t data; 185 __native private; /**< Private data to internal IPC */ 186 187 ipc_data_t data; /**< Data passed from/to userspace */ 186 188 }call_t; 187 189 … … 199 201 extern void task_print_list(void); 200 202 extern int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox); 201 202 extern answerbox_t *ipc_phone_0;203 203 extern void ipc_cleanup(task_t *task); 204 204 extern int ipc_phone_hangup(phone_t *phone); 205 extern void ipc_backsend_err(phone_t *phone, call_t *call, __native err); 206 207 extern answerbox_t *ipc_phone_0; 205 208 206 209 #endif -
generic/include/ipc/sysipc.h
r9f22213 r7c7aae16 40 40 __native arg1, __native arg2); 41 41 __native sys_ipc_answer(__native callid, ipc_data_t *data); 42 __native sys_ipc_connect_to_me(__native phoneid, __native arg1, 43 __native arg2, task_id_t *taskid); 44 __native sys_ipc_wait_for_call(ipc_data_t *calldata, task_id_t *taskid, 45 __native flags); 46 __native sys_ipc_connect_me_to(__native phoneid, __native arg1, 47 __native arg2); 42 __native sys_ipc_wait_for_call(ipc_data_t *calldata, __native flags); 48 43 __native sys_ipc_forward_fast(__native callid, __native phoneid, 49 44 __native method, __native arg1); -
generic/include/syscall/syscall.h
r9f22213 r7c7aae16 44 44 SYS_IPC_FORWARD_FAST, 45 45 SYS_IPC_WAIT, 46 SYS_IPC_CONNECT_TO_ME,47 SYS_IPC_CONNECT_ME_TO,48 46 SYS_IPC_HANGUP, 49 47 SYSCALL_END -
generic/src/ipc/ipc.c
r9f22213 r7c7aae16 146 146 answerbox_t *callerbox = call->callerbox; 147 147 148 call->flags &= ~IPC_CALL_DISPATCHED;149 148 call->flags |= IPC_CALL_ANSWERED; 150 149 … … 167 166 spinlock_unlock(&box->lock); 168 167 /* Send back answer */ 168 _ipc_answer_free_call(call); 169 } 170 171 /** Simulate sending back a message 172 * 173 * Most errors are better handled by forming a normal backward 174 * message and sending it as a normal answer. 175 */ 176 void ipc_backsend_err(phone_t *phone, call_t *call, __native err) 177 { 178 call->data.phone = phone; 179 atomic_inc(&phone->active_calls); 180 if (phone->busy == IPC_BUSY_CONNECTED) 181 IPC_SET_RETVAL(call->data, EHANGUP); 182 else 183 IPC_SET_RETVAL(call->data, ENOENT); 184 169 185 _ipc_answer_free_call(call); 170 186 } … … 201 217 if (call->flags & IPC_CALL_FORWARDED) { 202 218 IPC_SET_RETVAL(call->data, EFORWARD); 203 } else { /* Simulate sending a message */ 204 call->data.phone = phone; 205 atomic_inc(&phone->active_calls); 219 _ipc_answer_free_call(call); 220 } else { /* Simulate sending back a message */ 206 221 if (phone->busy == IPC_BUSY_CONNECTED) 207 IPC_SET_RETVAL(call->data, EHANGUP);222 ipc_backsend_err(phone, call, EHANGUP); 208 223 else 209 IPC_SET_RETVAL(call->data, ENOENT);224 ipc_backsend_err(phone, call, ENOENT); 210 225 } 211 226 212 _ipc_answer_free_call(call);213 227 return ENOENT; 214 228 } … … 308 322 /* Append request to dispatch queue */ 309 323 list_append(&request->list, &box->dispatched_calls); 310 request->flags |= IPC_CALL_DISPATCHED;311 324 } else { 312 325 printf("WARNING: Spurious IPC wakeup.\n"); -
generic/src/ipc/ipcrsc.c
r9f22213 r7c7aae16 63 63 * Destroying is less frequent, this approach is taken. 64 64 * 65 * Phone call 66 * 67 * *** Connect_me_to *** 68 * The caller sends IPC_M_CONNECT_ME_TO to an answerbox. The server 69 * receives 'phoneid' of the connecting phone as an ARG3. If it answers 70 * with RETVAL=0, the phonecall is accepted, otherwise it is refused. 71 * 72 * *** Connect_to_me *** 73 * The caller sends IPC_M_CONNECT_TO_ME, with special 74 * The server receives an automatically 75 * opened phoneid. If it accepts (RETVAL=0), it can use the phoneid 76 * immediately. 77 * Possible race condition can arise, when the client receives messages 78 * from new connection before getting response for connect_to_me message. 79 * Userspace should implement handshake protocol that would control it. 80 * 65 81 * Phone hangup 66 82 * … … 101 117 * appropriate error code (EHANGUP, EFORWARD). 102 118 * 103 * 4) Wait for all async answers to arrive .119 * 4) Wait for all async answers to arrive and dispose of them. 104 120 * 105 121 */ … … 143 159 } 144 160 145 /** Disconnect phone a free the slot 161 static void phone_deallocp(phone_t *phone) 162 { 163 ASSERT(phone->busy == IPC_BUSY_CONNECTING); 164 ASSERT(! phone->callee); 165 166 /* atomic operation */ 167 phone->busy = IPC_BUSY_FREE; 168 } 169 170 /** Free slot from a disconnected phone 146 171 * 147 172 * All already sent messages will be correctly processed … … 149 174 void phone_dealloc(int phoneid) 150 175 { 151 spinlock_lock(&TASK->lock); 152 153 ASSERT(TASK->phones[phoneid].busy == IPC_BUSY_CONNECTING); 154 ASSERT(! TASK->phones[phoneid].callee); 155 156 TASK->phones[phoneid].busy = IPC_BUSY_FREE; 157 spinlock_unlock(&TASK->lock); 176 phone_deallocp(&TASK->phones[phoneid]); 158 177 } 159 178 -
generic/src/ipc/sysipc.c
r9f22213 r7c7aae16 48 48 } 49 49 50 #define STRUCT_TO_USPACE(dst,src) copy_to_uspace(dst,src,sizeof(* src))50 #define STRUCT_TO_USPACE(dst,src) copy_to_uspace(dst,src,sizeof(*(src))) 51 51 52 52 /** Return true if the method is a system method */ … … 106 106 phone_dealloc(phoneid); 107 107 } else { 108 108 /* The connection was accepted */ 109 109 phone_connect(phoneid,&answer->sender->answerbox); 110 /* Set 'phone identification' as arg3 of response */ 111 IPC_SET_ARG3(answer->data, (__native)&TASK->phones[phoneid]); 110 112 } 111 113 } else if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_ME_TO) { … … 118 120 } 119 121 122 /** Called before the request is sent 123 * 124 * @return 0 - no error, -1 - report error to user 125 */ 126 static int request_preprocess(call_t *call) 127 { 128 int newphid; 129 130 switch (IPC_GET_METHOD(call->data)) { 131 case IPC_M_CONNECT_ME_TO: 132 newphid = phone_alloc(); 133 if (newphid < 0) 134 return ELIMIT; 135 /* Set arg3 for server */ 136 IPC_SET_ARG3(call->data, (__native)&TASK->phones[newphid]); 137 call->flags |= IPC_CALL_CONN_ME_TO; 138 call->private = newphid; 139 break; 140 default: 141 break; 142 } 143 return 0; 144 } 145 120 146 /****************************************************/ 121 147 /* Functions called to process received call/answer … … 124 150 125 151 /** Do basic kernel processing of received call answer */ 126 static int process_answer(answerbox_t *box,call_t *call)152 static void process_answer(call_t *call) 127 153 { 128 154 if (IPC_GET_RETVAL(call->data) == EHANGUP && \ 129 155 call->flags & IPC_CALL_FORWARDED) 130 156 IPC_SET_RETVAL(call->data, EFORWARD); 131 return 0; 157 158 if (call->flags & IPC_CALL_CONN_ME_TO) { 159 if (IPC_GET_RETVAL(call->data)) 160 phone_dealloc(call->private); 161 else 162 IPC_SET_ARG3(call->data, call->private); 163 } 132 164 } 133 165 … … 162 194 call_t call; 163 195 phone_t *phone; 164 165 if (is_system_method(method)) 166 return EPERM; 196 int res; 167 197 168 198 GET_CHECK_PHONE(phone, phoneid, return ENOENT); … … 171 201 IPC_SET_METHOD(call.data, method); 172 202 IPC_SET_ARG1(call.data, arg1); 173 174 ipc_call_sync(phone, &call); 175 203 204 if (!(res=request_preprocess(&call))) { 205 ipc_call_sync(phone, &call); 206 process_answer(&call); 207 } else 208 IPC_SET_RETVAL(call.data, res); 176 209 STRUCT_TO_USPACE(&data->args, &call.data.args); 177 210 … … 185 218 call_t call; 186 219 phone_t *phone; 220 int res; 187 221 188 222 ipc_call_static_init(&call); 189 223 copy_from_uspace(&call.data.args, &question->args, sizeof(call.data.args)); 190 224 191 if (is_system_method(IPC_GET_METHOD(call.data)))192 return EPERM;193 194 225 GET_CHECK_PHONE(phone, phoneid, return ENOENT); 195 226 196 ipc_call_sync(phone, &call); 227 if (!(res=request_preprocess(&call))) { 228 ipc_call_sync(phone, &call); 229 process_answer(&call); 230 } else 231 IPC_SET_RETVAL(call.data, res); 197 232 198 233 STRUCT_TO_USPACE(&reply->args, &call.data.args); … … 224 259 call_t *call; 225 260 phone_t *phone; 226 227 if (is_system_method(method)) 228 return IPC_CALLRET_FATAL; 261 int res; 229 262 230 263 if (check_call_limit()) 231 264 return IPC_CALLRET_TEMPORARY; 232 265 233 GET_CHECK_PHONE(phone, phoneid, return ENOENT);266 GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL); 234 267 235 268 call = ipc_call_alloc(); … … 238 271 IPC_SET_ARG2(call->data, arg2); 239 272 240 ipc_call(phone, call); 273 if (!(res=request_preprocess(call))) 274 ipc_call(phone, call); 275 else 276 ipc_backsend_err(phone, call, res); 241 277 242 278 return (__native) call; … … 251 287 call_t *call; 252 288 phone_t *phone; 289 int res; 253 290 254 291 if (check_call_limit()) 255 292 return IPC_CALLRET_TEMPORARY; 256 293 257 GET_CHECK_PHONE(phone, phoneid, return ENOENT);294 GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL); 258 295 259 296 call = ipc_call_alloc(); 260 297 copy_from_uspace(&call->data.args, &data->args, sizeof(call->data.args)); 261 262 if (is_system_method(IPC_GET_METHOD(call->data))) { 263 ipc_call_free(call); 264 return EPERM; 265 } 266 267 ipc_call(phone, call); 298 if (!(res=request_preprocess(call))) 299 ipc_call(phone, call); 300 else 301 ipc_backsend_err(phone, call, res); 268 302 269 303 return (__native) call; … … 305 339 */ 306 340 if (is_system_method(IPC_GET_METHOD(call->data))) { 341 if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) 342 phone_dealloc(IPC_GET_ARG3(call->data)); 343 307 344 IPC_SET_ARG1(call->data, method); 308 345 IPC_SET_ARG2(call->data, arg1); … … 366 403 } 367 404 368 /** Ask the other side of connection to do 'callback' connection369 *370 * @return 0 if no error, error otherwise371 */372 __native sys_ipc_connect_to_me(__native phoneid, __native arg1,373 __native arg2, task_id_t *taskid)374 {375 call_t call;376 phone_t *phone;377 378 ipc_call_static_init(&call);379 IPC_SET_METHOD(call.data, IPC_M_CONNECT_TO_ME);380 IPC_SET_ARG1(call.data, arg1);381 IPC_SET_ARG2(call.data, arg2);382 383 GET_CHECK_PHONE(phone, phoneid, return ENOENT);384 385 ipc_call_sync(phone, &call);386 387 if (!IPC_GET_RETVAL(call.data) && taskid)388 STRUCT_TO_USPACE(taskid, &phone->callee->task->taskid);389 390 return IPC_GET_RETVAL(call.data);391 }392 393 /** Ask target process to connect me somewhere394 *395 * @return phoneid - on success, error otherwise396 */397 __native sys_ipc_connect_me_to(__native phoneid, __native arg1,398 __native arg2)399 {400 call_t call;401 phone_t *phone;402 int newphid;403 404 GET_CHECK_PHONE(phone, phoneid, return ENOENT);405 406 newphid = phone_alloc();407 if (newphid < 0)408 return ELIMIT;409 410 ipc_call_static_init(&call);411 IPC_SET_METHOD(call.data, IPC_M_CONNECT_ME_TO);412 IPC_SET_ARG1(call.data, arg1);413 IPC_SET_ARG2(call.data, arg2);414 IPC_SET_ARG3(call.data, (__native)&TASK->phones[newphid]);415 416 ipc_call_sync(phone, &call);417 418 if (IPC_GET_RETVAL(call.data)) { /* Connection failed */419 phone_dealloc(newphid);420 return IPC_GET_RETVAL(call.data);421 }422 423 return newphid;424 }425 426 405 /** Hang up the phone 427 *428 *429 406 * 430 407 */ … … 449 426 * @return Callid, if callid & 1, then the call is answer 450 427 */ 451 __native sys_ipc_wait_for_call(ipc_data_t *calldata, task_id_t *taskid, 452 __native flags) 453 428 __native sys_ipc_wait_for_call(ipc_data_t *calldata, __native flags) 454 429 { 455 430 call_t *call; … … 461 436 462 437 if (call->flags & IPC_CALL_ANSWERED) { 463 if (process_answer(&TASK->answerbox, call)) 464 goto restart; 438 process_answer(call); 465 439 466 440 ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); … … 482 456 goto restart; 483 457 484 /* Include phone address('id') of the caller in the request */ 458 /* Include phone address('id') of the caller in the request, 459 * copy whole call->data, not only call->data.args */ 485 460 STRUCT_TO_USPACE(calldata, &call->data); 486 if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_ME_TO)487 STRUCT_TO_USPACE(taskid, &TASK->taskid);488 461 return (__native)call; 489 462 } -
generic/src/syscall/syscall.c
r9f22213 r7c7aae16 77 77 sys_ipc_forward_fast, 78 78 sys_ipc_wait_for_call, 79 sys_ipc_connect_to_me,80 sys_ipc_connect_me_to,81 79 sys_ipc_hangup 82 80 };
Note:
See TracChangeset
for help on using the changeset viewer.