Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Linux syscall return type "long"?

I am reading Linux Kernel Development, 3rd ed., to learn about the kernel implementation and design. Chapter 5 is about syscalls. The author shows an example of a syscall declaration that is defined using the SYSCALL_DEFINE0 macro, which in that particular example expands to:

asmlinkage long sys_getpid(void)

He further says that:

[...] For compatibility between 32- and 64-bit systems, system calls defined to return an int in user-space return a long in the kernel.

He doesn't go any deeper than that, and I can't exactly understand why it is that way. Why is the use of long related to 32- and 64-bit systems? Why can't we return a plain int?

like image 391
Filipe Gonçalves Avatar asked Jan 05 '14 22:01

Filipe Gonçalves


1 Answers

Because on many 64 bits machines (e.g. x86-64) for the common GCC compiler sizeof(int)==4 but sizeof(void*)==8 && sizeof(long)==8; This is called the I32LP64 (or just LP64) data model

For instance, compile and run the following program on a Linux/x86-64 system:

#include<stdio.h>
#include<stdint.h>
int main ()
{
  printf ("sizeof(int)=%d\n", (int) sizeof (int));
  printf ("sizeof(intptr_t)=%d\n", (int) sizeof (intptr_t));
  printf ("sizeof(short)=%d\n", (int) sizeof (short));
  printf ("sizeof(long)=%d\n", (int) sizeof (long));
  printf ("sizeof(long long)=%d\n", (int) sizeof (long long));
  printf ("sizeof(void*)=%d\n", (int) sizeof (void *));
  return 0;
}

After compiling on my system with gcc -Wall s.c -o s and running ./s on my Debian/Sid/x86-64 (i3770k processor, GCC 4.8.2):

sizeof(int)=4
sizeof(intptr_t)=8
sizeof(short)=2
sizeof(long)=8
sizeof(long long)=8
sizeof(void*)=8

after compiling in 32 bits mode using gcc -m32 -Wall s.c -o s32 and running ./s32:

sizeof(int)=4
sizeof(intptr_t)=4
sizeof(short)=2
sizeof(long)=4
sizeof(long long)=8
sizeof(void*)=4

I'm getting the same output if compiling for x32 using gcc -mx32 -O3 -Wall s.c -o sx32!

BTW, perhaps the better question is why not use intptr_t .... I have no idea (probably, a matter of habits; when Linus first started to code his kernel, the C99 standard -defining <stdint.h> and intptr_t- did not exist yet).

Read more about ABIs, in particular read carefully the X86-64 ABI (see also x32 ABI...) and the wikipage on x86 calling conventions.

like image 191
Basile Starynkevitch Avatar answered Oct 17 '22 16:10

Basile Starynkevitch