From: Suzuki Poulose <suzuki@in.ibm.com>
To: Linus Test Project <ltp-list@lists.sourceforge.net>
Cc: Josh Boyer <jwboyer@linux.vnet.ibm.com>, iranna.ankad@in.ibm.com
Subject: [LTP] [RFC] Timer related syscalls for LTP test
Date: Thu, 27 May 2010 16:40:02 +0530 [thread overview]
Message-ID: <4BFE530A.10709@in.ibm.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 3407 bytes --]
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
[-- Attachment #2: fix-timer_t-definition-for-syscall-tests.diff --]
[-- Type: text/plain, Size: 9270 bytes --]
Signed-off-by: Suzuki K P <suzuki@in.ibm.com>
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
Index: ltp/testcases/kernel/syscalls/timer_getoverrun/timer_getoverrun01.c
===================================================================
--- ltp.orig/testcases/kernel/syscalls/timer_getoverrun/timer_getoverrun01.c 2009-05-21 18:41:36.000000000 +0000
+++ ltp/testcases/kernel/syscalls/timer_getoverrun/timer_getoverrun01.c 2010-05-27 13:46:55.000000000 +0000
@@ -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 */
Index: ltp/testcases/kernel/syscalls/timer_gettime/timer_gettime01.c
===================================================================
--- ltp.orig/testcases/kernel/syscalls/timer_gettime/timer_gettime01.c 2009-05-21 18:43:48.000000000 +0000
+++ ltp/testcases/kernel/syscalls/timer_gettime/timer_gettime01.c 2010-05-27 13:47:25.000000000 +0000
@@ -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;
Index: ltp/testcases/kernel/timers/timer_delete/timer_delete02.c
===================================================================
--- ltp.orig/testcases/kernel/timers/timer_delete/timer_delete02.c 2009-12-06 20:53:44.000000000 +0000
+++ ltp/testcases/kernel/timers/timer_delete/timer_delete02.c 2010-05-27 14:01:21.000000000 +0000
@@ -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)) !=
Index: ltp/testcases/kernel/timers/timer_delete/timer_delete03.c
===================================================================
--- ltp.orig/testcases/kernel/timers/timer_delete/timer_delete03.c 2009-12-06 20:53:44.000000000 +0000
+++ ltp/testcases/kernel/timers/timer_delete/timer_delete03.c 2010-05-27 14:01:35.000000000 +0000
@@ -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();
Index: ltp/testcases/kernel/timers/timer_create/timer_create02.c
===================================================================
--- ltp.orig/testcases/kernel/timers/timer_create/timer_create02.c 2010-05-19 06:19:20.000000000 +0000
+++ ltp/testcases/kernel/timers/timer_create/timer_create02.c 2010-05-27 14:00:08.000000000 +0000
@@ -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",
Index: ltp/testcases/kernel/timers/timer_create/timer_create03.c
===================================================================
--- ltp.orig/testcases/kernel/timers/timer_create/timer_create03.c 2009-12-06 20:53:44.000000000 +0000
+++ ltp/testcases/kernel/timers/timer_create/timer_create03.c 2010-05-27 14:00:47.000000000 +0000
@@ -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",
Index: ltp/testcases/kernel/timers/timer_create/timer_create04.c
===================================================================
--- ltp.orig/testcases/kernel/timers/timer_create/timer_create04.c 2009-12-06 20:53:44.000000000 +0000
+++ ltp/testcases/kernel/timers/timer_create/timer_create04.c 2010-05-27 14:01:05.000000000 +0000
@@ -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. */
Index: ltp/testcases/kernel/timers/timer_settime/timer_settime02.c
===================================================================
--- ltp.orig/testcases/kernel/timers/timer_settime/timer_settime02.c 2009-12-06 20:53:44.000000000 +0000
+++ ltp/testcases/kernel/timers/timer_settime/timer_settime02.c 2010-05-27 14:01:53.000000000 +0000
@@ -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
Index: ltp/testcases/kernel/timers/timer_settime/timer_settime03.c
===================================================================
--- ltp.orig/testcases/kernel/timers/timer_settime/timer_settime03.c 2009-12-06 20:53:44.000000000 +0000
+++ ltp/testcases/kernel/timers/timer_settime/timer_settime03.c 2010-05-27 14:02:03.000000000 +0000
@@ -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:
Index: ltp/testcases/kernel/timers/include/common_timers.h
===================================================================
--- ltp.orig/testcases/kernel/timers/include/common_timers.h 2010-05-19 06:19:20.000000000 +0000
+++ ltp/testcases/kernel/timers/include/common_timers.h 2010-05-27 14:02:50.000000000 +0000
@@ -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
[-- Attachment #3: Type: text/plain, Size: 80 bytes --]
------------------------------------------------------------------------------
[-- Attachment #4: Type: text/plain, Size: 155 bytes --]
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list
next reply other threads:[~2010-05-27 11:19 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-27 11:10 Suzuki Poulose [this message]
2010-05-28 7:32 ` [LTP] [RFC] Timer related syscalls for LTP test Subrata Modak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4BFE530A.10709@in.ibm.com \
--to=suzuki@in.ibm.com \
--cc=iranna.ankad@in.ibm.com \
--cc=jwboyer@linux.vnet.ibm.com \
--cc=ltp-list@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox