Changeset eb3d379 in mainline
- Timestamp:
- 2006-06-04T15:58:01Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8adafa0
- Parents:
- 7669bcf
- Location:
- generic
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
generic/include/ipc/ipc.h
r7669bcf reb3d379 179 179 180 180 typedef enum { 181 IPC_BUSY_FREE = 0, 182 IPC_BUSY_CONNECTING, 183 IPC_BUSY_CONNECTED 184 } ipc_busy_t; 181 IPC_PHONE_FREE = 0, /**< Phone is free and can be allocated */ 182 IPC_PHONE_CONNECTING, /**< Phone is connecting somewhere */ 183 IPC_PHONE_CONNECTED, /**< Phone is connected */ 184 IPC_PHONE_HUNGUP, /**< Phone is hung up, waiting for answers to come */ 185 IPC_PHONE_SLAMMED /**< Phone was hungup from server */ 186 } ipc_phone_state_t; 185 187 186 188 struct phone_s { … … 188 190 link_t list; 189 191 answerbox_t *callee; 190 ipc_ busy_t busy;192 ipc_phone_state_t state; 191 193 atomic_t active_calls; 192 194 }; … … 223 225 extern int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox); 224 226 extern void ipc_cleanup(task_t *task); 225 extern int ipc_phone_hangup(phone_t *phone );227 extern int ipc_phone_hangup(phone_t *phone, int aggressive); 226 228 extern void ipc_backsend_err(phone_t *phone, call_t *call, __native err); 227 229 -
generic/include/proc/task.h
r7669bcf reb3d379 52 52 answerbox_t answerbox; /**< Communication endpoint */ 53 53 phone_t phones[IPC_MAX_PHONES]; 54 atomic_t active_calls; /**< Active asynchronous messages */ 54 atomic_t active_calls; /**< Active asynchronous messages. 55 * It is used for limiting uspace to 56 * certain extent. */ 55 57 56 58 task_arch_t arch; /**< Architecture specific task data. */ -
generic/src/ipc/ipc.c
r7669bcf reb3d379 112 112 113 113 ASSERT(!phone->callee); 114 phone-> busy = IPC_BUSY_CONNECTED;114 phone->state = IPC_PHONE_CONNECTED; 115 115 phone->callee = box; 116 116 … … 128 128 spinlock_initialize(&phone->lock, "phone_lock"); 129 129 phone->callee = NULL; 130 phone-> busy = IPC_BUSY_FREE;130 phone->state = IPC_PHONE_FREE; 131 131 atomic_set(&phone->active_calls, 0); 132 132 } … … 185 185 call->data.phone = phone; 186 186 atomic_inc(&phone->active_calls); 187 if (phone->busy == IPC_BUSY_CONNECTED) 188 IPC_SET_RETVAL(call->data, EHANGUP); 189 else 190 IPC_SET_RETVAL(call->data, ENOENT); 191 187 IPC_SET_RETVAL(call->data, err); 192 188 _ipc_answer_free_call(call); 193 189 } … … 217 213 218 214 spinlock_lock(&phone->lock); 219 220 box = phone->callee; 221 if (!box) { 222 /* Trying to send over disconnected phone */ 215 if (phone->state != IPC_PHONE_CONNECTED) { 223 216 spinlock_unlock(&phone->lock); 224 217 if (call->flags & IPC_CALL_FORWARDED) { 225 218 IPC_SET_RETVAL(call->data, EFORWARD); 226 219 _ipc_answer_free_call(call); 227 } else { /* Simulate sending back a message */228 if (phone-> busy == IPC_BUSY_CONNECTED)220 } else { 221 if (phone->state == IPC_PHONE_HUNGUP) 229 222 ipc_backsend_err(phone, call, EHANGUP); 230 223 else 231 224 ipc_backsend_err(phone, call, ENOENT); 232 225 } 233 234 226 return ENOENT; 235 227 } 228 box = phone->callee; 236 229 _ipc_call(phone, box, call); 237 230 … … 242 235 /** Disconnect phone from answerbox 243 236 * 244 * It is allowed to call disconnect on already disconnected phone 245 * 237 * This call leaves the phone in HUNGUP state. The change to 'free' is done 238 * lazily later. 239 * 240 * @param phone Phone to be hung up 241 * @param aggressive If false, the phone is only marked hungup, and all 242 * messages are allowed to complete. 243 * If true, all messages in all queues are discarded. There 244 * may still be some messages that will be 'in-transit' on 245 * other CPU. 246 * 246 247 * @return 0 - phone disconnected, -1 - the phone was already disconnected 247 248 */ 248 int ipc_phone_hangup(phone_t *phone )249 int ipc_phone_hangup(phone_t *phone, int aggressive) 249 250 { 250 251 answerbox_t *box; … … 252 253 253 254 spinlock_lock(&phone->lock); 255 if (phone->state == IPC_PHONE_FREE || phone->state ==IPC_PHONE_HUNGUP \ 256 || phone->state == IPC_PHONE_CONNECTING) { 257 spinlock_unlock(&phone->lock); 258 return -1; 259 } 254 260 box = phone->callee; 255 if (!box) { 256 if (phone->busy == IPC_BUSY_CONNECTING) { 257 spinlock_unlock(&phone->lock); 258 return -1; 261 if (phone->state != IPC_PHONE_SLAMMED) { 262 /* Remove myself from answerbox */ 263 spinlock_lock(&box->lock); 264 list_remove(&phone->list); 265 spinlock_unlock(&box->lock); 266 267 if (phone->state != IPC_PHONE_SLAMMED) { 268 call = ipc_call_alloc(0); 269 IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); 270 call->flags |= IPC_CALL_DISCARD_ANSWER; 271 _ipc_call(phone, box, call); 259 272 } 260 /* Already disconnected phone */ 261 phone->busy = IPC_BUSY_FREE; 262 spinlock_unlock(&phone->lock); 263 return 0; 264 } 265 266 spinlock_lock(&box->lock); 267 list_remove(&phone->list); 268 phone->callee = NULL; 269 spinlock_unlock(&box->lock); 270 271 call = ipc_call_alloc(0); 272 IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); 273 call->flags |= IPC_CALL_DISCARD_ANSWER; 274 _ipc_call(phone, box, call); 275 276 phone->busy = IPC_BUSY_FREE; 277 273 } 274 275 if (aggressive && atomic_get(&phone->active_calls) > 0) { 276 /* TODO: Do some stuff be VERY aggressive */ 277 } 278 279 phone->callee = 0; 280 281 phone->state = IPC_PHONE_HUNGUP; 278 282 spinlock_unlock(&phone->lock); 279 283 … … 381 385 /* Disconnect all our phones ('ipc_phone_hangup') */ 382 386 for (i=0;i < IPC_MAX_PHONES; i++) 383 ipc_phone_hangup(&task->phones[i] );387 ipc_phone_hangup(&task->phones[i], 1); 384 388 385 389 /* Disconnect all connected irqs */ … … 399 403 400 404 /* Disconnect phone */ 401 phone->callee = NULL; 405 ASSERT(phone->state == IPC_PHONE_CONNECTED); 406 phone->state = IPC_PHONE_SLAMMED; 402 407 list_remove(&phone->list); 403 408 … … 412 417 413 418 /* Wait for all async answers to arrive */ 414 while (atomic_get(&task->active_calls)) { 419 while (1) { 420 /* Go through all phones, until all are FREE... */ 421 /* Locking not needed, no one else should modify 422 * it, when we are in cleanup */ 423 for (i=0;i < IPC_MAX_PHONES; i++) { 424 if (task->phones[i].state == IPC_PHONE_HUNGUP && \ 425 atomic_get(&task->phones[i].active_calls) == 0) 426 task->phones[i].state = IPC_PHONE_FREE; 427 if (task->phones[i].state != IPC_PHONE_FREE) 428 break; 429 } 430 /* Voila, got into cleanup */ 431 if (i == IPC_MAX_PHONES) 432 break; 433 415 434 call = ipc_wait_for_call(&task->answerbox, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); 416 435 ASSERT((call->flags & IPC_CALL_ANSWERED) || (call->flags & IPC_CALL_NOTIF)); -
generic/src/ipc/ipcrsc.c
r7669bcf reb3d379 159 159 160 160 for (i=0; i < IPC_MAX_PHONES; i++) { 161 if (TASK->phones[i].busy==IPC_BUSY_FREE && !atomic_get(&TASK->phones[i].active_calls)) { 162 TASK->phones[i].busy = IPC_BUSY_CONNECTING; 161 if (TASK->phones[i].state == IPC_PHONE_HUNGUP && \ 162 atomic_get(&TASK->phones[i].active_calls) == 0) 163 TASK->phones[i].state = IPC_PHONE_FREE; 164 165 if (TASK->phones[i].state == IPC_PHONE_FREE) { 166 TASK->phones[i].state = IPC_PHONE_CONNECTING; 163 167 break; 164 168 } … … 173 177 static void phone_deallocp(phone_t *phone) 174 178 { 175 ASSERT(phone-> busy == IPC_BUSY_CONNECTING);179 ASSERT(phone->state == IPC_PHONE_CONNECTING); 176 180 ASSERT(! phone->callee); 177 181 178 182 /* atomic operation */ 179 phone-> busy = IPC_BUSY_FREE;183 phone->state = IPC_PHONE_FREE; 180 184 } 181 185 … … 201 205 phone_t *phone = &TASK->phones[phoneid]; 202 206 203 ASSERT(phone-> busy == IPC_BUSY_CONNECTING);207 ASSERT(phone->state == IPC_PHONE_CONNECTING); 204 208 ipc_phone_connect(phone, box); 205 209 } -
generic/src/ipc/sysipc.c
r7669bcf reb3d379 106 106 spinlock_lock(&answer->data.phone->lock); 107 107 spinlock_lock(&TASK->answerbox.lock); 108 if (answer->data.phone-> callee) {108 if (answer->data.phone->state == IPC_PHONE_CONNECTED) { 109 109 list_remove(&answer->data.phone->list); 110 answer->data.phone-> callee = 0;110 answer->data.phone->state = IPC_PHONE_SLAMMED; 111 111 } 112 112 spinlock_unlock(&TASK->answerbox.lock); … … 493 493 GET_CHECK_PHONE(phone, phoneid, return ENOENT); 494 494 495 if (ipc_phone_hangup(phone ))495 if (ipc_phone_hangup(phone, 0)) 496 496 return -1; 497 497 -
generic/src/mm/frame.c
r7669bcf reb3d379 135 135 * Insert-sort zone into zones list 136 136 * 137 * @param newzone New zone to be inserted into zone list 137 138 * @return zone number on success, -1 on error 138 139 */ … … 173 174 * Try to find a zone where can we find the frame 174 175 * 175 * @param hint Start searching in zone 'hint' 176 * @param lock Lock zone if true 176 * @param frame Frame number contained in zone 177 * @param pzone If not null, it is used as zone hint. Zone index 178 * is filled into the variable on success. 179 * @return Pointer to LOCKED zone containing frame 177 180 * 178 181 * Assume interrupts disable … … 221 224 * Assume interrupts are disabled!! 222 225 * 226 * @param order Size (2^order) of free space we are trying to find 223 227 * @param pzone Pointer to preferred zone or NULL, on return contains zone number 224 228 */ … … 469 473 * 470 474 * Assume zone is locked 475 * 476 * @param zone Pointer to zone from which the frame is to be freed 477 * @param frame_idx Frame index relative to zone 471 478 */ 472 479 static void zone_frame_free(zone_t *zone, index_t frame_idx) … … 519 526 * 520 527 * Assume z1 & z2 are locked 528 * 529 * @param z Target zone structure pointer 530 * @param z1 Zone to merge 531 * @param z2 Zone to merge 521 532 */ 522 533 … … 628 639 * 629 640 * The allocated block need 2^order frames of space. Reduce all frames 630 * in block to order 0 and free the unneded frames. This means, that 631 * when freeing the block, you have to free every frame from block. 641 * in block to order 0 and free the unneeded frames. This means, that 642 * when freeing the previously allocated block starting with frame_idx, 643 * you have to free every frame. 632 644 * 633 645 * @param zone … … 752 764 * 753 765 * @param start Physical address of the first frame within the zone. 754 * @param size Size of the zone. Must be a multiple of FRAME_SIZE.755 * @param conffram Address of configuration frame766 * @param count Count of frames in zone 767 * @param z Address of configuration information of zone 756 768 * @param flags Zone flags. 757 769 * … … 794 806 } 795 807 796 /** Compute configuration data size for zone */ 808 /** Compute configuration data size for zone 809 * 810 * @param count Size of zone in frames 811 * @return Size of zone configuration info (in bytes) 812 */ 797 813 __address zone_conf_size(count_t count) 798 814 { … … 807 823 /** Create and add zone to system 808 824 * 809 * @param confframe Where configuration frame is supposed to be. 810 * Always check, that we will not disturb the kernel and possibly init. 825 * @param start First frame number (absolute) 826 * @param count Size of zone in frames 827 * @param confframe Where configuration frames are supposed to be. 828 * Automatically checks, that we will not disturb the 829 * kernel and possibly init. 811 830 * If confframe is given _outside_ this zone, it is expected, 812 831 * that the area is already marked BUSY and big enough 813 * to contain zone_conf_size() amount of data 832 * to contain zone_conf_size() amount of data. 833 * If the confframe is inside the area, the zone free frame 834 * information is modified not to include it. 814 835 * 815 836 * @return Zone number or -1 on error
Note:
See TracChangeset
for help on using the changeset viewer.