Changeset 9f22213 in mainline
- Timestamp:
- 2006-03-19T12:43:12Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7c7aae16
- Parents:
- b4b45210
- Location:
- generic
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/include/errno.h
rb4b45210 r9f22213 38 38 #define EFORWARD -5 /* Forward error */ 39 39 #define EPERM -6 /* Permission denied */ 40 #define EHANGUP -7 /* Answerbox closed cionnection, call sys_ipc_hangup 41 * to close the connection. Used by answerbox 42 * to close the connection. */ 40 43 41 44 #endif -
generic/include/ipc/ipc.h
rb4b45210 r9f22213 38 38 39 39 /* Flags for calls */ 40 #define IPC_CALL_ANSWERED (1<<0) /**< This is answer to a call */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 */40 #define IPC_CALL_ANSWERED (1<<0) /**< This is answer to a call */ 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 43 #define IPC_CALL_DISCARD_ANSWER (1<<3) /**< Answer will not be passed to 44 44 * userspace, will be discarded */ 45 #define IPC_CALL_FORWARDED (1<<4) /* Call was forwarded */ 45 46 46 47 /* Flags for ipc_wait_for_call */ … … 156 157 }; 157 158 159 typedef enum { 160 IPC_BUSY_FREE = 0, 161 IPC_BUSY_CONNECTING, 162 IPC_BUSY_CONNECTED 163 } ipc_busy_t; 164 158 165 struct phone_s { 159 166 SPINLOCK_DECLARE(lock); 160 167 link_t list; 161 168 answerbox_t *callee; 162 i nt busy;169 ipc_busy_t busy; 163 170 atomic_t active_calls; 164 171 }; … … 182 189 extern call_t * ipc_wait_for_call(answerbox_t *box, int flags); 183 190 extern void ipc_answer(answerbox_t *box, call_t *request); 184 extern void ipc_call(phone_t *phone, call_t *request);191 extern int ipc_call(phone_t *phone, call_t *call); 185 192 extern void ipc_call_sync(phone_t *phone, call_t *request); 186 193 extern void ipc_phone_init(phone_t *phone); … … 191 198 extern void ipc_call_static_init(call_t *call); 192 199 extern void task_print_list(void); 193 extern voidipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox);200 extern int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox); 194 201 195 202 extern answerbox_t *ipc_phone_0; -
generic/src/ipc/ipc.c
rb4b45210 r9f22213 105 105 106 106 ASSERT(!phone->callee); 107 phone->busy = 1;107 phone->busy = IPC_BUSY_CONNECTED; 108 108 phone->callee = box; 109 109 … … 121 121 spinlock_initialize(&phone->lock, "phone_lock"); 122 122 phone->callee = NULL; 123 phone->busy = 0; 123 phone->busy = IPC_BUSY_FREE; 124 atomic_set(&phone->active_calls, 0); 124 125 } 125 126 … … 172 173 static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) 173 174 { 174 atomic_inc(&phone->active_calls); 175 call->data.phone = phone; 175 if (! (call->flags & IPC_CALL_FORWARDED)) { 176 atomic_inc(&phone->active_calls); 177 call->data.phone = phone; 178 } 176 179 177 180 spinlock_lock(&box->lock); … … 186 189 * @param request Request to be sent 187 190 */ 188 voidipc_call(phone_t *phone, call_t *call)191 int ipc_call(phone_t *phone, call_t *call) 189 192 { 190 193 answerbox_t *box; … … 196 199 /* Trying to send over disconnected phone */ 197 200 spinlock_unlock(&phone->lock); 198 199 call->data.phone = phone; 200 IPC_SET_RETVAL(call->data, ENOENT); 201 if (call->flags & IPC_CALL_FORWARDED) { 202 IPC_SET_RETVAL(call->data, EFORWARD); 203 } else { /* Simulate sending a message */ 204 call->data.phone = phone; 205 atomic_inc(&phone->active_calls); 206 if (phone->busy == IPC_BUSY_CONNECTED) 207 IPC_SET_RETVAL(call->data, EHANGUP); 208 else 209 IPC_SET_RETVAL(call->data, ENOENT); 210 } 211 201 212 _ipc_answer_free_call(call); 202 return ;213 return ENOENT; 203 214 } 204 215 _ipc_call(phone, box, call); 205 216 206 217 spinlock_unlock(&phone->lock); 218 return 0; 207 219 } 208 220 … … 221 233 box = phone->callee; 222 234 if (!box) { 235 if (phone->busy == IPC_BUSY_CONNECTING) { 236 spinlock_unlock(&phone->lock); 237 return -1; 238 } 239 /* Already disconnected phone */ 240 phone->busy = IPC_BUSY_FREE; 223 241 spinlock_unlock(&phone->lock); 224 return -1;242 return 0; 225 243 } 226 244 … … 235 253 _ipc_call(phone, box, call); 236 254 237 phone->busy = 0;255 phone->busy = IPC_BUSY_FREE; 238 256 239 257 spinlock_unlock(&phone->lock); … … 247 265 * @param newbox Target answerbox 248 266 * @param oldbox Old answerbox 249 */ 250 void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) 267 * @return 0 on forward ok, error code, if there was error 268 * 269 * - the return value serves only as an information for the forwarder, 270 * the original caller is notified automatically with EFORWARD 271 */ 272 int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) 251 273 { 252 274 spinlock_lock(&oldbox->lock); 253 atomic_dec(&call->data.phone->active_calls);254 275 list_remove(&call->list); 255 276 spinlock_unlock(&oldbox->lock); 256 277 257 ipc_call(newphone, call);278 return ipc_call(newphone, call); 258 279 } 259 280 … … 280 301 request = list_get_instance(box->answers.next, call_t, list); 281 302 list_remove(&request->list); 282 printf("%d %P\n", IPC_GET_METHOD(request->data),283 request->data.phone);284 303 atomic_dec(&request->data.phone->active_calls); 285 304 } else if (!list_empty(&box->calls)) { … … 314 333 void ipc_cleanup(task_t *task) 315 334 { 316 /* Cancel all calls in my dispatch queue */ 335 int i; 336 337 /* Disconnect all our phones ('ipc_phone_hangup') */ 338 for (i=0;i < IPC_MAX_PHONES; i++) 339 ipc_phone_hangup(&task->phones[i]); 340 341 /* Disconnect all phones connected to answerbox */ 342 343 /* Answer all messages in 'calls' and 'dispatched_calls' queues */ 317 344 318 } 345 /* Wait for all async answers to arrive */ 346 } -
generic/src/ipc/ipcrsc.c
rb4b45210 r9f22213 71 71 * calls are answered, the phone is deallocated. 72 72 * 73 * *** The answerbox hangs up (ipc_answer(ESLAM)) 74 * - The phone is disconnected. IPC_M_ANSWERBOX_HUNGUP notification 75 * is sent to source task, the calling process is expected to 73 * *** The answerbox hangs up (ipc_answer(EHANGUP)) 74 * - The phone is disconnected. EHANGUP response code is sent 75 * to the calling process. All new calls through this phone 76 * get a EHUNGUP error code, the task is expected to 76 77 * send an sys_ipc_hangup after cleaning up it's internal structures. 78 * 79 * Call forwarding 80 * 81 * The call can be forwarded, so that the answer to call is passed directly 82 * to the original sender. However, this poses special problems regarding 83 * routing of hangup messages. 84 * 85 * sys_ipc_hangup -> IPC_M_PHONE_HUNGUP 86 * - this message CANNOT be forwarded 87 * 88 * EHANGUP during forward 89 * - The *forwarding* phone will be closed, EFORWARD is sent to receiver. 90 * 91 * EHANGUP, ENOENT during forward 92 * - EFORWARD is sent to the receiver, ipc_forward returns error code EFORWARD 77 93 * 78 94 * Cleanup strategy 79 95 * 80 * 1) Disconnect all our phones (' sys_ipc_hangup')96 * 1) Disconnect all our phones ('ipc_phone_hangup'). 81 97 * 82 98 * 2) Disconnect all phones connected to answerbox. 83 * * Send message 'PHONE_DISCONNECTED' to the target application84 * - Once all phones are disconnected, no further calls can arrive85 99 * 86 100 * 3) Answer all messages in 'calls' and 'dispatched_calls' queues with 87 * appropriate error code .101 * appropriate error code (EHANGUP, EFORWARD). 88 102 * 89 * 4) Wait for all async answers to arrive 103 * 4) Wait for all async answers to arrive. 90 104 * 91 105 */ … … 117 131 118 132 for (i=0; i < IPC_MAX_PHONES; i++) { 119 if ( !TASK->phones[i].busy&& !atomic_get(&TASK->phones[i].active_calls)) {120 TASK->phones[i].busy = 1;133 if (TASK->phones[i].busy==IPC_BUSY_FREE && !atomic_get(&TASK->phones[i].active_calls)) { 134 TASK->phones[i].busy = IPC_BUSY_CONNECTING; 121 135 break; 122 136 } … … 137 151 spinlock_lock(&TASK->lock); 138 152 139 ASSERT(TASK->phones[phoneid].busy );153 ASSERT(TASK->phones[phoneid].busy == IPC_BUSY_CONNECTING); 140 154 ASSERT(! TASK->phones[phoneid].callee); 141 155 142 TASK->phones[phoneid].busy = 0;156 TASK->phones[phoneid].busy = IPC_BUSY_FREE; 143 157 spinlock_unlock(&TASK->lock); 144 158 } … … 156 170 phone_t *phone = &TASK->phones[phoneid]; 157 171 158 ASSERT(phone->busy );172 ASSERT(phone->busy == IPC_BUSY_CONNECTING); 159 173 ipc_phone_connect(phone, box); 160 174 } -
generic/src/ipc/sysipc.c
rb4b45210 r9f22213 76 76 77 77 /** Return true if the caller (ipc_answer) should save 78 * the old call contents and callanswer_preprocess79 */ 80 static inline int answer_ will_preprocess(call_t *call)78 * the old call contents for answer_preprocess 79 */ 80 static inline int answer_need_old(call_t *call) 81 81 { 82 82 if (IPC_GET_METHOD(call->data) == IPC_M_CONNECT_TO_ME) … … 91 91 { 92 92 int phoneid; 93 94 if (IPC_GET_RETVAL(answer->data) == EHANGUP) { 95 /* Atomic operation */ 96 answer->data.phone->callee = NULL; 97 } 98 99 if (!olddata) 100 return; 93 101 94 102 if (IPC_GET_METHOD(*olddata) == IPC_M_CONNECT_TO_ME) { … … 98 106 phone_dealloc(phoneid); 99 107 } else { 100 /* The connection was accepted */108 /* The connection was accepted */ 101 109 phone_connect(phoneid,&answer->sender->answerbox); 102 110 } … … 118 126 static int process_answer(answerbox_t *box,call_t *call) 119 127 { 128 if (IPC_GET_RETVAL(call->data) == EHANGUP && \ 129 call->flags & IPC_CALL_FORWARDED) 130 IPC_SET_RETVAL(call->data, EFORWARD); 120 131 return 0; 121 132 } … … 276 287 return ENOENT; 277 288 289 call->flags |= IPC_CALL_FORWARDED; 290 278 291 GET_CHECK_PHONE(phone, phoneid, { 279 292 IPC_SET_RETVAL(call->data, EFORWARD); … … 299 312 } 300 313 301 ipc_forward(call, phone, &TASK->answerbox); 302 303 return 0; 314 return ipc_forward(call, phone, &TASK->answerbox); 304 315 } 305 316 … … 310 321 call_t *call; 311 322 ipc_data_t saved_data; 312 int preprocess= 0;323 int saveddata = 0; 313 324 314 325 call = get_call(callid); … … 316 327 return ENOENT; 317 328 318 if (answer_ will_preprocess(call)) {329 if (answer_need_old(call)) { 319 330 memcpy(&saved_data, &call->data, sizeof(call->data)); 320 preprocess= 1;331 saveddata = 1; 321 332 } 322 333 … … 324 335 IPC_SET_ARG1(call->data, arg1); 325 336 IPC_SET_ARG2(call->data, arg2); 326 327 if (preprocess) 328 answer_preprocess(call, &saved_data); 337 answer_preprocess(call, saveddata ? &saved_data : NULL); 329 338 330 339 ipc_answer(&TASK->answerbox, call); … … 337 346 call_t *call; 338 347 ipc_data_t saved_data; 339 int preprocess= 0;348 int saveddata = 0; 340 349 341 350 call = get_call(callid); … … 343 352 return ENOENT; 344 353 345 if (answer_ will_preprocess(call)) {354 if (answer_need_old(call)) { 346 355 memcpy(&saved_data, &call->data, sizeof(call->data)); 347 preprocess= 1;356 saveddata = 1; 348 357 } 349 358 copy_from_uspace(&call->data.args, &data->args, 350 359 sizeof(call->data.args)); 351 360 352 if (preprocess) 353 answer_preprocess(call, &saved_data); 361 answer_preprocess(call, saveddata ? &saved_data : NULL); 354 362 355 363 ipc_answer(&TASK->answerbox, call); … … 449 457 restart: 450 458 call = ipc_wait_for_call(&TASK->answerbox, flags); 459 if (!call) 460 return 0; 451 461 452 462 if (call->flags & IPC_CALL_ANSWERED) {
Note:
See TracChangeset
for help on using the changeset viewer.