Timer related syscalls for LTP test
RFC 1/1 Timer related syscalls for LTP test
Hi,
I have found a problem with the timer related syscall tests.
The following syscall tests, uses the direct syscall interface to the kernel for testing the interface, instead of using the GLIBC interface.
testcases/kernel/syscalls
\_ timer_getoverrun/
\_ timer_gettime/
testcases/kernel/timers
\_ timer_create/
\_ timer_delete/
\_ timer_settime/
So they use :
syscall(__NR_timer_XXXX, args )
for directly using the kernel syscall interface than using the
timer_xxxxx(args)
provided by the GLIBC. This is completely fine.
But however there is a mismatch in the "timer_t" type defined by the Linux kernel and the GNU Libc.
Linux kernel defines it as an int for all architectures.
include/linux/types.h :
typedef __kernel_timer_t timer_t;
arch/powerpc/include/asm/posix_types.h :
typedef int __kernel_timer_t;
Now, the glibc provides a wrapper to the timer related system calls. While providing the wrapper, Glibc stores some internal data associated with the timer. So it defines the "timer_t" as a pointer (void*) as below:
/usr/include/time.h :
/* Timer ID returned by `timer_create'. */
typedef __timer_t timer_t;
in /usr/include/bits/types.h :
/* Timer ID returned by `timer_create'. */__STD_TYPE __TIMER_T_TYPE __timer_t;
in /usr/include/bits/typesizes.h
#define __TIMER_T_TYPE void *
So that leads to the definiton of timer_t as void* by glibc. And this cannot be changed. But the glibc uses the "proper" typed argument for the syscalls it issues by defining a kernel_timer_t.
On 32bit machines the difference is not noticed, since both the timer_t in userspace and the kernel space are of the same size. But on 64bit machines this is different.
Userspace has a width of 64bit and the kernel has 32bit width. Now, when we pass the pointer to timer_t to the kernel, things get complicated and on Big endian machines, ppc64, s390x, this leads to a problem. As the value kept is not available when we try to dereference it as a 32bit and this leads to undesired results like below:
timer_getoverrun01 1 TFAIL : Block 1: test 0 FAILED... errno = 22 :Invalid argument
strace shows :
13017 timer_create(CLOCK_REALTIME, {(nil), SIGALRM, SIGEV_SIGNAL, {...}},{0x26e80}) = 0
13017 fstat(1, {st_dev=makedev(0, 11), st_ino=3, st_mode=S_IFCHR|0620,
st_nlink=1, st_uid=0, st_gid=5, st_blksize=1024, st_blocks=0, st_rdev=makedev(136, 0), st_atime=2010/05/17-15:48:40,st_mtime=2010/05/17-15:48:40, st_ctime=2010/05/17-13:15:48}) = 0 13017 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)= 0x20000028000
13017 write(1, "timer_getoverrun01 0 TINFO "..., 66) = 66
13017 timer_getoverrun(0x26e80) = -1 EINVAL (Invalid argument)
So the conclusion is that, if we are using the System calls directly, we should use the argument which is compatible with the kernel. We simply *cannot* use the glibc definition and the kernel API directly.
I have a patch attached below that fixes this issue.
One more comment regarding the placement of timer_gettime and timer_getoverrun syscall tests. I strongly believe they could be moved to testcases/kernel/timers/ directory where the rest of the timer related syscall tests are placed. If that change is made, we can use the definition added in common_timers.h (in the patch) for those tests too, instead of defining in each of the tests.
Thanks
Suzuki
Fix timer_t argument for timer related direct syscalls.
The tests timer_getoverrun and timer_gettime should be moved to testcases/kernel/timers directory. If that is done, then we could use the definition in the common_timers.h, like the other tests.
/* Description */
There is a mismatch in the "timer_t" type defined by the Linux kernel and the GNU Libc.
Linux kernel defines it as an int for all architectures.
include/linux/types.h :
typedef __kernel_timer_t timer_t;
arch/powerpc/include/asm/posix_types.h :
typedef int __kernel_timer_t;
Now, the glibc provides a wrapper to the timer related system calls. While providing the wrapper, Glibc stores some internal data associated with the timer. So it defines the "timer_t" as a pointer (void*) as below:
/usr/include/time.h :
/* Timer ID returned by `timer_create'. */
typedef __timer_t timer_t;
in /usr/include/bits/types.h :
/* Timer ID returned by `timer_create'. */__STD_TYPE __TIMER_T_TYPE __timer_t;
in /usr/include/bits/typesizes.h
#define __TIMER_T_TYPE void *
So that leads to the definiton of timer_t as void* by glibc. And this cannot be changed. But the glibc uses the "proper" typed argument for the syscalls it issues by defining a kernel_timer_t.
On 32bit machines the difference is not noticed, since both the timer_t in userspace and the kernel space are of the same size. But on 64bit machines this is different.
Userspace has a width of 64bit and the kernel has 32bit width. Now, when we pass the pointer to timer_t to the kernel, things get complicated and on Big endian machines, ppc64, s390x, this leads to a problem. As the value kept is not available when we try to dereference it as a 32bit and this leads to undesired results
testcases/kernel/syscalls/timer_getoverrun/timer_getoverrun01.c +6 -1
@@ -49,6 +49,11 @@#include "usctest.h" #include "linux_syscall_numbers.h" +/* timer_t in kernel(int) is different from Glibc definition(void*). +* Use the kernel definition. +*/ +typedef int kernel_timer_t ; +/* Extern Global Variables */ extern int Tst_count;/* counter for tst_xxx routines. */ extern char *TESTDIR ;/* temporary dir created by tst_tmpdir() */
@@ -120,7 +125,7 @@int main (int ac,char **av) {int lc;/* loop counter */ char *msg;/* message returned from parse_opts */ -timer_t created_timer_id; +kernel_timer_t created_timer_id;struct sigevent ev;/* parse standard options */
testcases/kernel/syscalls/timer_gettime/timer_gettime01.c +6 -1
@@ -48,6 +48,11 @@#include "usctest.h" #include "linux_syscall_numbers.h" +/* timer_t in kernel(int) is different from Glibc definition(void*). +* Use the kernel definition. +*/ +typedef int kernel_timer_t ; +/* Extern Global Variables */ extern int Tst_count;/* counter for tst_xxx routines. */ extern char *TESTDIR ;/* temporary dir created by tst_tmpdir() */
@@ -122,7 +127,7 @@int lc;/* loop counter */ char *msg;/* message returned from parse_opts */ -timer_t created_timer_id; +kernel_timer_t created_timer_id;struct sigevent ev;struct itimerspec spec;
testcases/kernel/timers/timer_delete/timer_delete02.c +1 -1
@@ -84,7 +84,7 @@ {int lc;/* loop counter */ char *msg;/* message returned from parse_opts */ -timer_t timer_id; +kernel_timer_t timer_id;/* parse standard options */ if ((msg = parse_opts (ac, av, (option_t *) NULL, NULL)) !=
testcases/kernel/timers/timer_delete/timer_delete03.c +1 -1
@@ -73,7 +73,7 @@#include "usctest.h" #include "common_timers.h" -#define INVALID_ID ((timer_t)-1) +#define INVALID_ID ((kernel_timer_t)-1)static void setup ();
testcases/kernel/timers/timer_create/timer_create02.c +1 -1
@@ -86,7 +86,7 @@ {int lc, i, j;/* loop counter */ char *msg;/* message returned from parse_opts */ -timer_t created_timer_id;/* holds the returned timer_id */ +kernel_timer_t created_timer_id;/* holds the returned timer_id */ char *message[3 ] = {"SIGEV_SIGNAL" ,"NULL" ,
testcases/kernel/timers/timer_create/timer_create03.c +1 -1
@@ -100,7 +100,7 @@ {int lc, i;/* loop counter */ char *msg;/* message returned from parse_opts */ -timer_t created_timer_id;/* holds the returned timer_id */ +kernel_timer_t created_timer_id;/* holds the returned timer_id */ char *message[] = {"SIGEV_SIGNAL" ,"NULL" ,
testcases/kernel/timers/timer_create/timer_create04.c +3 -3
@@ -111,7 +111,7 @@ {int lc, i;/* loop counter */ char *msg;/* message returned from parse_opts */ -timer_t timer_id, *temp_id;/* stores the returned timer_id */ +kernel_timer_t timer_id, *temp_id;/* stores the returned timer_id */ struct sigevent *temp_ev;/* used for bad address test case */ clockid_t clocks[6 ] = {
@@ -158,7 +158,7 @@switch (i) {case 2 :/* make the timer_id bad address */ - temp_id = (timer_t *)-1 ; + temp_id = (kernel_timer_t *)-1 ;break ;case 3 :/* make the event bad address */
@@ -167,7 +167,7 @@case 4 :/* Produce an invalid timer_id address. */ if (tst_kvercmp (2 ,6 ,12 ) >=0 ) - temp_id = (timer_t *)-1 ; + temp_id = (kernel_timer_t *)-1 ;break ;case 5 :/* Produce an invalid event address. */
testcases/kernel/timers/timer_settime/timer_settime02.c +1 -1
@@ -81,7 +81,7 @@extern int Tst_count;/* Test Case counter for tst_* routines */ static struct itimerspec new_set, old_set, *old_temp; -static timer_t timer; +static kernel_timer_t timer;static int flag;int
testcases/kernel/timers/timer_settime/timer_settime03.c +2 -2
@@ -81,7 +81,7 @@extern int Tst_count;/* Test Case counter for tst_* routines */ static struct itimerspec new_set, old_set, *old_temp, *new_temp; -static timer_t timer, tim; +static kernel_timer_t timer, tim;static int exp_enos[] = {EINVAL ,EFAULT ,0 };
@@ -168,7 +168,7 @@break ;case 3 :/* make timer_id invalid */ - tim = (timer_t)-1 ; + tim = (kernel_timer_t)-1 ; new_set.it_value.tv_nsec =0 ;break ;case 4 :
testcases/kernel/timers/include/common_timers.h +5 -0
@@ -63,4 +63,9 @@#include <time.h> #include <unistd.h> +/* timer_t in kernel(int) is different from Glibc definition(void*). +* Use the kernel definition for syscall tests +*/ +typedef int kernel_timer_t ; +#endif
------------------------------------------------------------------------------
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list
Quoted 91 lines · Suzuki Poulose
Hi,
I have found a problem with the timer related syscall tests.
The following syscall tests, uses the direct syscall interface to the kernel for testing the interface, instead of using the GLIBC interface.
testcases/kernel/syscalls
\_ timer_getoverrun/
\_ timer_gettime/testcases/kernel/timers
\_ timer_create/
\_ timer_delete/
\_ timer_settime/So they use :
syscall(__NR_timer_XXXX, args )
for directly using the kernel syscall interface than using the
timer_xxxxx(args)provided by the GLIBC. This is completely fine.
But however there is a mismatch in the "
timer_t" type defined by the Linux kernel and the GNU Libc.Linux kernel defines it as an int for all architectures.
include/linux/types.h:typedef
__kernel_timer_ttimer_t;
arch/powerpc/include/asm/posix_types.h:
typedef int__kernel_timer_t;Now, the glibc provides a wrapper to the timer related system calls. While providing the wrapper, Glibc stores some internal data associated with the timer. So it defines the "
timer_t" as a pointer (void*) as below:
/usr/include/time.h:/* Timer ID returned by `timer_create'. */
typedef__timer_ttimer_t;in
/usr/include/bits/types.h:/* Timer ID returned by `timer_create'. */
__STD_TYPE__TIMER_T_TYPE__timer_t;in
/usr/include/bits/typesizes.h#define
__TIMER_T_TYPEvoid *So that leads to the definiton of
timer_tas void* by glibc. And this cannot be changed. But the glibc uses the "proper" typed argument for the syscalls it issues by defining akernel_timer_t.On 32bit machines the difference is not noticed, since both the
timer_tin userspace and the kernel space are of the same size. But on 64bit machines this is different.Userspace has a width of 64bit and the kernel has 32bit width. Now, when we pass the pointer to
timer_tto the kernel, things get complicated and on Big endian machines, ppc64, s390x, this leads to a problem. As the value kept is not available when we try to dereference it as a 32bit and this leads to undesired results like below:
timer_getoverrun011 TFAIL : Block 1: test 0 FAILED... errno = 22
:Invalid argumentstrace shows :
13017
timer_create(CLOCK_REALTIME, {(nil), SIGALRM, SIGEV_SIGNAL, {...}},{0x26e80})= 0
13017 fstat(1, {st_dev=makedev(0, 11), st_ino=3, st_mode=S_IFCHR|0620, st_nlink=1, st_uid=0, st_gid=5, st_blksize=1024, st_blocks=0, st_rdev=makedev(136, 0), st_atime=2010/05/17-15:48:40,st_mtime=2010/05/17-15:48:40, st_ctime=2010/05/17-13:15:48}) = 0
13017mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)=0x20000028000
13017write(1, "timer_getoverrun01 0 TINFO "..., 66)= 66
13017timer_getoverrun(0x26e80)= -1 EINVAL (Invalid argument)
Quoted 5 lines
So the conclusion is that, if we are using the System calls directly, we should use the argument which is compatible with the kernel. We simply *cannot* use the glibc definition and the kernel API directly.
I have a patch attached below that fixes this issue.
Thanks Suzie.
Quoted 7 lines
One more comment regarding the placement of
timer_gettimeandtimer_getoverrunsyscall tests. I strongly believe they could be moved to testcases/kernel/timers/ directory where the rest of the timer related syscall tests are placed. If that change is made, we can use the definition added incommon_timers.h(in the patch) for those tests too, instead of defining in each of the tests.
Sure, you can move them accordingly in the next patch :-)
Regards--
Subrata
Quoted 13 lines
Thanks
Suzuki
Quoted 6 lines
------------------------------------------------------------------------------
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list
------------------------------------------------------------------------------
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list