diff options
| author | Nick Piggin <npiggin@suse.de> | 2009-12-15 19:47:29 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:20:09 -0500 |
| commit | 9cad200c7686708b326520a45dd680a4147568a6 (patch) | |
| tree | 76a3299679ef23c945e9371f330559d6bc3d0a43 /ipc | |
| parent | bf17bb717759d50a2733a7a8157a7c4a25d93abc (diff) | |
ipc/sem.c: sem use list operations
Replace the handcoded list operations in update_queue() with the standard
list_for_each_entry macros.
list_for_each_entry_safe() must be used, because list entries can
disappear immediately uppon the wakeup event.
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
Cc: Pierre Peiffer <peifferp@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/sem.c | 75 |
1 files changed, 31 insertions, 44 deletions
| @@ -403,58 +403,45 @@ undo: | |||
| 403 | */ | 403 | */ |
| 404 | static void update_queue (struct sem_array * sma) | 404 | static void update_queue (struct sem_array * sma) |
| 405 | { | 405 | { |
| 406 | int error; | 406 | struct sem_queue *q, *tq; |
| 407 | struct sem_queue * q; | 407 | |
| 408 | again: | ||
| 409 | list_for_each_entry_safe(q, tq, &sma->sem_pending, list) { | ||
| 410 | int error; | ||
| 411 | int alter; | ||
| 408 | 412 | ||
| 409 | q = list_entry(sma->sem_pending.next, struct sem_queue, list); | ||
| 410 | while (&q->list != &sma->sem_pending) { | ||
| 411 | error = try_atomic_semop(sma, q->sops, q->nsops, | 413 | error = try_atomic_semop(sma, q->sops, q->nsops, |
| 412 | q->undo, q->pid); | 414 | q->undo, q->pid); |
| 413 | 415 | ||
| 414 | /* Does q->sleeper still need to sleep? */ | 416 | /* Does q->sleeper still need to sleep? */ |
| 415 | if (error <= 0) { | 417 | if (error > 0) |
| 416 | struct sem_queue *n; | 418 | continue; |
| 417 | 419 | ||
| 418 | /* | 420 | list_del(&q->list); |
| 419 | * Continue scanning. The next operation | ||
| 420 | * that must be checked depends on the type of the | ||
| 421 | * completed operation: | ||
| 422 | * - if the operation modified the array, then | ||
| 423 | * restart from the head of the queue and | ||
| 424 | * check for threads that might be waiting | ||
| 425 | * for semaphore values to become 0. | ||
| 426 | * - if the operation didn't modify the array, | ||
| 427 | * then just continue. | ||
| 428 | * The order of list_del() and reading ->next | ||
| 429 | * is crucial: In the former case, the list_del() | ||
| 430 | * must be done first [because we might be the | ||
| 431 | * first entry in ->sem_pending], in the latter | ||
| 432 | * case the list_del() must be done last | ||
| 433 | * [because the list is invalid after the list_del()] | ||
| 434 | */ | ||
| 435 | if (q->alter) { | ||
| 436 | list_del(&q->list); | ||
| 437 | n = list_entry(sma->sem_pending.next, | ||
| 438 | struct sem_queue, list); | ||
| 439 | } else { | ||
| 440 | n = list_entry(q->list.next, struct sem_queue, | ||
| 441 | list); | ||
| 442 | list_del(&q->list); | ||
| 443 | } | ||
| 444 | 421 | ||
| 445 | /* wake up the waiting thread */ | 422 | /* |
| 446 | q->status = IN_WAKEUP; | 423 | * The next operation that must be checked depends on the type |
| 424 | * of the completed operation: | ||
| 425 | * - if the operation modified the array, then restart from the | ||
| 426 | * head of the queue and check for threads that might be | ||
| 427 | * waiting for semaphore values to become 0. | ||
| 428 | * - if the operation didn't modify the array, then just | ||
| 429 | * continue. | ||
| 430 | */ | ||
| 431 | alter = q->alter; | ||
| 432 | |||
| 433 | /* wake up the waiting thread */ | ||
| 434 | q->status = IN_WAKEUP; | ||
| 447 | 435 | ||
| 448 | wake_up_process(q->sleeper); | 436 | wake_up_process(q->sleeper); |
| 449 | /* hands-off: q will disappear immediately after | 437 | /* hands-off: q will disappear immediately after |
| 450 | * writing q->status. | 438 | * writing q->status. |
| 451 | */ | 439 | */ |
| 452 | smp_wmb(); | 440 | smp_wmb(); |
| 453 | q->status = error; | 441 | q->status = error; |
| 454 | q = n; | 442 | |
| 455 | } else { | 443 | if (alter) |
| 456 | q = list_entry(q->list.next, struct sem_queue, list); | 444 | goto again; |
| 457 | } | ||
| 458 | } | 445 | } |
| 459 | } | 446 | } |
| 460 | 447 | ||
