Linux kernel code syntax doubt


 
Thread Tools Search this Thread
Top Forums Programming Linux kernel code syntax doubt
# 1  
Old 06-27-2011
Linux kernel code syntax doubt

I have found some definitions as below, can anyone explain me what it means and why it is being used this way please.


Code:
asmlinkage void __sched schedule(void)

# 2  
Old 06-27-2011
asmlinkage tells the compiler to pass parameters will be get from stack(it is local) area therefore does not looked in registers.(its good optimization for more fast).
schedule is a void function which decides what will run.

regards
ygemici
# 3  
Old 06-27-2011
Hello, kumaran_5555:


THE SHORT VERSION

asmlinkage and __sched are just macro definitions which use gcc function attributes to supply further instructions to the compiler. asmlinkage is architecture specific. __sched is not. On a 32 bit x86 system, asmlinkage void __sched schedule(void) expands to CPP_ASMLINKAGE __attribute__((regparm(0))) void __attribute__((__section__(".sched.text"))) schedule(void).

CPP_ASMLINKAGE is either null (if __cplusplus is not defined) or it's "extern C" (if it is).



THE LONG VERSION

__sched is a macro which uses a gcc function attribute extension to tell the compiler in which section (of the binary) to place the generated code (instead of the usual text section).

include/linux/sched.h:
Code:
/* Attach to any functions which should be ignored in wchan output. */
#define __sched         __attribute__((__section__(".sched.text")))

What's the purpose of this? It's used to mark scheduler-related kernel functions. When walking the stack looking for a wchan (wait channel, i.e. the kernel function which caused a process to sleep/block), this makes it easy to skip the scheduler stuff. This is done using in_sched_functions(), which tests a function's address to see if it lies within the .sched.text section.

include/linux/sched.h:
Code:
/* Is this address in the __sched functions? */
extern int in_sched_functions(unsigned long addr);

kernel/sched.c:
Code:
int in_sched_functions(unsigned long addr)
{
        return in_lock_functions(addr) ||
                (addr >= (unsigned long)__sched_text_start
                && addr < (unsigned long)__sched_text_end);
}

In case you're interested, here's an implementation of get_wchan(). It's architecture specific code, so what follows is the 32bit x86 version. It returns 0 if the process is running or if it fails some basic sanity checks (pointer out of stack bounds, for example), and returns non-zero when it finds the first non-scheduler function.

arch/x86/kernel/process_32.c:
Code:
unsigned long get_wchan(struct task_struct *p)
{
	unsigned long bp, sp, ip;
	unsigned long stack_page;
	int count = 0;
	if (!p || p == current || p->state == TASK_RUNNING)
		return 0;
	stack_page = (unsigned long)task_stack_page(p);
	sp = p->thread.sp;
	if (!stack_page || sp < stack_page || sp > top_esp+stack_page)
		return 0;
	/* include/asm-i386/system.h:switch_to() pushes bp last. */
	bp = *(unsigned long *) sp;
	do {
		if (bp < stack_page || bp > top_ebp+stack_page)
			return 0;
		ip = *(unsigned long *) (bp+4);
		if (!in_sched_functions(ip))
			return ip;
		bp = *(unsigned long *) bp;
	} while (count++ < 16);
	return 0;
}



asmlinkage is an architecture specific macro which also uses a gcc function attribute extension, in this case to insure that the compiler passes all arguments on the stack, without using any registers. This is the 32 bit x86 definition (along with related macros and comments which should help shed light on its purpose).

arch/x86/include/asm/linkage.h:
Code:
#ifdef CONFIG_X86_32
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))

/*
 * Make sure the compiler doesn't do anything stupid with the
 * arguments on the stack - they are owned by the *caller*, not
 * the callee. This just fools gcc into not spilling into them,
 * and keeps it from doing tailcall recursion and/or using the
 * stack slots for temporaries, since they are live and "used"
 * all the way to the end of the function.
 *
 * NOTE! On x86-64, all the arguments are in registers, so this
 * only matters on a 32-bit kernel.
 */
#define asmlinkage_protect(n, ret, args...) \
	__asmlinkage_protect##n(ret, ##args)
#define __asmlinkage_protect_n(ret, args...) \
	__asm__ __volatile__ ("" : "=r" (ret) : "0" (ret), ##args)
#define __asmlinkage_protect0(ret) \
	__asmlinkage_protect_n(ret)
#define __asmlinkage_protect1(ret, arg1) \
	__asmlinkage_protect_n(ret, "g" (arg1))
#define __asmlinkage_protect2(ret, arg1, arg2) \
	__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2))
#define __asmlinkage_protect3(ret, arg1, arg2, arg3) \
	__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3))
#define __asmlinkage_protect4(ret, arg1, arg2, arg3, arg4) \
	__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \
			      "g" (arg4))
#define __asmlinkage_protect5(ret, arg1, arg2, arg3, arg4, arg5) \
	__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \
			      "g" (arg4), "g" (arg5))
#define __asmlinkage_protect6(ret, arg1, arg2, arg3, arg4, arg5, arg6) \
	__asmlinkage_protect_n(ret, "g" (arg1), "g" (arg2), "g" (arg3), \
			      "g" (arg4), "g" (arg5), "g" (arg6))

#endif /* CONFIG_X86_32 */


All linux code quoted above was taken from the lastest tree at git.kernel.org.

For more info on these gcc function attribute extensions, consult Function Attributes - Using the GNU Compiler Collection (GCC)


Regards,
Alister

---------- Post updated at 09:13 AM ---------- Previous update was at 08:55 AM ----------

Quote:
Originally Posted by ygemici
asmlinkage tells the compiler to pass parameters will be get from stack(it is local) area therefore does not looked in registers.(its good optimization for more fast).
I believe you are absolutely mistaken regarding this being a performance optimization. The cpu registers are the fastest, operating system-visible processor-storage locations available, faster than any level of cache and most definitely faster than main memory (RAM). Performance optimizations typically attempt to stuff as many things into registers as possible.

I'm not a big hardware person, but if I'm not mistaken, the x86 32bit architecture has comparitively few registers. asmlinkage is a workaround for this. Note that the stack is not used for this purpose on any other platform. Except for x86 32-bit which includes the gcc function attribute code in the definition of asmlinkage, by default asmlinkage is nothing more than "extern C".

Regards,
Alister

Last edited by alister; 06-27-2011 at 10:43 AM..
These 2 Users Gave Thanks to alister For This Post:
# 4  
Old 06-27-2011
Quote:
Originally Posted by alister
I believe you are absolutely mistaken regarding this being a performance optimization. The cpu registers are the fastest, operating system-visible processor-storage locations available, faster than any level of cache and most definitely faster than main memory (RAM). Performance optimizations typically attempt to stuff as many things into registers as possible.

I'm not a big hardware person, but if I'm not mistaken, the x86 32bit architecture has comparitively few registers. asmlinkage is a workaround for this. Note that the stack is not used for this purpose on any other platform. Except for x86 32-bit which includes the gcc function attribute code in the definition of asmlinkage, by default asmlinkage is nothing more than "extern C".

Regards,
Alister
Smilie
generally you are right.registers are faster therefore are part of the microprocessor.yes stack access is slower than register access.
Additional, CPU often access the stack and therefore stack(return addres of functions,parameters,registers,tmp infos,local variables..) datas usually is
saved in processor's cache.however cpu registers are very fast beceause of registers are very near and wired directly alu.So I meant just optimization not fast my fault.

i want to add some information about this issue.
asmlinkage tells to compiler that the arguments are on the stack(gcc takes it (i386 specific __attribute__((regparm(0))) and related in below asm code)
(actually,is a tag for assembly code convention for compiler (like asm/nasm/..))

# define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0))) provides like about below..
* userspace application executes
* (c) library routines puts arguments in registers from userspace.
( about register i want to tell something , since Linux 2.3.31 that is supported six system call parameters,but before
linux could handle 4(for some ver..5) system call parametres, if more than four arguments are needed, they are lef on the stack but i mentioned for new
version)
* enter kernel mode (executing trap --> int 0x80/sysenter) and executed kernel syscall handler(system_call() f)
* save current syscall number to eax.
* executed SAVE_ALL macro (%macro SAVE_ALL)
1) save address of kernel data(ds) and extra segment(to es)
2) all arguments(ebx,ecx,edx,esi,edi,ebp actually correct order will be reverse of this for C function call ) saves to stack
3) copy user_data_segment to ds register.
* %endmacro
* call (C) function (arguments are passed on the stack to c function (with asmlinkage))
* RESTORE_ALL(restores ebx, ecx, edx, esi, edi, ebp, eax, ds, es) and then go back to usermode (ret)

And asmlinkage format is like..
On i386
__attribute__((regparm(0)))
On ia64
__attribute__((syscall_linkage))

regards
ygemici
# 5  
Old 06-28-2011
Thanks for your wonderful explanation. Let me study further the things you have introduced to me, and post my doubts.

Thanks again Gurus.
Login or Register to Ask a Question

Previous Thread | Next Thread

4 More Discussions You Might Find Interesting

1. Programming

Linux Kernel code "current" macro

I was going through the Linux code, i stuck with few inline assembly language code, I have tried online but in vain. Any help is much appreciated. Thanks. /* how to get the thread information struct from C */ static inline struct thread_info *current_thread_info(void) { struct... (3 Replies)
Discussion started by: kumaran_5555
3 Replies

2. UNIX for Dummies Questions & Answers

Any tips/suggestions for a newbie beginning to read the Linux Kernel Source Code

Hi All, I recently downloaded the Linux kernel source code, added them all to a project in MS VC++ and plan to read through it so that I can improve the way I code, read/understand a large code database and hopefully contribute something to the development of the Linux OS. I have taken a... (3 Replies)
Discussion started by: clavian
3 Replies

3. Red Hat

Doubt on Linux console

Can anyone explain me the usage of momentary press, press and hold, Reset.. I usually use cold boot option which is used to boot the system. Any help on the other options is really helpful thanks in advance (5 Replies)
Discussion started by: rogerben
5 Replies

4. Shell Programming and Scripting

awk syntax doubt - trailing 1 value

In the below awk syntax, what does the value '1' signify? awk '{....}1' file some eg: awk '{gsub(/]/,"")}1' awk 'BEGIN{ORS=""}1' awk '{ORS=(!(NR%5)?"":"\n")}1' (4 Replies)
Discussion started by: royalibrahim
4 Replies
Login or Register to Ask a Question