19,6 → 19,13 |
* For legalese, check out the included GPL license. |
*/ |
|
/* Added Advanced Timer Code |
* |
* Date: 8.4.2003 |
* Author: Giacomo Guidi <giacomo@gandalf.sssup.it> |
* |
*/ |
|
/* Inline functions for managing timespec structures. |
All timespec values are pointers!!! |
This file defines these functions: |
34,7 → 41,7 |
t = t + n |
ADDUSEC2TIMESPEC(m, t) |
t = t + m |
SUBTIMESPEC(s1, s2, d) Works well only if s1 >= s2 |
SUBTIMESPEC(s1, s2, d) |
d = s1 - s2 |
ADDTIMESPEC(s1, s2, d) |
d = s1 + s2 |
49,6 → 56,10 |
TIMESPEC_ASSIGN(t1,t2) |
t1 = t2 */ |
|
/* Advanced Timer Support |
* Giacomo Guidi <giacomo@gandalf.sssup.it> |
*/ |
|
#ifndef __LL_SYS_LL_TIME_H__ |
#define __LL_SYS_LL_TIME_H__ |
|
55,11 → 66,66 |
#include <ll/i386/defs.h> |
BEGIN_DEF |
|
extern signed long long clk_per_msec; |
extern signed long long init_tsc; |
|
extern unsigned char use_tsc; |
|
struct timespec { |
long tv_sec; /* Seconds */ |
long tv_nsec; /* Nanoseconds */ |
long long tsc; /* 64 bit TSC */ |
}; |
|
extern __inline__ void UNSIGNED_TSC2NSEC(unsigned long long tsc, unsigned long long *n) |
{ |
|
unsigned long nl,nh; |
|
nl = *n & 0xFFFFFFFF; |
nh = *n >> 32; |
|
__asm__("mull %%ecx\n\t" |
"movl %%eax,%%esi\n\t" |
"movl %%edx,%%edi\n\t" |
"xorl %%edx,%%edx\n\t" |
"movl %6,%%eax\n\t" |
"mull %%ecx\n\t" |
"addl %%edi,%%eax\n\t" |
"adcl $0,%%edx\n\t" |
"movl %5,%%ecx\n\t" |
"divl %%ecx\n\t" |
"xchgl %%eax,%%esi\n\t" |
"divl %%ecx\n\t" |
: "=a" (nl), "=S" (nh) |
: "c" (1000000), "a" ((unsigned long)(tsc & 0xFFFFFFFF)), "d" (0), |
"m" ((unsigned long)(clk_per_msec)), "m" ((unsigned long)(tsc >> 32)), |
"S" (0), "D" (0)); |
|
*n = nh; |
*n <<= 32; |
*n |= nl; |
|
} |
|
extern __inline__ void ADJUST_TIMESPEC(struct timespec *t) |
{ |
|
signed long long dt,dn; |
|
dt = t->tsc - init_tsc; |
|
if (dt >= 0) UNSIGNED_TSC2NSEC((unsigned long long)(dt),(unsigned long long *)&dn); |
else { |
UNSIGNED_TSC2NSEC((unsigned long long)(-dt),(unsigned long long *)&dn); |
dn -= dn; |
} |
|
t->tv_sec = dn / 1000000000; |
t->tv_nsec = dn % 1000000000; |
|
} |
|
/* |
* these macros come from the Utah Flux oskit... |
*/ |
66,27 → 132,50 |
|
#define TIMESPEC2NANOSEC(t) ((t)->tv_sec * 1000000000 + (t)->tv_nsec) |
#define TIMESPEC2USEC(t) ((t)->tv_sec * 1000000 + (t)->tv_nsec / 1000) |
#define NULL_TIMESPEC(t) ((t)->tv_sec = (t)->tv_nsec = 0) |
#define ADDNANO2TIMESPEC(n, t) ((t)->tv_nsec += (n), \ |
(t)->tv_sec += (t)->tv_nsec / 1000000000, \ |
(t)->tv_nsec %= 1000000000) |
#define NULL_TIMESPEC(t) ((t)->tv_sec = (t)->tv_nsec = 0, (t)->tsc = 0) |
|
#define SUBTIMESPEC(s1, s2, d) \ |
((d)->tv_nsec = ((s1)->tv_nsec >= (s2)->tv_nsec) ? \ |
(((d)->tv_sec = (s1)->tv_sec - (s2)->tv_sec), \ |
(s1)->tv_nsec - (s2)->tv_nsec) \ |
: \ |
(((d)->tv_sec = (s1)->tv_sec - (s2)->tv_sec - 1), \ |
(1000000000 + (s1)->tv_nsec - (s2)->tv_nsec))) |
extern __inline__ void ADDNANO2TIMESPEC(const signed long n, struct timespec *t) |
{ |
t->tv_nsec += n; |
t->tv_sec += t->tv_nsec / 1000000000; |
t->tv_nsec %= 1000000000; |
|
/* |
* ...and these not! |
*/ |
if (use_tsc) t->tsc += clk_per_msec * n / 1000000; |
|
} |
|
extern __inline__ void ADDUSEC2TIMESPEC(const signed long m, struct timespec *t) |
{ |
|
t->tv_nsec += m * 1000; |
t->tv_sec += t->tv_nsec / 1000000000; |
t->tv_nsec %= 1000000000; |
|
if (use_tsc) t->tsc += clk_per_msec * m / 1000; |
|
} |
|
extern __inline__ void SUBTIMESPEC(const struct timespec *s1, |
const struct timespec *s2, |
struct timespec *d) |
{ |
if (s1->tv_nsec >= s2->tv_nsec) { |
d->tv_sec = s1->tv_sec - s2->tv_sec; |
d->tv_nsec = s1->tv_nsec - s2->tv_nsec; |
} else { |
d->tv_sec = s1->tv_sec - s2->tv_sec - 1; |
d->tv_nsec = 1000000000 + s1->tv_nsec - s2->tv_nsec; |
} |
|
if (use_tsc) d->tsc = s1->tsc - s2->tsc + init_tsc; |
|
} |
|
extern __inline__ void ADDTIMESPEC(const struct timespec *s1, |
const struct timespec *s2, |
struct timespec *d) |
{ |
|
d->tv_sec = s1->tv_sec + s2->tv_sec; |
d->tv_nsec = s1->tv_nsec + s2->tv_nsec; |
|
97,12 → 186,10 |
d->tv_sec++; |
d->tv_nsec -= 1000000000; |
} |
} |
|
if (use_tsc) d->tsc = s1->tsc + s2->tsc - init_tsc; |
|
#define ADDUSEC2TIMESPEC(m, t) ((t)->tv_nsec += (m%1000000)*1000, \ |
(t)->tv_sec += ((t)->tv_nsec / 1000000000) + (m/1000000), \ |
(t)->tv_nsec %= 1000000000) |
} |
|
#define TIMESPEC_A_LT_B(a,b) \ |
( \ |
123,7 → 210,7 |
((a)->tv_sec != (b)->tv_sec || (a)->tv_nsec != (b)->tv_nsec) |
|
#define TIMESPEC_ASSIGN(t1,t2) \ |
((t1)->tv_sec = (t2)->tv_sec, (t1)->tv_nsec = (t2)->tv_nsec) |
((t1)->tv_sec = (t2)->tv_sec, (t1)->tv_nsec = (t2)->tv_nsec, (t1)->tsc = (t2)->tsc) |
|
#if 0 |
#define PITSPEC2TIMESPEC(a,b) \ |
148,8 → 235,12 |
#endif |
|
TIME ll_gettime(int mode, struct timespec *tsres); |
void ll_read_timespec(struct timespec *tspec); |
|
//Advanced Timer (advtimer.c) |
void read_timespec(struct timespec *tspec); |
void ll_init_advtimer(void); |
void restore_CMOS(void); |
|
#define TIME_PTICK 1 |
#define TIME_EXACT 2 |
#define TIME_NEW 3 |