Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab465df9 authored by Manfred Spraul's avatar Manfred Spraul Committed by Linus Torvalds
Browse files

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: default avatarManfred Spraul <manfred@colorfullife.com>
Acked-by: default avatarDavidlohr Bueso <davidlohr.bueso@hp.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 89ff7783
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -752,19 +752,29 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
			int otime, struct list_head *pt)
{
	int i;
	int progress;

	if (sma->complex_count || sops == NULL) {
		if (update_queue(sma, -1, pt))
	progress = 1;
retry_global:
	if (sma->complex_count) {
		if (update_queue(sma, -1, pt)) {
			progress = 1;
			otime = 1;
			sops = NULL;
		}
	}
	if (!progress)
		goto done;

	if (!sops) {
		/* No semops; something special is going on. */
		for (i = 0; i < sma->sem_nsems; i++) {
			if (update_queue(sma, i, pt))
			if (update_queue(sma, i, pt)) {
				otime = 1;
				progress = 1;
			}
		goto done;
		}
		goto done_checkretry;
	}

	/* Check the semaphores that were modified. */
@@ -772,8 +782,15 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
		if (sops[i].sem_op > 0 ||
			(sops[i].sem_op < 0 &&
				sma->sem_base[sops[i].sem_num].semval == 0))
			if (update_queue(sma, sops[i].sem_num, pt))
			if (update_queue(sma, sops[i].sem_num, pt)) {
				otime = 1;
				progress = 1;
			}
	}
done_checkretry:
	if (progress) {
		progress = 0;
		goto retry_global;
	}
done:
	if (otime)