Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Manfred Spraul and committed by
Linus Torvalds
d12e1e50 f269f40a

+31 -7
-1
include/linux/sem.h
··· 12 12 struct sem_array { 13 13 struct kern_ipc_perm ____cacheline_aligned_in_smp 14 14 sem_perm; /* permissions .. see ipc.h */ 15 - time_t sem_otime; /* last semop time */ 16 15 time_t sem_ctime; /* last change time */ 17 16 struct sem *sem_base; /* ptr to first semaphore in array */ 18 17 struct list_head pending_alter; /* pending operations */
+31 -6
ipc/sem.c
··· 99 99 /* that alter the semaphore */ 100 100 struct list_head pending_const; /* pending single-sop operations */ 101 101 /* that do not alter the semaphore*/ 102 + time_t sem_otime; /* candidate for sem_otime */ 102 103 } ____cacheline_aligned_in_smp; 103 104 104 105 /* One queue for each sleeping process in the system. */ ··· 912 911 } 913 912 } 914 913 } 915 - if (otime) 916 - sma->sem_otime = get_seconds(); 914 + if (otime) { 915 + if (sops == NULL) { 916 + sma->sem_base[0].sem_otime = get_seconds(); 917 + } else { 918 + sma->sem_base[sops[0].sem_num].sem_otime = 919 + get_seconds(); 920 + } 921 + } 917 922 } 918 923 919 924 ··· 1065 1058 } 1066 1059 } 1067 1060 1061 + static time_t get_semotime(struct sem_array *sma) 1062 + { 1063 + int i; 1064 + time_t res; 1065 + 1066 + res = sma->sem_base[0].sem_otime; 1067 + for (i = 1; i < sma->sem_nsems; i++) { 1068 + time_t to = sma->sem_base[i].sem_otime; 1069 + 1070 + if (to > res) 1071 + res = to; 1072 + } 1073 + return res; 1074 + } 1075 + 1068 1076 static int semctl_nolock(struct ipc_namespace *ns, int semid, 1069 1077 int cmd, int version, void __user *p) 1070 1078 { ··· 1153 1131 goto out_unlock; 1154 1132 1155 1133 kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm); 1156 - tbuf.sem_otime = sma->sem_otime; 1157 - tbuf.sem_ctime = sma->sem_ctime; 1158 - tbuf.sem_nsems = sma->sem_nsems; 1134 + tbuf.sem_otime = get_semotime(sma); 1135 + tbuf.sem_ctime = sma->sem_ctime; 1136 + tbuf.sem_nsems = sma->sem_nsems; 1159 1137 rcu_read_unlock(); 1160 1138 if (copy_semid_to_user(p, &tbuf, version)) 1161 1139 return -EFAULT; ··· 2047 2025 { 2048 2026 struct user_namespace *user_ns = seq_user_ns(s); 2049 2027 struct sem_array *sma = it; 2028 + time_t sem_otime; 2029 + 2030 + sem_otime = get_semotime(sma); 2050 2031 2051 2032 return seq_printf(s, 2052 2033 "%10d %10d %4o %10u %5u %5u %5u %5u %10lu %10lu\n", ··· 2061 2036 from_kgid_munged(user_ns, sma->sem_perm.gid), 2062 2037 from_kuid_munged(user_ns, sma->sem_perm.cuid), 2063 2038 from_kgid_munged(user_ns, sma->sem_perm.cgid), 2064 - sma->sem_otime, 2039 + sem_otime, 2065 2040 sma->sem_ctime); 2066 2041 } 2067 2042 #endif