Changeset eb3d379 in mainline for generic/src/ipc/ipc.c
- 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
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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));
Note:
See TracChangeset
for help on using the changeset viewer.