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

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

ipc/sem.c: update sem_otime for all operations



In commit 0a2b9d4c ("ipc/sem.c: move wake_up_process out of the
spinlock section"), the update of semaphore's sem_otime(last semop time)
was moved to one central position (do_smart_update).

But since do_smart_update() is only called for operations that modify
the array, this means that wait-for-zero semops do not update sem_otime
anymore.

The fix is simple:
Non-alter operations must update sem_otime.

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: default avatarManfred Spraul <manfred@colorfullife.com>
Reported-by: default avatarJia He <jiakernel@gmail.com>
Tested-by: default avatarJia He <jiakernel@gmail.com>
Cc: Davidlohr Bueso <davidlohr.bueso@hp.com>
Cc: Mike Galbraith <efault@gmx.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent fb31ba30
Loading
Loading
Loading
Loading
+29 −13
Original line number Diff line number Diff line
@@ -917,6 +917,24 @@ static int update_queue(struct sem_array *sma, int semnum, struct list_head *pt)
	return semop_completed;
}

/**
 * set_semotime(sma, sops) - set sem_otime
 * @sma: semaphore array
 * @sops: operations that modified the array, may be NULL
 *
 * sem_otime is replicated to avoid cache line trashing.
 * This function sets one instance to the current time.
 */
static void set_semotime(struct sem_array *sma, struct sembuf *sops)
{
	if (sops == NULL) {
		sma->sem_base[0].sem_otime = get_seconds();
	} else {
		sma->sem_base[sops[0].sem_num].sem_otime =
							get_seconds();
	}
}

/**
 * do_smart_update(sma, sops, nsops, otime, pt) - optimized update_queue
 * @sma: semaphore array
@@ -967,17 +985,10 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
			}
		}
	}
	if (otime) {
		if (sops == NULL) {
			sma->sem_base[0].sem_otime = get_seconds();
		} else {
			sma->sem_base[sops[0].sem_num].sem_otime =
								get_seconds();
		}
	}
	if (otime)
		set_semotime(sma, sops);
}


/* The following counts are associated to each semaphore:
 *   semncnt        number of tasks waiting on semval being nonzero
 *   semzcnt        number of tasks waiting on semval being zero
@@ -1839,12 +1850,17 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,

	error = perform_atomic_semop(sma, sops, nsops, un,
					task_tgid_vnr(current));
	if (error <= 0) {
		if (alter && error == 0)
	if (error == 0) {
		/* If the operation was successful, then do
		 * the required updates.
		 */
		if (alter)
			do_smart_update(sma, sops, nsops, 1, &tasks);

		goto out_unlock_free;
		else
			set_semotime(sma, sops);
	}
	if (error <= 0)
		goto out_unlock_free;

	/* We need to sleep on this operation, so we put the current
	 * task into the pending queue and go to sleep.