Commit 9c0f1100 authored by Nick Piggin's avatar Nick Piggin Committed by james toy

Around a month ago, there was some discussion about an improvement of the

sysv sem algorithm: Most (at least: some important) users only use simple
semaphore operations, therefore it's worthwile to optimize this use case.


This patch:

Move last looked up sem_undo struct to the head of the task's undo list. 
Attempt to move common entries to the front of the list so search time is
reduced.  This reduces lookup_undo on oprofile of problematic SAP workload
by 30% (see patch 4 for a description of SAP workload).
Signed-off-by: default avatarNick Piggin <npiggin@suse.de>
Signed-off-by: default avatarManfred Spraul <manfred@colorfullife.com>
Cc: Pierre Peiffer <peifferp@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent ad3982c4
...@@ -962,17 +962,31 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp) ...@@ -962,17 +962,31 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
return 0; return 0;
} }
static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid) static struct sem_undo *__lookup_undo(struct sem_undo_list *ulp, int semid)
{ {
struct sem_undo *walk; struct sem_undo *un;
list_for_each_entry_rcu(walk, &ulp->list_proc, list_proc) { list_for_each_entry_rcu(un, &ulp->list_proc, list_proc) {
if (walk->semid == semid) if (un->semid == semid)
return walk; return un;
} }
return NULL; return NULL;
} }
static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
{
struct sem_undo *un;
assert_spin_locked(&ulp->lock);
un = __lookup_undo(ulp, semid);
if (un) {
list_del_rcu(&un->list_proc);
list_add_rcu(&un->list_proc, &ulp->list_proc);
}
return un;
}
/** /**
* find_alloc_undo - Lookup (and if not present create) undo array * find_alloc_undo - Lookup (and if not present create) undo array
* @ns: namespace * @ns: namespace
...@@ -1308,7 +1322,7 @@ void exit_sem(struct task_struct *tsk) ...@@ -1308,7 +1322,7 @@ void exit_sem(struct task_struct *tsk)
if (IS_ERR(sma)) if (IS_ERR(sma))
continue; continue;
un = lookup_undo(ulp, semid); un = __lookup_undo(ulp, semid);
if (un == NULL) { if (un == NULL) {
/* exit_sem raced with IPC_RMID+semget() that created /* exit_sem raced with IPC_RMID+semget() that created
* exactly the same semid. Nothing to do. * exactly the same semid. Nothing to do.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment