aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorManfred Spraul <manfred@colorfullife.com>2013-07-08 19:01:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-09 13:33:28 -0400
commitd12e1e50e47e0900dbbf52237b7e171f4f15ea1e (patch)
tree83b54585a883ee062353eb464d93944d08ab4a1c /ipc
parentf269f40ad5aeee229ed70044926f44318abe41ef (diff)
ipc/sem.c: replace shared sem_otime with per-semaphore value
sem_otime contains the time of the last semaphore operation that completed successfully. Every operation updates this value, thus access from multiple cpus can cause thrashing. Therefore the patch replaces the variable with a per-semaphore variable. The per-array sem_otime is only calculated when required. No performance improvement on a single-socket i3 - only important for larger systems. Signed-off-by: Manfred Spraul <manfred@colorfullife.com> Cc: Rik van Riel <riel@redhat.com> Cc: Davidlohr Bueso <davidlohr.bueso@hp.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/sem.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/ipc/sem.c b/ipc/sem.c
index 6291257ee049..51352e1bfff9 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -99,6 +99,7 @@ struct sem {
99 /* that alter the semaphore */ 99 /* that alter the semaphore */
100 struct list_head pending_const; /* pending single-sop operations */ 100 struct list_head pending_const; /* pending single-sop operations */
101 /* that do not alter the semaphore*/ 101 /* that do not alter the semaphore*/
102 time_t sem_otime; /* candidate for sem_otime */
102} ____cacheline_aligned_in_smp; 103} ____cacheline_aligned_in_smp;
103 104
104/* One queue for each sleeping process in the system. */ 105/* One queue for each sleeping process in the system. */
@@ -911,8 +912,14 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
911 } 912 }
912 } 913 }
913 } 914 }
914 if (otime) 915 if (otime) {
915 sma->sem_otime = get_seconds(); 916 if (sops == NULL) {
917 sma->sem_base[0].sem_otime = get_seconds();
918 } else {
919 sma->sem_base[sops[0].sem_num].sem_otime =
920 get_seconds();
921 }
922 }
916} 923}
917 924
918 925
@@ -1058,6 +1065,21 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in,
1058 } 1065 }
1059} 1066}
1060 1067
1068static time_t get_semotime(struct sem_array *sma)
1069{
1070 int i;
1071 time_t res;
1072
1073 res = sma->sem_base[0].sem_otime;
1074 for (i = 1; i < sma->sem_nsems; i++) {
1075 time_t to = sma->sem_base[i].sem_otime;
1076
1077 if (to > res)
1078 res = to;
1079 }
1080 return res;
1081}
1082
1061static int semctl_nolock(struct ipc_namespace *ns, int semid, 1083static int semctl_nolock(struct ipc_namespace *ns, int semid,
1062 int cmd, int version, void __user *p) 1084 int cmd, int version, void __user *p)
1063{ 1085{
@@ -1131,9 +1153,9 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
1131 goto out_unlock; 1153 goto out_unlock;
1132 1154
1133 kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm); 1155 kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
1134 tbuf.sem_otime = sma->sem_otime; 1156 tbuf.sem_otime = get_semotime(sma);
1135 tbuf.sem_ctime = sma->sem_ctime; 1157 tbuf.sem_ctime = sma->sem_ctime;
1136 tbuf.sem_nsems = sma->sem_nsems; 1158 tbuf.sem_nsems = sma->sem_nsems;
1137 rcu_read_unlock(); 1159 rcu_read_unlock();
1138 if (copy_semid_to_user(p, &tbuf, version)) 1160 if (copy_semid_to_user(p, &tbuf, version))
1139 return -EFAULT; 1161 return -EFAULT;
@@ -2025,6 +2047,9 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
2025{ 2047{
2026 struct user_namespace *user_ns = seq_user_ns(s); 2048 struct user_namespace *user_ns = seq_user_ns(s);
2027 struct sem_array *sma = it; 2049 struct sem_array *sma = it;
2050 time_t sem_otime;
2051
2052 sem_otime = get_semotime(sma);
2028 2053
2029 return seq_printf(s, 2054 return seq_printf(s,
2030 "%10d %10d %4o %10u %5u %5u %5u %5u %10lu %10lu\n", 2055 "%10d %10d %4o %10u %5u %5u %5u %5u %10lu %10lu\n",
@@ -2036,7 +2061,7 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
2036 from_kgid_munged(user_ns, sma->sem_perm.gid), 2061 from_kgid_munged(user_ns, sma->sem_perm.gid),
2037 from_kuid_munged(user_ns, sma->sem_perm.cuid), 2062 from_kuid_munged(user_ns, sma->sem_perm.cuid),
2038 from_kgid_munged(user_ns, sma->sem_perm.cgid), 2063 from_kgid_munged(user_ns, sma->sem_perm.cgid),
2039 sma->sem_otime, 2064 sem_otime,
2040 sma->sem_ctime); 2065 sma->sem_ctime);
2041} 2066}
2042#endif 2067#endif