Messages in this thread | | | Date | Tue, 23 Feb 1999 01:56:53 +0200 | From | Ville Herva <> | Subject | Re: linux-kernel-digest V1 #3387 |
| |
On Thu, Feb 18, 1999 at 04:00:04PM -0500, you wrote: > From: hans@grumbeer.inka.de (Hans-Joachim Baader) > Date: Thu, 18 Feb 99 07:41 MET > Subject: Re: 2.0.34: clock() returns -1 after 248.5 days uptime > > Your program is incorrect. clock() returns clock_t, not int. clock_t
I'm sorry, I just quickly wrote that to test what clock() returns since it seemed return something bizarre. Then I just went on pasting that in thhe linux-kernel posting without properly checking the types.
> is long in glibc 2.1, so on a 32 bit architecture this would help > nothing...
That I did check before posting.
> Certainly a result of -1 is less than useful. But perhaps it conforms > to some standard ;-|
I did crawl through some source, but I did not check the standards on this issue.
From what I can conclude from the sources, it's just one typical unsigned->signed issue ending disgracefully into a "if (value < 0) return -1;" check.
The glibc-2.0.7 (and glibc-2.0.108-0.981221 - the version numbers are from RedHat packages, but I doubt the function below varies all that much across versions) seems to define clock() in sysdeps/unix/sysv/linux/clock.c as follows:
#include <sys/times.h> #include <time.h> #include <unistd.h>
/* Return the time used by the program so far (user time + system time). */ clock_t clock (void) { struct tms buf; long clk_tck = __sysconf (_SC_CLK_TCK); if (__times (&buf) < 0) return (clock_t) -1;
return (clk_tck <= CLOCKS_PER_SEC) ? ((unsigned long) buf.tms_utime + buf.tms_stime) * (CLOCKS_PER_SEC / clk_tck) : ((unsigned long) buf.tms_utime + buf.tms_stime) / (clk_tck / CLOCKS_PER_SEC); }
A closer inspection revealed that Linux seems return a signed long as the return value of sys_times:
linux-2.0.3[46]/kernel/sys.c: asmlinkage long sys_times(struct tms * tbuf) { if (tbuf) { int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf); if (error) return error; put_user(current->utime,&tbuf->tms_utime); put_user(current->stime,&tbuf->tms_stime); put_user(current->cutime,&tbuf->tms_cutime); put_user(current->cstime,&tbuf->tms_cstime); } return jiffies; }
linux-2.2.1/kernel/sys.c: asmlinkage long sys_times(struct tms * tbuf) { /* * In the SMP world we might just be unlucky and have one of * the times increment as we use it. Since the value is an * atomically safe type this is just fine. Conceptually its * as if the syscall took an instant longer to occur. */ if (tbuf) if (copy_to_user(tbuf, ¤t->times, sizeof(struct tms))) return -EFAULT; return jiffies; }
However, jiffies is a unsigned variable:
linux-2.2.1/kernel/sched.c: unsigned long volatile jiffies=0; linux-2.0.3[46]/kernel/sched.c: unsigned long volatile jiffies=0;
Now, glibc seems to treat this value as signed:
glibc-2.0.6: posix/sys/times.h:extern clock_t __times __P ((struct tms *__buffer));
glibc-2.0.108-0.981221: include/sys/times.h:extern clock_t __times __P ((struct tms *__buffer));
which makes clock() to return -1 after 248.5 days due to the (__times() < 0) return -1; -line.
(Hopefully I did not miss anything crucial in that...)
Although the real problem lies in the fact that 32 bit is not enough for these counters, it would make more sense to me to return something else that a consistent -1.
Hopefully, this problem will go away as our server reaches 500 day uptime... But only for another 248 days.
> Since clock() is a libc function you should ask the > libc maintainers about it.
I did that. Waiting for results...
There are propably other points of code in glibc that get broken after 248.5 days, since zsh's terminal handling begun working improperly after 248.5 days of uptime.
-- v --
v@iki.fi
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |