Commit f8afd1fd31f4e263ee407f20f65b7afb8bef23b9

Authored by Davidlohr Bueso
Committed by Greg Kroah-Hartman
1 parent 8bacb5ad41

ipc,shm: introduce lockless functions to obtain the ipc object

commit 8b8d52ac382b17a19906b930cd69e2edb0aca8ba upstream.

This is the third and final patchset that deals with reducing the amount
of contention we impose on the ipc lock (kern_ipc_perm.lock).  These
changes mostly deal with shared memory, previous work has already been
done for semaphores and message queues:

  http://lkml.org/lkml/2013/3/20/546 (sems)
  http://lkml.org/lkml/2013/5/15/584 (mqueues)

With these patches applied, a custom shm microbenchmark stressing shmctl
doing IPC_STAT with 4 threads a million times, reduces the execution
time by 50%.  A similar run, this time with IPC_SET, reduces the
execution time from 3 mins and 35 secs to 27 seconds.

Patches 1-8: replaces blindly taking the ipc lock for a smarter
combination of rcu and ipc_obtain_object, only acquiring the spinlock
when updating.

Patch 9: renames the ids rw_mutex to rwsem, which is what it already was.

Patch 10: is a trivial mqueue leftover cleanup

Patch 11: adds a brief lock scheme description, requested by Andrew.

This patch:

Add shm_obtain_object() and shm_obtain_object_check(), which will allow us
to get the ipc object without acquiring the lock.  Just as with other
forms of ipc, these functions are basically wrappers around
ipc_obtain_object*().

Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Manfred Spraul <manfred@colorfullife.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mike Galbraith <efault@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 20 additions and 0 deletions Side-by-side Diff

... ... @@ -124,6 +124,26 @@
124 124 IPC_SHM_IDS, sysvipc_shm_proc_show);
125 125 }
126 126  
  127 +static inline struct shmid_kernel *shm_obtain_object(struct ipc_namespace *ns, int id)
  128 +{
  129 + struct kern_ipc_perm *ipcp = ipc_obtain_object(&shm_ids(ns), id);
  130 +
  131 + if (IS_ERR(ipcp))
  132 + return ERR_CAST(ipcp);
  133 +
  134 + return container_of(ipcp, struct shmid_kernel, shm_perm);
  135 +}
  136 +
  137 +static inline struct shmid_kernel *shm_obtain_object_check(struct ipc_namespace *ns, int id)
  138 +{
  139 + struct kern_ipc_perm *ipcp = ipc_obtain_object_check(&shm_ids(ns), id);
  140 +
  141 + if (IS_ERR(ipcp))
  142 + return ERR_CAST(ipcp);
  143 +
  144 + return container_of(ipcp, struct shmid_kernel, shm_perm);
  145 +}
  146 +
127 147 /*
128 148 * shm_lock_(check_) routines are called in the paths where the rw_mutex
129 149 * is not necessarily held.