From: Manfred Spraul <manfred@colorfullife.com>
To: Davidlohr Bueso <davidlohr.bueso@hp.com>,
Michael Kerrisk <mtk.manpages@gmail.com>
Cc: LKML <linux-kernel@vger.kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
1vier1@web.de, Manfred Spraul <manfred@colorfullife.com>
Subject: [PATCH 3/6] ipc/sem.c: remove code duplication
Date: Sat, 10 May 2014 12:03:16 +0200 [thread overview]
Message-ID: <1399716199-26776-4-git-send-email-manfred@colorfullife.com> (raw)
In-Reply-To: <1399716199-26776-3-git-send-email-manfred@colorfullife.com>
count_semzcnt and count_semncnt are more of less identical.
The patch creates a single function that either counts the number of tasks
waiting for zero or waiting due to a decrease operation.
Signed-off-by: Manfred Spraul <manfred@colorfullife.com>
---
ipc/sem.c | 103 ++++++++++++++++++++++++++++++--------------------------------
1 file changed, 50 insertions(+), 53 deletions(-)
diff --git a/ipc/sem.c b/ipc/sem.c
index dc648f8..821aba7 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -47,8 +47,7 @@
* Thus: Perfect SMP scaling between independent semaphore arrays.
* If multiple semaphores in one array are used, then cache line
* trashing on the semaphore array spinlock will limit the scaling.
- * - semncnt and semzcnt are calculated on demand in count_semncnt() and
- * count_semzcnt()
+ * - semncnt and semzcnt are calculated on demand in count_semcnt()
* - the task that performs a successful semop() scans the list of all
* sleeping tasks and completes any pending operations that can be fulfilled.
* Semaphores are actively given to waiting tasks (necessary for FIFO).
@@ -989,6 +988,31 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
set_semotime(sma, sops);
}
+/*
+ * check_qop: Test how often a queued operation sleeps on the semaphore semnum
+ */
+static int check_qop(struct sem_array *sma, int semnum, struct sem_queue *q,
+ bool count_zero)
+{
+ struct sembuf *sops = q->sops;
+ int nsops = q->nsops;
+ int i, semcnt;
+
+ semcnt = 0;
+
+ for (i = 0; i < nsops; i++) {
+ if (sops[i].sem_num != semnum)
+ continue;
+ if (sops[i].sem_flg & IPC_NOWAIT)
+ continue;
+ if (count_zero && sops[i].sem_op == 0)
+ semcnt++;
+ if (!count_zero && sops[i].sem_op < 0)
+ semcnt++;
+ }
+ return semcnt;
+}
+
/* The following counts are associated to each semaphore:
* semncnt number of tasks waiting on semval being nonzero
* semzcnt number of tasks waiting on semval being zero
@@ -998,66 +1022,39 @@ static void do_smart_update(struct sem_array *sma, struct sembuf *sops, int nsop
* The counts we return here are a rough approximation, but still
* warrant that semncnt+semzcnt>0 if the task is on the pending queue.
*/
-static int count_semncnt(struct sem_array *sma, ushort semnum)
+static int count_semcnt(struct sem_array *sma, ushort semnum,
+ bool count_zero)
{
- int semncnt;
+ struct list_head *l;
struct sem_queue *q;
+ int semcnt;
- semncnt = 0;
- list_for_each_entry(q, &sma->sem_base[semnum].pending_alter, list) {
- struct sembuf *sops = q->sops;
- BUG_ON(sops->sem_num != semnum);
- if ((sops->sem_op < 0) && !(sops->sem_flg & IPC_NOWAIT))
- semncnt++;
- }
+ semcnt = 0;
+ /* First: check the simple operations. They are easy to evaluate */
+ if (count_zero)
+ l = &sma->sem_base[semnum].pending_const;
+ else
+ l = &sma->sem_base[semnum].pending_alter;
- list_for_each_entry(q, &sma->pending_alter, list) {
+ list_for_each_entry(q, l, list) {
struct sembuf *sops = q->sops;
- int nsops = q->nsops;
- int i;
- for (i = 0; i < nsops; i++)
- if (sops[i].sem_num == semnum
- && (sops[i].sem_op < 0)
- && !(sops[i].sem_flg & IPC_NOWAIT))
- semncnt++;
- }
- return semncnt;
-}
-static int count_semzcnt(struct sem_array *sma, ushort semnum)
-{
- int semzcnt;
- struct sem_queue *q;
-
- semzcnt = 0;
- list_for_each_entry(q, &sma->sem_base[semnum].pending_const, list) {
- struct sembuf *sops = q->sops;
BUG_ON(sops->sem_num != semnum);
- if ((sops->sem_op == 0) && !(sops->sem_flg & IPC_NOWAIT))
- semzcnt++;
+ BUG_ON(sops->sem_flg & IPC_NOWAIT);
+ BUG_ON(sops->sem_op > 0);
+ semcnt++;
}
- list_for_each_entry(q, &sma->pending_const, list) {
- struct sembuf *sops = q->sops;
- int nsops = q->nsops;
- int i;
- for (i = 0; i < nsops; i++)
- if (sops[i].sem_num == semnum
- && (sops[i].sem_op == 0)
- && !(sops[i].sem_flg & IPC_NOWAIT))
- semzcnt++;
- }
+ /* Then: check the complex operations. */
list_for_each_entry(q, &sma->pending_alter, list) {
- struct sembuf *sops = q->sops;
- int nsops = q->nsops;
- int i;
- for (i = 0; i < nsops; i++)
- if (sops[i].sem_num == semnum
- && (sops[i].sem_op == 0)
- && !(sops[i].sem_flg & IPC_NOWAIT))
- semzcnt++;
+ semcnt += check_qop(sma, semnum, q, count_zero);
+ }
+ if (count_zero) {
+ list_for_each_entry(q, &sma->pending_const, list) {
+ semcnt += check_qop(sma, semnum, q, count_zero);
+ }
}
- return semzcnt;
+ return semcnt;
}
/* Free a semaphore set. freeary() is called with sem_ids.rwsem locked
@@ -1459,10 +1456,10 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
err = curr->sempid;
goto out_unlock;
case GETNCNT:
- err = count_semncnt(sma, semnum);
+ err = count_semcnt(sma, semnum, 0);
goto out_unlock;
case GETZCNT:
- err = count_semzcnt(sma, semnum);
+ err = count_semcnt(sma, semnum, 1);
goto out_unlock;
}
--
1.9.0
next prev parent reply other threads:[~2014-05-10 10:04 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-10 10:03 [PATCH 0/6] ipc/sem.c: Fix semctl(,,{GETNCNT,GETZCNT}) Manfred Spraul
2014-05-10 10:03 ` [PATCH 1/6] ipc/sem.c: further whitespace cleanups Manfred Spraul
2014-05-10 10:03 ` [PATCH 2/6] ipc/sem.c: Bugfix for semctl(,,GETZCNT) Manfred Spraul
2014-05-10 10:03 ` Manfred Spraul [this message]
2014-05-10 10:03 ` [PATCH 4/6] ipc/sem.c: Change perform_atomic_semop parameters Manfred Spraul
2014-05-10 10:03 ` [PATCH 5/6] ipc/sem.c: Store which operation blocks in perform_atomic_semop() Manfred Spraul
2014-05-10 10:03 ` [PATCH 6/6] ipc/sem.c: make semctl(,,{GETNCNT,GETZCNT}) standard compliant Manfred Spraul
2014-05-14 14:52 ` Davidlohr Bueso
2014-05-14 22:30 ` Andrew Morton
2014-05-15 4:24 ` Manfred Spraul
2014-05-13 0:04 ` [PATCH 4/6] ipc/sem.c: Change perform_atomic_semop parameters Davidlohr Bueso
2014-05-12 18:19 ` [PATCH 3/6] ipc/sem.c: remove code duplication Davidlohr Bueso
2014-05-12 18:11 ` [PATCH 2/6] ipc/sem.c: Bugfix for semctl(,,GETZCNT) Davidlohr Bueso
2014-05-13 17:43 ` Manfred Spraul
2014-05-11 23:34 ` [PATCH 1/6] ipc/sem.c: further whitespace cleanups Davidlohr Bueso
2014-05-12 17:50 ` Manfred Spraul
2014-05-12 2:56 ` [PATCH 0/6] ipc/sem.c: Fix semctl(,,{GETNCNT,GETZCNT}) Davidlohr Bueso
2014-05-12 8:02 ` Michael Kerrisk (man-pages)
2014-05-12 17:43 ` Manfred Spraul
2014-05-18 7:58 Manfred Spraul
2014-05-18 7:58 ` [PATCH 1/6] ipc/sem.c: further whitespace cleanups Manfred Spraul
2014-05-18 7:58 ` [PATCH 2/6] ipc/sem.c: Bugfix for semctl(,,GETZCNT) Manfred Spraul
2014-05-18 7:58 ` [PATCH 3/6] ipc/sem.c: remove code duplication Manfred Spraul
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1399716199-26776-4-git-send-email-manfred@colorfullife.com \
--to=manfred@colorfullife.com \
--cc=1vier1@web.de \
--cc=akpm@linux-foundation.org \
--cc=davidlohr.bueso@hp.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mtk.manpages@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).