Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf17bb71 authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds
Browse files

ipc/sem.c: sem optimise undo list search



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>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 7d6feeb2
Loading
Loading
Loading
Loading
+20 −6
Original line number Diff line number Diff line
@@ -962,17 +962,31 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
	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) {
		if (walk->semid == semid)
			return walk;
	list_for_each_entry_rcu(un, &ulp->list_proc, list_proc) {
		if (un->semid == semid)
			return un;
	}
	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
 * @ns: namespace
@@ -1308,7 +1322,7 @@ void exit_sem(struct task_struct *tsk)
		if (IS_ERR(sma))
			continue;

		un = lookup_undo(ulp, semid);
		un = __lookup_undo(ulp, semid);
		if (un == NULL) {
			/* exit_sem raced with IPC_RMID+semget() that created
			 * exactly the same semid. Nothing to do.