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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.