Mail Archives: djgpp-workers/1999/10/26/09:53:19
> I tend to include this change in the current CVS sources, but I'd like
> to give it some more testing. If you can download the latest
> djtst203.zip (from the alphas directory on one of the usual DJGPP
> sites), run the test programs in the tests/libc/posix/signal and see
> if they still behave the same (or better) with the new version, that
> would be swell. If not, I'll do it when I have time.
I don't know when I will have the possibility to download djtst203.zip. For
now, I tried to run only the test from djtst202.zip, and it runs fine.
>> Maybe setitimer() should be changed to use the more precise version also,
>> so that getitimer() and setitimer() will have identical behavior?
> Yes. Please change setitimer also, to use the same conversion.
Here is the corrected diff to itimer.c. This conversion can cause overflow
with tv_usec > LONG_MAX*1000000/UCLOCKS_PER_SEC, but such large values are
out of range anyway.
I also noticed that the conversion of the tv_sec part in setitimer() was
also wrong: the value was calculated as 32-bit, limiting the maximum delay
to about an hour. Adding cast to uclock_t fixes this.
--- Sergey Vlasov <vsu AT au DOT ru>
=========================== itimer.diff ===========================
*** itimer0.c Fri Oct 22 15:51:28 1999
--- itimer.c Tue Oct 26 16:25:30 1999
***************
*** 34,39 ****
--- 34,56 ----
static uclock_t u_now;
+ /* Multiply a signed 32-bit integer (val) by a signed 32-bit integer (m)
+ and divide the 64-bit intermediate result by a signed 32-bit integer (d).
+ Returns 32-bit signed integer result of the division.
+
+ In other words, calculate (long)(((long long)val * m)/d), but
+ in a more efficient way, using 32*32->64 multiplication and
+ 64/32->32 division commands of Intel processors. */
+ static inline long muldiv(long val, long m, long d)
+ {
+ long rv;
+ asm( "imull %2\n\t"
+ "idivl %3"
+ : "=a" (rv) : "a" (val), "r" (m), "r" (d) : "dx" );
+ return rv;
+ }
+
+
int
getitimer(int which, struct itimerval *value)
{
***************
*** 61,70 ****
errno = EINVAL;
return -1;
}
! value->it_value.tv_sec = expire / UCLOCKS_PER_SEC;
! value->it_value.tv_usec = (expire % UCLOCKS_PER_SEC)*3433/4096;
! value->it_interval.tv_sec = reload / UCLOCKS_PER_SEC;
! value->it_interval.tv_usec= (reload % UCLOCKS_PER_SEC)*3433/4096;
return 0;
}
--- 78,89 ----
errno = EINVAL;
return -1;
}
! value->it_value.tv_sec = expire / UCLOCKS_PER_SEC;
! value->it_value.tv_usec = muldiv(expire % UCLOCKS_PER_SEC,
! 1000000, UCLOCKS_PER_SEC);
! value->it_interval.tv_sec = reload / UCLOCKS_PER_SEC;
! value->it_interval.tv_usec = muldiv(reload % UCLOCKS_PER_SEC,
! 1000000, UCLOCKS_PER_SEC);
return 0;
}
***************
*** 223,229 ****
so don't return just yet. */
}
! *t_rel = value->it_interval.tv_sec * UCLOCKS_PER_SEC;
/* Posix systems expect timer values smaller than the resolution of
the system clock be rounded up to the clock resolution. */
--- 242,248 ----
so don't return just yet. */
}
! *t_rel = (uclock_t)value->it_interval.tv_sec * UCLOCKS_PER_SEC;
/* Posix systems expect timer values smaller than the resolution of
the system clock be rounded up to the clock resolution. */
***************
*** 234,257 ****
if (value->it_interval.tv_sec == 0 && usecs < usecs_min)
usecs = usecs_min;
! /* Rounding errors ?? First multiply and then divide gives an
! overflow if the USEC member is larger than 524288. */
! if (usecs < 524200)
! *t_rel += (usecs * 4096) / 3433;
! else
! *t_rel += (usecs * 2048) / 1716;
if ((value->it_value.tv_sec|value->it_value.tv_usec) == 0)
return 0;
! *t_exp = value->it_value.tv_sec * UCLOCKS_PER_SEC;
usecs = value->it_value.tv_usec;
if (value->it_value.tv_sec == 0 && usecs < usecs_min)
usecs = usecs_min;
! if (usecs < 524200)
! *t_exp += (usecs * 4096) / 3433;
! else
! *t_exp += (usecs * 2048) / 1716;
/* u_now is returned zero first time uclock() is called. That first
call could be the one we issued above, or it could be two days
--- 253,270 ----
if (value->it_interval.tv_sec == 0 && usecs < usecs_min)
usecs = usecs_min;
! /* No more rounding errors here. And no overflows (when `usecs' is not
! absurdly large), since the intermediate result is now 64 bits wide. */
! *t_rel += muldiv(usecs, UCLOCKS_PER_SEC, 1000000);
if ((value->it_value.tv_sec|value->it_value.tv_usec) == 0)
return 0;
! *t_exp = (uclock_t)value->it_value.tv_sec * UCLOCKS_PER_SEC;
usecs = value->it_value.tv_usec;
if (value->it_value.tv_sec == 0 && usecs < usecs_min)
usecs = usecs_min;
! *t_exp += muldiv(usecs, UCLOCKS_PER_SEC, 1000000);
/* u_now is returned zero first time uclock() is called. That first
call could be the one we issued above, or it could be two days
- Raw text -