[PATCH] ipc/sem: Update duplicate sop detection
From: Manfred Spraul
Date: Mon Sep 19 2016 - 00:25:20 EST
The duplicated sop detection can be improved:
- use uint64_t instead of unsigned long for the bit array
storage, otherwise we break 32-bit archs
- support large arrays, just interpret the bit array
as a hash array (i.e.: an operation that accesses semaphore
0 and 64 would trigger the dupsop code, but that is
far better than not trying at all for semnum >=64)
- support test-for-zero-and-increase, this case can use the
fast codepath.
Untested! S-O-B only for the code, needs testing.
Signed-off-by: Manfred Spraul <manfred@xxxxxxxxxxxxxxxx>
---
ipc/sem.c | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/ipc/sem.c b/ipc/sem.c
index d9c743a..eda9e46 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1784,7 +1784,8 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
int max, locknum;
bool undos = false, alter = false, dupsop = false;
struct sem_queue queue;
- unsigned long dup = 0, jiffies_left = 0;
+ unsigned long jiffies_left = 0;
+ uint64_t dup;
struct ipc_namespace *ns;
ns = current->nsproxy->ipc_ns;
@@ -1816,18 +1817,32 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
jiffies_left = timespec_to_jiffies(&_timeout);
}
max = 0;
+
+ dup = 0;
for (sop = sops; sop < sops + nsops; sop++) {
+ uint64_t mask;
+
if (sop->sem_num >= max)
max = sop->sem_num;
if (sop->sem_flg & SEM_UNDO)
undos = true;
- if (sop->sem_op != 0)
+
+ /* 64: BITS_PER_UNIT64 */
+ mask = 1<<((sop->sem_num)%64);
+
+ if (dup & mask) {
+ /*
+ * There was a previous alter access that appears
+ * to have accessed the same semaphore, thus
+ * use the dupsop logic.
+ * "appears", because the detection can only check
+ * % BITS_PER_UNIT64.
+ */
+ dupsop = 1;
+ }
+ if (sop->sem_op != 0) {
alter = true;
- if (sop->sem_num < SEMOPM_FAST && !dupsop) {
- if (dup & (1 << sop->sem_num))
- dupsop = 1;
- else
- dup |= 1 << sop->sem_num;
+ dup |= mask;
}
}
--
2.7.4
--------------414C701457DDE2FCCE4D4B30--