ipc/sem.c: update sem_otime for all operations
In commit 0a2b9d4c79
("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: Manfred Spraul <manfred@colorfullife.com>
Reported-by: Jia He <jiakernel@gmail.com>
Tested-by: Jia He <jiakernel@gmail.com>
Cc: Davidlohr Bueso <davidlohr.bueso@hp.com>
Cc: Mike Galbraith <efault@gmx.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
fb31ba30fb
commit
0e8c665699
1 changed files with 29 additions and 13 deletions
42
ipc/sem.c
42
ipc/sem.c
|
@ -917,6 +917,24 @@ again:
|
|||
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.
|
||||
|
|
Loading…
Reference in a new issue