ipc/sem.c: Fix missing wakeups in do_smart_update_queue()

do_smart_update_queue() is called when an operation (semop,
semctl(SETVAL), semctl(SETALL), ...) modified the array. It must check
which of the sleeping tasks can proceed.

do_smart_update_queue() missed a few wakeups:
- if a sleeping complex op was completed, then all per-semaphore queues
must be scanned - not only those that were modified by *sops
- if a sleeping simple op proceeded, then the global queue must be
scanned again

And:
- the test for "|sops == NULL) before scanning the global queue is not
required: If the global queue is empty, then it doesn't need to be
scanned - regardless of the reason for calling do_smart_update_queue()

The patch is not optimized, i.e. even completing a wait-for-zero
operation causes a rescan. This is done to keep the patch as simple as
possible.

Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
Acked-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Manfred Spraul and committed by Linus Torvalds ab465df9 89ff7783

Changed files
+22 -5
ipc
+22 -5
ipc/sem.c
··· 752 752 int otime, struct list_head *pt) 753 753 { 754 754 int i; 755 + int progress; 755 756 756 - if (sma->complex_count || sops == NULL) { 757 - if (update_queue(sma, -1, pt)) 757 + progress = 1; 758 + retry_global: 759 + if (sma->complex_count) { 760 + if (update_queue(sma, -1, pt)) { 761 + progress = 1; 758 762 otime = 1; 763 + sops = NULL; 764 + } 759 765 } 766 + if (!progress) 767 + goto done; 760 768 761 769 if (!sops) { 762 770 /* No semops; something special is going on. */ 763 771 for (i = 0; i < sma->sem_nsems; i++) { 764 - if (update_queue(sma, i, pt)) 772 + if (update_queue(sma, i, pt)) { 765 773 otime = 1; 774 + progress = 1; 775 + } 766 776 } 767 - goto done; 777 + goto done_checkretry; 768 778 } 769 779 770 780 /* Check the semaphores that were modified. */ ··· 782 772 if (sops[i].sem_op > 0 || 783 773 (sops[i].sem_op < 0 && 784 774 sma->sem_base[sops[i].sem_num].semval == 0)) 785 - if (update_queue(sma, sops[i].sem_num, pt)) 775 + if (update_queue(sma, sops[i].sem_num, pt)) { 786 776 otime = 1; 777 + progress = 1; 778 + } 779 + } 780 + done_checkretry: 781 + if (progress) { 782 + progress = 0; 783 + goto retry_global; 787 784 } 788 785 done: 789 786 if (otime)