Skip to content

Commit

Permalink
ipc/sem.c: replace shared sem_otime with per-semaphore value
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Rik van Riel <[email protected]>
Cc: Davidlohr Bueso <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
manfred-colorfu authored and torvalds committed Jul 9, 2013
1 parent f269f40 commit d12e1e5
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 7 deletions.
1 change: 0 additions & 1 deletion include/linux/sem.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ struct task_struct;
struct sem_array {
struct kern_ipc_perm ____cacheline_aligned_in_smp
sem_perm; /* permissions .. see ipc.h */
time_t sem_otime; /* last semop time */
time_t sem_ctime; /* last change time */
struct sem *sem_base; /* ptr to first semaphore in array */
struct list_head pending_alter; /* pending operations */
Expand Down
37 changes: 31 additions & 6 deletions ipc/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ struct sem {
/* that alter the semaphore */
struct list_head pending_const; /* pending single-sop operations */
/* that do not alter the semaphore*/
time_t sem_otime; /* candidate for sem_otime */
} ____cacheline_aligned_in_smp;

/* One queue for each sleeping process in the system. */
Expand Down Expand Up @@ -911,8 +912,14 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
}
}
}
if (otime)
sma->sem_otime = get_seconds();
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();
}
}
}


Expand Down Expand Up @@ -1058,6 +1065,21 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in,
}
}

static time_t get_semotime(struct sem_array *sma)
{
int i;
time_t res;

res = sma->sem_base[0].sem_otime;
for (i = 1; i < sma->sem_nsems; i++) {
time_t to = sma->sem_base[i].sem_otime;

if (to > res)
res = to;
}
return res;
}

static int semctl_nolock(struct ipc_namespace *ns, int semid,
int cmd, int version, void __user *p)
{
Expand Down Expand Up @@ -1131,9 +1153,9 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
goto out_unlock;

kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
tbuf.sem_otime = sma->sem_otime;
tbuf.sem_ctime = sma->sem_ctime;
tbuf.sem_nsems = sma->sem_nsems;
tbuf.sem_otime = get_semotime(sma);
tbuf.sem_ctime = sma->sem_ctime;
tbuf.sem_nsems = sma->sem_nsems;
rcu_read_unlock();
if (copy_semid_to_user(p, &tbuf, version))
return -EFAULT;
Expand Down Expand Up @@ -2025,6 +2047,9 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
{
struct user_namespace *user_ns = seq_user_ns(s);
struct sem_array *sma = it;
time_t sem_otime;

sem_otime = get_semotime(sma);

return seq_printf(s,
"%10d %10d %4o %10u %5u %5u %5u %5u %10lu %10lu\n",
Expand All @@ -2036,7 +2061,7 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
from_kgid_munged(user_ns, sma->sem_perm.gid),
from_kuid_munged(user_ns, sma->sem_perm.cuid),
from_kgid_munged(user_ns, sma->sem_perm.cgid),
sma->sem_otime,
sem_otime,
sma->sem_ctime);
}
#endif

0 comments on commit d12e1e5

Please sign in to comment.