aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/sem.c
diff options
context:
space:
mode:
authorManfred Spraul <manfred@colorfullife.com>2013-09-30 16:45:25 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-10-18 10:45:48 -0400
commite556ea0191d648c63fbc4fe24bbfb15ad872a205 (patch)
treea5a45211eff01fde39bca0c148327cca54405e42 /ipc/sem.c
parent83aeb6e3449cc54fa8867a0c9cc1b8d2484fa91e (diff)
ipc/sem.c: update sem_otime for all operations
commit 0e8c665699e953fa58dc1b0b0d09e5dce7343cc7 upstream. In commit 0a2b9d4c7967 ("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'ipc/sem.c')
-rw-r--r--ipc/sem.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/ipc/sem.c b/ipc/sem.c
index cd6a733011a2..8c4f59b0204a 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -918,6 +918,24 @@ again:
918} 918}
919 919
920/** 920/**
921 * set_semotime(sma, sops) - set sem_otime
922 * @sma: semaphore array
923 * @sops: operations that modified the array, may be NULL
924 *
925 * sem_otime is replicated to avoid cache line trashing.
926 * This function sets one instance to the current time.
927 */
928static void set_semotime(struct sem_array *sma, struct sembuf *sops)
929{
930 if (sops == NULL) {
931 sma->sem_base[0].sem_otime = get_seconds();
932 } else {
933 sma->sem_base[sops[0].sem_num].sem_otime =
934 get_seconds();
935 }
936}
937
938/**
921 * do_smart_update(sma, sops, nsops, otime, pt) - optimized update_queue 939 * do_smart_update(sma, sops, nsops, otime, pt) - optimized update_queue
922 * @sma: semaphore array 940 * @sma: semaphore array
923 * @sops: operations that were performed 941 * @sops: operations that were performed
@@ -967,17 +985,10 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
967 } 985 }
968 } 986 }
969 } 987 }
970 if (otime) { 988 if (otime)
971 if (sops == NULL) { 989 set_semotime(sma, sops);
972 sma->sem_base[0].sem_otime = get_seconds();
973 } else {
974 sma->sem_base[sops[0].sem_num].sem_otime =
975 get_seconds();
976 }
977 }
978} 990}
979 991
980
981/* The following counts are associated to each semaphore: 992/* The following counts are associated to each semaphore:
982 * semncnt number of tasks waiting on semval being nonzero 993 * semncnt number of tasks waiting on semval being nonzero
983 * semzcnt number of tasks waiting on semval being zero 994 * semzcnt number of tasks waiting on semval being zero
@@ -1839,12 +1850,17 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1839 1850
1840 error = perform_atomic_semop(sma, sops, nsops, un, 1851 error = perform_atomic_semop(sma, sops, nsops, un,
1841 task_tgid_vnr(current)); 1852 task_tgid_vnr(current));
1842 if (error <= 0) { 1853 if (error == 0) {
1843 if (alter && error == 0) 1854 /* If the operation was successful, then do
1855 * the required updates.
1856 */
1857 if (alter)
1844 do_smart_update(sma, sops, nsops, 1, &tasks); 1858 do_smart_update(sma, sops, nsops, 1, &tasks);
1845 1859 else
1846 goto out_unlock_free; 1860 set_semotime(sma, sops);
1847 } 1861 }
1862 if (error <= 0)
1863 goto out_unlock_free;
1848 1864
1849 /* We need to sleep on this operation, so we put the current 1865 /* We need to sleep on this operation, so we put the current
1850 * task into the pending queue and go to sleep. 1866 * task into the pending queue and go to sleep.