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

Commit 9cad200c authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds
Browse files

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: default avatarNick Piggin <npiggin@suse.de>
Signed-off-by: default avatarManfred Spraul <manfred@colorfullife.com>
Cc: Pierre Peiffer <peifferp@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent bf17bb71
Loading
Loading
Loading
Loading
+31 −44
Original line number Diff line number Diff line
@@ -403,44 +403,32 @@ static int try_atomic_semop (struct sem_array * sma, struct sembuf * sops,
 */
static void update_queue (struct sem_array * sma)
{
	struct sem_queue *q, *tq;

again:
	list_for_each_entry_safe(q, tq, &sma->sem_pending, list) {
		int error;
	struct sem_queue * q;
		int alter;

	q = list_entry(sma->sem_pending.next, struct sem_queue, list);
	while (&q->list != &sma->sem_pending) {
		error = try_atomic_semop(sma, q->sops, q->nsops,
					 q->undo, q->pid);

		/* Does q->sleeper still need to sleep? */
		if (error <= 0) {
			struct sem_queue *n;
		if (error > 0)
			continue;

		list_del(&q->list);

		/*
			 * Continue scanning. The next operation
			 * that must be checked depends on the type of the
			 * completed operation:
			 * - if the operation modified the array, then
			 *   restart from the head of the queue and
			 *   check for threads that might be waiting
			 *   for semaphore values to become 0.
			 * - if the operation didn't modify the array,
			 *   then just continue.
			 * The order of list_del() and reading ->next
			 * is crucial: In the former case, the list_del()
			 * must be done first [because we might be the
			 * first entry in ->sem_pending], in the latter
			 * case the list_del() must be done last
			 * [because the list is invalid after the list_del()]
		 * The next operation that must be checked depends on the type
		 * of the completed operation:
		 * - if the operation modified the array, then restart from the
		 *   head of the queue and check for threads that might be
		 *   waiting for semaphore values to become 0.
		 * - if the operation didn't modify the array, then just
		 *   continue.
		 */
			if (q->alter) {
				list_del(&q->list);
				n = list_entry(sma->sem_pending.next,
						struct sem_queue, list);
			} else {
				n = list_entry(q->list.next, struct sem_queue,
						list);
				list_del(&q->list);
			}
		alter = q->alter;

		/* wake up the waiting thread */
		q->status = IN_WAKEUP;
@@ -451,10 +439,9 @@ static void update_queue (struct sem_array * sma)
		 */
		smp_wmb();
		q->status = error;
			q = n;
		} else {
			q = list_entry(q->list.next, struct sem_queue, list);
		}

		if (alter)
			goto again;
	}
}