Page 1 of 1

linux kernel: why up() and down() are no longer inlined ?

Posted: Tue Oct 25, 2016 12:52 am
by miaowei
Hi, friends. I am reading the source code of linux 2.4.
In the semaphore partion, its up() and down() operations are implemented as inline functon.

Code: Select all

static inline void down(struct semaphore * sem)
{
	__asm__ __volatile__(
		"# atomic down operation\n\t"
		LOCK "decl %0\n\t"     /* --sem->count */
		"js 2f\n"
		"1:\n"
		".section .text.lock,\"ax\"\n"
		"2:\tcall __down_failed\n\t"
		"jmp 1b\n"
		".previous"
		:"=m" (sem->count)
		:"c" (sem)
		:"memory");
}

static inline void up(struct semaphore * sem)
{
	__asm__ __volatile__(
		"# atomic up operation\n\t"
		LOCK "incl %0\n\t"     /* ++sem->count */
		"jle 2f\n"
		"1:\n"
		".section .text.lock,\"ax\"\n"
		"2:\tcall __up_wakeup\n\t"
		"jmp 1b\n"
		".previous"
		:"=m" (sem->count)
		:"c" (sem)
		:"memory");
}
But in linux 2.6.32, it's no longer inlined.

Code: Select all

void down(struct semaphore *sem)
{
	unsigned long flags;

	spin_lock_irqsave(&sem->lock, flags);
	if (likely(sem->count > 0))
		sem->count--;
	else
		__down(sem);
	spin_unlock_irqrestore(&sem->lock, flags);
}

void up(struct semaphore *sem)
{
	unsigned long flags;

	spin_lock_irqsave(&sem->lock, flags);
	if (likely(list_empty(&sem->wait_list)))
		sem->count++;
	else
		__up(sem);
	spin_unlock_irqrestore(&sem->lock, flags);
}
The code itself is much more graceful, but it's not as fast as linux-2.4 any more.
The inline version works really fast when the code 'fall through', namely, when the down() gets a ticket immediately or up() gives back the tick while no waiters.
The cpu only needs execute a 'lock dec' or 'lock inc' instruction in that case, and that case is more commonly. After all, the race condition doesn't occur very often.

I want to know, what's the reason that made kernel developers can tolerate the overhead of the latter?

Re: linux kernel: why up() and down() are no longer inlined

Posted: Tue Oct 25, 2016 5:27 am
by Kevin
Have a look at this article: https://lwn.net/Articles/273731/

Essentially the reason stated in the commit message for 64ac24e73 is "no longer performance-critical", so the maintainability of a single C function trumps the performance of an assembly function per arch.

Re: linux kernel: why up() and down() are no longer inlined

Posted: Tue Oct 25, 2016 7:17 am
by miaowei
Kevin wrote:Have a look at this article: https://lwn.net/Articles/273731/

Essentially the reason stated in the commit message for 64ac24e73 is "no longer performance-critical", so the maintainability of a single C function trumps the performance of an assembly function per arch.
Really Great !
And may i ask you something more ... How did you find this article ? I want to find it by myself the next time i meet a similar question.

Re: linux kernel: why up() and down() are no longer inlined

Posted: Tue Oct 25, 2016 1:01 pm
by Roman
I think, I'd try digging the git commit history.

Re: linux kernel: why up() and down() are no longer inlined

Posted: Wed Oct 26, 2016 1:40 am
by Kevin
miaowei wrote:Really Great !
And may i ask you something more ... How did you find this article ? I want to find it by myself the next time i meet a similar question.
First git grep to find the function you mentioned, then git blame to find out which commit introduced it, and then I just googled for the subject line of that commit (because originally I just wanted to link the commit in some gitweb thing, but then the search turned up the LWN article, which I liked even better).

Re: linux kernel: why up() and down() are no longer inlined

Posted: Wed Oct 26, 2016 7:02 am
by miaowei
Thanks !
@Roman @Kevin

Re: linux kernel: why up() and down() are no longer inlined

Posted: Wed Nov 02, 2016 11:43 am
by Ycep
Are they ******** crazy?
If it's no longer performance critical then you need to slow it down?
I hope they returned it back after some time.

Re: linux kernel: why up() and down() are no longer inlined

Posted: Wed Nov 02, 2016 11:47 am
by Roman
Functions are often inlined because they reside in hot code paths. As stated, these functions no longer belong to this case.

Re: linux kernel: why up() and down() are no longer inlined

Posted: Wed Nov 02, 2016 12:04 pm
by glauxosdever
Hi,

Lukand wrote:Are they ******** crazy?
If it's no longer performance critical then you need to slow it down?
I hope they returned it back after some time.
I have to mention that inlining functions makes the total code size bigger.

Besides, would you please stop cursing for no reason?


Regards,
glauxosdever

Re: linux kernel: why up() and down() are no longer inlined

Posted: Wed Nov 02, 2016 12:44 pm
by iansjack
glauxosdever wrote:Besides, would you please stop cursing for no reason?
It is certainly worrying that this site allows 11-year olds to post such language. It is inappropriate, on a serious web site, from people of any age let alone young children.

Re: linux kernel: why up() and down() are no longer inlined

Posted: Wed Nov 02, 2016 2:30 pm
by Sik
Um, ignoring the whole manners incident for a moment...
Lukand wrote:If it's no longer performance critical then you need to slow it down?
Maintenance became a bigger issue (especially future maintenance). It was reworked with that new goal in mind. Also the new version is not written in assembly, which makes me think portability was a big factor too.

Re: linux kernel: why up() and down() are no longer inlined

Posted: Thu Nov 03, 2016 2:12 am
by Kevin
Lukand wrote:Are they ******** crazy?
If it's no longer performance critical then you need to slow it down?
I hope they returned it back after some time.
Thanks for writing this, despite the language you used. It gives everyone the clear message that it's best to stay far away from your code as long as you can't even possibly see a point in this decision (the motivation for which was explained both in the LWN article and earlier in this thread), and so it might save some people from using bad code.