Rev 4430 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4430 | Rev 4460 | ||
|---|---|---|---|
| Line 334... | Line 334... | ||
| 334 | answer->buffer = NULL; |
334 | answer->buffer = NULL; |
| 335 | } |
335 | } |
| 336 | return 0; |
336 | return 0; |
| 337 | } |
337 | } |
| 338 | 338 | ||
| - | 339 | static void phones_lock(phone_t *p1, phone_t *p2) |
|
| - | 340 | { |
|
| - | 341 | if (p1 < p2) { |
|
| - | 342 | mutex_lock(&p1->lock); |
|
| - | 343 | mutex_lock(&p2->lock); |
|
| - | 344 | } else if (p1 > p2) { |
|
| - | 345 | mutex_lock(&p2->lock); |
|
| - | 346 | mutex_lock(&p1->lock); |
|
| - | 347 | } else { |
|
| - | 348 | mutex_lock(&p1->lock); |
|
| - | 349 | } |
|
| - | 350 | } |
|
| - | 351 | ||
| - | 352 | static void phones_unlock(phone_t *p1, phone_t *p2) |
|
| - | 353 | { |
|
| - | 354 | mutex_unlock(&p1->lock); |
|
| - | 355 | if (p1 != p2) |
|
| - | 356 | mutex_unlock(&p2->lock); |
|
| - | 357 | } |
|
| - | 358 | ||
| 339 | /** Called before the request is sent. |
359 | /** Called before the request is sent. |
| 340 | * |
360 | * |
| 341 | * @param call Call structure with the request. |
361 | * @param call Call structure with the request. |
| 342 | * @param phone Phone that the call will be sent through. |
362 | * @param phone Phone that the call will be sent through. |
| 343 | * |
363 | * |
| Line 353... | Line 373... | ||
| 353 | switch (IPC_GET_METHOD(call->data)) { |
373 | switch (IPC_GET_METHOD(call->data)) { |
| 354 | case IPC_M_CONNECTION_CLONE: { |
374 | case IPC_M_CONNECTION_CLONE: { |
| 355 | phone_t *cloned_phone; |
375 | phone_t *cloned_phone; |
| 356 | GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data), |
376 | GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data), |
| 357 | return ENOENT); |
377 | return ENOENT); |
| 358 | if (cloned_phone < phone) { |
- | |
| 359 | mutex_lock(&cloned_phone->lock); |
378 | phones_lock(cloned_phone, phone); |
| 360 | mutex_lock(&phone->lock); |
- | |
| 361 | } else if (cloned_phone > phone) { |
- | |
| 362 | mutex_lock(&phone->lock); |
- | |
| 363 | mutex_lock(&cloned_phone->lock); |
- | |
| 364 | } else { |
- | |
| 365 | mutex_lock(&phone->lock); |
- | |
| 366 | } |
- | |
| 367 | if ((cloned_phone->state != IPC_PHONE_CONNECTED) || |
379 | if ((cloned_phone->state != IPC_PHONE_CONNECTED) || |
| 368 | phone->state != IPC_PHONE_CONNECTED) { |
380 | phone->state != IPC_PHONE_CONNECTED) { |
| 369 | if (cloned_phone != phone) |
- | |
| 370 | mutex_unlock(&cloned_phone->lock); |
381 | phones_unlock(cloned_phone, phone); |
| 371 | mutex_unlock(&phone->lock); |
- | |
| 372 | return EINVAL; |
382 | return EINVAL; |
| 373 | } |
383 | } |
| 374 | /* |
384 | /* |
| 375 | * We can be pretty sure now that both tasks exist and we are |
385 | * We can be pretty sure now that both tasks exist and we are |
| 376 | * connected to them. As we continue to hold the phone locks, |
386 | * connected to them. As we continue to hold the phone locks, |
| 377 | * we are effectively preventing them from finishing their |
387 | * we are effectively preventing them from finishing their |
| 378 | * potential cleanup. |
388 | * potential cleanup. |
| 379 | */ |
389 | */ |
| 380 | newphid = phone_alloc(phone->callee->task); |
390 | newphid = phone_alloc(phone->callee->task); |
| 381 | if (newphid < 0) { |
391 | if (newphid < 0) { |
| 382 | if (cloned_phone != phone) |
- | |
| 383 | mutex_unlock(&cloned_phone->lock); |
392 | phones_unlock(cloned_phone, phone); |
| 384 | mutex_unlock(&phone->lock); |
- | |
| 385 | return ELIMIT; |
393 | return ELIMIT; |
| 386 | } |
394 | } |
| 387 | ipc_phone_connect(&phone->callee->task->phones[newphid], |
395 | ipc_phone_connect(&phone->callee->task->phones[newphid], |
| 388 | cloned_phone->callee); |
396 | cloned_phone->callee); |
| 389 | if (cloned_phone != phone) |
- | |
| 390 | mutex_unlock(&cloned_phone->lock); |
397 | phones_unlock(cloned_phone, phone); |
| 391 | mutex_unlock(&phone->lock); |
- | |
| 392 | /* Set the new phone for the callee. */ |
398 | /* Set the new phone for the callee. */ |
| 393 | IPC_SET_ARG1(call->data, newphid); |
399 | IPC_SET_ARG1(call->data, newphid); |
| 394 | break; |
400 | break; |
| 395 | } |
401 | } |
| 396 | case IPC_M_CONNECT_ME: |
402 | case IPC_M_CONNECT_ME: |