Jan Kiszka wrote: > Gilles Chanteperdrix wrote: > > Jan Kiszka wrote: > > > Gilles Chanteperdrix wrote: > > > > Jan Kiszka wrote: > > > > > Gilles Chanteperdrix wrote: > > > > > > Hi, > > > > > > > > > > > > here comes, for review, a patch which reduces the overhead of > > > > > > clock_gettime by directly reading the tsc in user-space for > > > > > > architectures that support it. > > > > > > > > > > Highly welcome. But I have one concern: How and when do you > > propagate > > > > > wallclock_offset changes to user space? > > > > > > > > Since clock_settime is not implemented, never, but if clock_settime > > was > > > > implemented, clock_settime would re-issue the __xn_sys_info syscall. > > > > > > This excludes automatic clock adjustment, something I'm convinced we > > > will have to provide in the future. > > > > When we provide automatic clock adjustment, we will have to devise > > something more subtle than just an offset, so we will have to redesign > > I think offset + scaling factor. > > > posix clocks support anyway. Maybe clock_gettime(CLOCK_REALTIME) will > > then always be a syscall. After all, rt_timer_read is a syscall. If you > > want the fast clock, use CLOCK_MONOTONIC or rt_timer_tsc. > > Actually, the issue of the intermediate approach starts earlier: as soon > as you have clock_settime. Then you need to sync the offset across > applications in different processes. > > Having clock_monotonic (and maybe also rt_timer_tsc2ns) as a fast > variant already now is not bad. But beyond that, before introducing a > new interface between kernel and user space, I would like to consider > the effort to get it future-proof immediately. That doesn't mean that we > already have to implement clock adjustment, but we may already prepare > the prerequisites.
Ok. Here is a new version that does not break the ABI, and where clock_gettime(CLOCK_REALTIME) remains a syscall. Note that it also adds user-space conversions between tsc and ns to the native skin. -- Gilles Chanteperdrix.
Index: include/asm-ia64/Makefile.in =================================================================== --- include/asm-ia64/Makefile.in (revision 2454) +++ include/asm-ia64/Makefile.in (working copy) @@ -230,7 +230,9 @@ target_os = @target_os@ target_vendor = @target_vendor@ includesubdir = $(includedir)/asm-ia64 -includesub_HEADERS = atomic.h calibration.h features.h hal.h syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h syscall.h system.h wrappers.h + SUBDIRS = bits all: all-recursive Index: include/asm-ia64/Makefile.am =================================================================== --- include/asm-ia64/Makefile.am (revision 2454) +++ include/asm-ia64/Makefile.am (working copy) @@ -1,5 +1,6 @@ includesubdir = $(includedir)/asm-ia64 -includesub_HEADERS = atomic.h calibration.h features.h hal.h syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h syscall.h system.h wrappers.h SUBDIRS = bits Index: include/asm-ia64/arith.h =================================================================== --- include/asm-ia64/arith.h (revision 0) +++ include/asm-ia64/arith.h (revision 0) @@ -0,0 +1,6 @@ +#ifndef _XENO_ASM_IA64_ARITH_H +#define _XENO_ASM_IA64_ARITH_H + +#include <asm-generic/xenomai/arith.h> + +#endif /* _XENO_ASM_IA64_ARITH_H */ Index: include/asm-blackfin/Makefile.in =================================================================== --- include/asm-blackfin/Makefile.in (revision 2454) +++ include/asm-blackfin/Makefile.in (working copy) @@ -230,8 +230,8 @@ target_os = @target_os@ target_vendor = @target_vendor@ includesubdir = $(includedir)/asm-blackfin -includesub_HEADERS = atomic.h calibration.h features.h hal.h \ - syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h syscall.h system.h wrappers.h SUBDIRS = bits all: all-recursive Index: include/asm-blackfin/Makefile.am =================================================================== --- include/asm-blackfin/Makefile.am (revision 2454) +++ include/asm-blackfin/Makefile.am (working copy) @@ -1,6 +1,6 @@ includesubdir = $(includedir)/asm-blackfin -includesub_HEADERS = atomic.h calibration.h features.h hal.h \ - syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h syscall.h system.h wrappers.h SUBDIRS = bits Index: include/asm-blackfin/arith.h =================================================================== --- include/asm-blackfin/arith.h (revision 0) +++ include/asm-blackfin/arith.h (revision 0) @@ -0,0 +1,6 @@ +#ifndef _XENO_ASM_BLACKFIN_ARITH_H +#define _XENO_ASM_BLACKFIN_ARITH_H + +#include <asm-generic/xenomai/arith.h> + +#endif /* _XENO_ASM_BLACKFIN_ARITH_H */ Index: include/asm-generic/syscall.h =================================================================== --- include/asm-generic/syscall.h (revision 2454) +++ include/asm-generic/syscall.h (working copy) @@ -55,7 +55,6 @@ unsigned long long cpufreq; /* CPU frequency */ unsigned long tickval; /* Tick duration (ns) */ - } xnsysinfo_t; #define SIGHARDEN SIGWINCH Index: include/asm-generic/bits/bind.h =================================================================== --- include/asm-generic/bits/bind.h (revision 2454) +++ include/asm-generic/bits/bind.h (working copy) @@ -62,7 +62,7 @@ sa.sa_flags = 0; sigaction(SIGXCPU, &sa, NULL); - return __xn_mux_shifted_id(muxid); + return muxid; } static inline int @@ -105,7 +105,7 @@ exit(1); } - return __xn_mux_shifted_id(muxid); + return muxid; } #endif /* _XENO_ASM_GENERIC_BITS_BIND_H */ Index: include/asm-generic/Makefile.in =================================================================== --- include/asm-generic/Makefile.in (revision 2454) +++ include/asm-generic/Makefile.in (working copy) @@ -230,7 +230,7 @@ target_os = @target_os@ target_vendor = @target_vendor@ includesubdir = $(includedir)/asm-generic -includesub_HEADERS = features.h hal.h syscall.h system.h wrappers.h +includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h SUBDIRS = bits all: all-recursive Index: include/asm-generic/Makefile.am =================================================================== --- include/asm-generic/Makefile.am (revision 2454) +++ include/asm-generic/Makefile.am (working copy) @@ -1,5 +1,5 @@ includesubdir = $(includedir)/asm-generic -includesub_HEADERS = features.h hal.h syscall.h system.h wrappers.h +includesub_HEADERS = arith.h features.h hal.h syscall.h system.h wrappers.h SUBDIRS = bits Index: include/asm-generic/hal.h =================================================================== --- include/asm-generic/hal.h (revision 2454) +++ include/asm-generic/hal.h (working copy) @@ -37,8 +37,8 @@ #include <linux/kallsyms.h> #include <linux/init.h> #include <asm/byteorder.h> -#include <asm/div64.h> #include <asm/xenomai/wrappers.h> +#include <asm/xenomai/arith.h> #define RTHAL_DOMAIN_ID 0x58454e4f @@ -385,121 +385,6 @@ #define rthal_printk printk -#ifdef __BIG_ENDIAN -#define endianstruct struct { unsigned _h; unsigned _l; } _s -#else /* __LITTLE_ENDIAN */ -#define endianstruct struct { unsigned _l; unsigned _h; } _s -#endif - -#ifndef __rthal_u64tou32 -#define __rthal_u64tou32(ull, h, l) ({ \ - union { unsigned long long _ull; \ - endianstruct; \ - } _u; \ - _u._ull = (ull); \ - (h) = _u._s._h; \ - (l) = _u._s._l; \ -}) -#endif /* !__rthal_u64tou32 */ - -#ifndef __rthal_u64fromu32 -#define __rthal_u64fromu32(h, l) ({ \ - union { unsigned long long _ull; \ - endianstruct; \ - } _u; \ - _u._s._h = (h); \ - _u._s._l = (l); \ - _u._ull; \ -}) -#endif /* !__rthal_u64fromu32 */ - -#ifndef rthal_ullmul -static inline __attribute_const__ unsigned long long -__rthal_generic_ullmul(const unsigned m0, const unsigned m1) -{ - return (unsigned long long) m0 * m1; -} -#define rthal_ullmul(m0,m1) __rthal_generic_ullmul((m0),(m1)) -#endif /* !rthal_ullmul */ - -#ifndef rthal_ulldiv -static inline unsigned long long __rthal_generic_ulldiv (unsigned long long ull, - const unsigned uld, - unsigned long *const rp) -{ - const unsigned r = do_div(ull, uld); - - if (rp) - *rp = r; - - return ull; -} -#define rthal_ulldiv(ull,uld,rp) __rthal_generic_ulldiv((ull),(uld),(rp)) -#endif /* !rthal_ulldiv */ - -#ifndef rthal_uldivrem -#define rthal_uldivrem(ull,ul,rp) ((unsigned) rthal_ulldiv((ull),(ul),(rp))) -#endif /* !rthal_uldivrem */ - -#ifndef rthal_imuldiv -static inline __attribute_const__ int __rthal_generic_imuldiv (int i, - int mult, - int div) -{ - /* Returns (int)i = (unsigned long long)i*(unsigned)(mult)/(unsigned)div. */ - const unsigned long long ull = rthal_ullmul(i, mult); - return rthal_uldivrem(ull, div, NULL); -} -#define rthal_imuldiv(i,m,d) __rthal_generic_imuldiv((i),(m),(d)) -#endif /* !rthal_imuldiv */ - -#ifndef rthal_llimd -/* Division of an unsigned 96 bits ((h << 32) + l) by an unsigned 32 bits. - Building block for llimd. Without const qualifiers, gcc reload registers - after each call to uldivrem. */ -static inline unsigned long long -__rthal_generic_div96by32 (const unsigned long long h, - const unsigned l, - const unsigned d, - unsigned long *const rp) -{ - unsigned long rh; - const unsigned qh = rthal_uldivrem(h, d, &rh); - const unsigned long long t = __rthal_u64fromu32(rh, l); - const unsigned ql = rthal_uldivrem(t, d, rp); - - return __rthal_u64fromu32(qh, ql); -} - -static inline __attribute_const__ -unsigned long long __rthal_generic_ullimd (const unsigned long long op, - const unsigned m, - const unsigned d) -{ - unsigned oph, opl, tlh, tll; - unsigned long long th, tl; - - __rthal_u64tou32(op, oph, opl); - tl = rthal_ullmul(opl, m); - __rthal_u64tou32(tl, tlh, tll); - th = rthal_ullmul(oph, m); - th += tlh; - - return __rthal_generic_div96by32(th, tll, d, NULL); -} - -static inline __attribute_const__ long long __rthal_generic_llimd (long long op, - unsigned m, - unsigned d) -{ - - if(op < 0LL) - return -__rthal_generic_ullimd(-op, m, d); - return __rthal_generic_ullimd(op, m, d); -} -#define rthal_llimd(ll,m,d) __rthal_generic_llimd((ll),(m),(d)) -#endif /* !rthal_llimd */ - typedef ipipe_irq_handler_t rthal_irq_handler_t; typedef ipipe_irq_ackfn_t rthal_irq_ackfn_t; Index: include/asm-generic/system.h =================================================================== --- include/asm-generic/system.h (revision 2454) +++ include/asm-generic/system.h (working copy) @@ -133,18 +133,6 @@ #define xnarch_logerr(fmt,args...) printk(KERN_ERR XNARCH_PROMPT fmt , ##args) #define xnarch_printf(fmt,args...) printk(KERN_INFO XNARCH_PROMPT fmt , ##args) -#define xnarch_ullmod(ull,uld,rem) ({ xnarch_ulldiv(ull,uld,rem); (*rem); }) -#define xnarch_uldiv(ull, d) rthal_uldivrem(ull, d, NULL) -#define xnarch_ulmod(ull, d) ({ u_long _rem; \ - rthal_uldivrem(ull,d,&_rem); _rem; }) - -#define xnarch_ullmul rthal_ullmul -#define xnarch_uldivrem rthal_uldivrem -#define xnarch_ulldiv rthal_ulldiv -#define xnarch_imuldiv rthal_imuldiv -#define xnarch_llimd rthal_llimd -#define xnarch_get_cpu_tsc rthal_rdtsc - typedef cpumask_t xnarch_cpumask_t; #ifdef CONFIG_SMP Index: include/asm-generic/arith.h =================================================================== --- include/asm-generic/arith.h (revision 0) +++ include/asm-generic/arith.h (revision 0) @@ -0,0 +1,173 @@ +/** + * @ingroup hal + * @file + * + * Generic arithmetic/conversion routines. + * Copyright © 2005 Stelian Pop. + * Copyright © 2005 Gilles Chanteperdrix. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139, + * USA; either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * @addtogroup hal + [EMAIL PROTECTED]/ + +#ifndef _XENO_ASM_GENERIC_ARITH_H +#define _XENO_ASM_GENERIC_ARITH_H + +#ifdef __KERNEL__ +#include <asm/div64.h> +#else /* !__KERNEL__ */ +static inline unsigned __rthal_do_div(unsigned long long *a, unsigned d) +{ + unsigned r = *a % d; + *a /= d; + return r; +} +#define do_div(a, d) __rthal_do_div(&(a), (d)) +#endif /* !__KERNEL__ */ + +#ifdef __BIG_ENDIAN +#define endianstruct struct { unsigned _h; unsigned _l; } _s +#else /* __LITTLE_ENDIAN */ +#define endianstruct struct { unsigned _l; unsigned _h; } _s +#endif + +#ifndef __rthal_u64tou32 +#define __rthal_u64tou32(ull, h, l) ({ \ + union { unsigned long long _ull; \ + endianstruct; \ + } _u; \ + _u._ull = (ull); \ + (h) = _u._s._h; \ + (l) = _u._s._l; \ +}) +#endif /* !__rthal_u64tou32 */ + +#ifndef __rthal_u64fromu32 +#define __rthal_u64fromu32(h, l) ({ \ + union { unsigned long long _ull; \ + endianstruct; \ + } _u; \ + _u._s._h = (h); \ + _u._s._l = (l); \ + _u._ull; \ +}) +#endif /* !__rthal_u64fromu32 */ + +#ifndef rthal_ullmul +static inline __attribute_const__ unsigned long long +__rthal_generic_ullmul(const unsigned m0, const unsigned m1) +{ + return (unsigned long long) m0 * m1; +} +#define rthal_ullmul(m0,m1) __rthal_generic_ullmul((m0),(m1)) +#endif /* !rthal_ullmul */ + +#ifndef rthal_ulldiv +static inline unsigned long long __rthal_generic_ulldiv (unsigned long long ull, + const unsigned uld, + unsigned long *const rp) +{ + const unsigned r = do_div(ull, uld); + + if (rp) + *rp = r; + + return ull; +} +#define rthal_ulldiv(ull,uld,rp) __rthal_generic_ulldiv((ull),(uld),(rp)) +#endif /* !rthal_ulldiv */ + +#ifndef rthal_uldivrem +#define rthal_uldivrem(ull,ul,rp) ((unsigned) rthal_ulldiv((ull),(ul),(rp))) +#endif /* !rthal_uldivrem */ + +#ifndef rthal_imuldiv +static inline __attribute_const__ int __rthal_generic_imuldiv (int i, + int mult, + int div) +{ + /* Returns (int)i = (unsigned long long)i*(unsigned)(mult)/(unsigned)div. */ + const unsigned long long ull = rthal_ullmul(i, mult); + return rthal_uldivrem(ull, div, NULL); +} +#define rthal_imuldiv(i,m,d) __rthal_generic_imuldiv((i),(m),(d)) +#endif /* !rthal_imuldiv */ + +#ifndef rthal_llimd +/* Division of an unsigned 96 bits ((h << 32) + l) by an unsigned 32 bits. + Building block for llimd. Without const qualifiers, gcc reload registers + after each call to uldivrem. */ +static inline unsigned long long +__rthal_generic_div96by32 (const unsigned long long h, + const unsigned l, + const unsigned d, + unsigned long *const rp) +{ + unsigned long rh; + const unsigned qh = rthal_uldivrem(h, d, &rh); + const unsigned long long t = __rthal_u64fromu32(rh, l); + const unsigned ql = rthal_uldivrem(t, d, rp); + + return __rthal_u64fromu32(qh, ql); +} + +static inline __attribute_const__ +unsigned long long __rthal_generic_ullimd (const unsigned long long op, + const unsigned m, + const unsigned d) +{ + unsigned oph, opl, tlh, tll; + unsigned long long th, tl; + + __rthal_u64tou32(op, oph, opl); + tl = rthal_ullmul(opl, m); + __rthal_u64tou32(tl, tlh, tll); + th = rthal_ullmul(oph, m); + th += tlh; + + return __rthal_generic_div96by32(th, tll, d, NULL); +} + +static inline __attribute_const__ long long __rthal_generic_llimd (long long op, + unsigned m, + unsigned d) +{ + + if(op < 0LL) + return -__rthal_generic_ullimd(-op, m, d); + return __rthal_generic_ullimd(op, m, d); +} +#define rthal_llimd(ll,m,d) __rthal_generic_llimd((ll),(m),(d)) +#endif /* !rthal_llimd */ + +#define xnarch_ullmod(ull,uld,rem) ({ xnarch_ulldiv(ull,uld,rem); (*rem); }) +#define xnarch_uldiv(ull, d) rthal_uldivrem(ull, d, NULL) +#define xnarch_ulmod(ull, d) ({ u_long _rem; \ + rthal_uldivrem(ull,d,&_rem); _rem; }) + +#define xnarch_ullmul rthal_ullmul +#define xnarch_uldivrem rthal_uldivrem +#define xnarch_ulldiv rthal_ulldiv +#define xnarch_imuldiv rthal_imuldiv +#define xnarch_llimd rthal_llimd +#define xnarch_get_cpu_tsc rthal_rdtsc + +/[EMAIL PROTECTED]/ + +#endif /* _XENO_ASM_GENERIC_ARITH_H */ Index: include/asm-powerpc/Makefile.in =================================================================== --- include/asm-powerpc/Makefile.in (revision 2454) +++ include/asm-powerpc/Makefile.in (working copy) @@ -230,8 +230,8 @@ target_os = @target_os@ target_vendor = @target_vendor@ includesubdir = $(includedir)/asm-powerpc -includesub_HEADERS = atomic.h calibration.h features.h hal.h \ - syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h syscall.h system.h wrappers.h SUBDIRS = bits all: all-recursive Index: include/asm-powerpc/Makefile.am =================================================================== --- include/asm-powerpc/Makefile.am (revision 2454) +++ include/asm-powerpc/Makefile.am (working copy) @@ -1,6 +1,6 @@ includesubdir = $(includedir)/asm-powerpc -includesub_HEADERS = atomic.h calibration.h features.h hal.h \ - syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h syscall.h system.h wrappers.h SUBDIRS = bits Index: include/asm-powerpc/arith.h =================================================================== --- include/asm-powerpc/arith.h (revision 0) +++ include/asm-powerpc/arith.h (revision 0) @@ -0,0 +1,6 @@ +#ifndef _XENO_ASM_POWERPC_ARITH_H +#define _XENO_ASM_POWERPC_ARITH_H + +#include <asm-generic/xenomai/arith.h> + +#endif /* _XENO_ASM_POWERPC_ARITH_H */ Index: include/asm-arm/Makefile.in =================================================================== --- include/asm-arm/Makefile.in (revision 2454) +++ include/asm-arm/Makefile.in (working copy) @@ -230,8 +230,8 @@ target_os = @target_os@ target_vendor = @target_vendor@ includesubdir = $(includedir)/asm-arm -includesub_HEADERS = atomic.h calibration.h features.h hal.h \ - syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h syscall.h system.h wrappers.h SUBDIRS = bits all: all-recursive Index: include/asm-arm/Makefile.am =================================================================== --- include/asm-arm/Makefile.am (revision 2454) +++ include/asm-arm/Makefile.am (working copy) @@ -1,6 +1,6 @@ includesubdir = $(includedir)/asm-arm -includesub_HEADERS = atomic.h calibration.h features.h hal.h \ - syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h syscall.h system.h wrappers.h SUBDIRS = bits Index: include/asm-arm/arith.h =================================================================== --- include/asm-arm/arith.h (revision 0) +++ include/asm-arm/arith.h (revision 0) @@ -0,0 +1,6 @@ +#ifndef _XENO_ASM_ARM_ARITH_H +#define _XENO_ASM_ARM_ARITH_H + +#include <asm-generic/xenomai/arith.h> + +#endif /* _XENO_ASM_ARM_ARITH_H */ Index: include/posix/syscall.h =================================================================== --- include/posix/syscall.h (revision 2454) +++ include/posix/syscall.h (working copy) @@ -100,6 +100,11 @@ #define __pse51_condattr_setpshared 74 #define __pse51_thread_getschedparam 75 +typedef struct pse51_sysinfo { + unsigned period; + unsigned long long wallclock_offset; +} pse51_sysinfo_t; + #ifdef __KERNEL__ #ifdef __cplusplus Index: include/asm-i386/Makefile.in =================================================================== --- include/asm-i386/Makefile.in (revision 2454) +++ include/asm-i386/Makefile.in (working copy) @@ -230,8 +230,8 @@ target_os = @target_os@ target_vendor = @target_vendor@ includesubdir = $(includedir)/asm-i386 -includesub_HEADERS = atomic.h calibration.h features.h \ - hal.h smi.h switch.h syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h smi.h switch.h syscall.h system.h wrappers.h SUBDIRS = bits all: all-recursive Index: include/asm-i386/Makefile.am =================================================================== --- include/asm-i386/Makefile.am (revision 2454) +++ include/asm-i386/Makefile.am (working copy) @@ -1,6 +1,6 @@ includesubdir = $(includedir)/asm-i386 -includesub_HEADERS = atomic.h calibration.h features.h \ - hal.h smi.h switch.h syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h smi.h switch.h syscall.h system.h wrappers.h SUBDIRS = bits Index: include/asm-i386/hal.h =================================================================== --- include/asm-i386/hal.h (revision 2454) +++ include/asm-i386/hal.h (working copy) @@ -39,71 +39,6 @@ #include <asm/xenomai/wrappers.h> -#define __rthal_u64tou32(ull, h, l) ({ \ - unsigned long long _ull = (ull); \ - (l) = _ull & 0xffffffff; \ - (h) = _ull >> 32; \ -}) - -#define __rthal_u64fromu32(h, l) ({ \ - unsigned long long _ull; \ - asm ( "": "=A"(_ull) : "d"(h), "a"(l)); \ - _ull; \ -}) - -/* const helper for rthal_uldivrem, so that the compiler will eliminate - multiple calls with same arguments, at no additionnal cost. */ -static inline __attribute_const__ unsigned long long -__rthal_uldivrem(const unsigned long long ull, const unsigned long d) -{ - unsigned long long ret; - __asm__ ("divl %1" : "=A,A"(ret) : "r,?m"(d), "A,A"(ull)); - /* Exception if quotient does not fit on unsigned long. */ - return ret; -} - -/* Fast long long division: when the quotient and remainder fit on 32 bits. */ -static inline unsigned long __rthal_i386_uldivrem(unsigned long long ull, - const unsigned d, - unsigned long *const rp) -{ - unsigned long q, r; - ull = __rthal_uldivrem(ull, d); - __asm__ ( "": "=d"(r), "=a"(q) : "A"(ull)); - if(rp) - *rp = r; - return q; -} -#define rthal_uldivrem(ull, d, rp) __rthal_i386_uldivrem((ull),(d),(rp)) - -/* Division of an unsigned 96 bits ((h << 32) + l) by an unsigned 32 bits. - Building block for ulldiv. */ -static inline unsigned long long __rthal_div96by32 (const unsigned long long h, - const unsigned long l, - const unsigned long d, - unsigned long *const rp) -{ - u_long rh; - const u_long qh = rthal_uldivrem(h, d, &rh); - const unsigned long long t = __rthal_u64fromu32(rh, l); - const u_long ql = rthal_uldivrem(t, d, rp); - - return __rthal_u64fromu32(qh, ql); -} - -/* Slow long long division. Uses rthal_uldivrem, hence has the same property: - the compiler removes redundant calls. */ -static inline unsigned long long -__rthal_i386_ulldiv (const unsigned long long ull, - const unsigned d, - unsigned long *const rp) -{ - unsigned long h, l; - __rthal_u64tou32(ull, h, l); - return __rthal_div96by32(h, l, d, rp); -} -#define rthal_ulldiv(ull,d,rp) __rthal_i386_ulldiv((ull),(d),(rp)) - #include <asm-generic/xenomai/hal.h> /* Read the generic bits. */ #ifndef CONFIG_X86_WP_WORKS_OK Index: include/asm-i386/arith.h =================================================================== --- include/asm-i386/arith.h (revision 0) +++ include/asm-i386/arith.h (revision 0) @@ -0,0 +1,107 @@ +/** + * @ingroup hal + * @file + * + * Arithmetic/conversion routines for x86. + * + * Original RTAI/x86 HAL services from: \n + * Copyright © 2000 Paolo Mantegazza, \n + * Copyright © 2000 Steve Papacharalambous, \n + * Copyright © 2000 Stuart Hughes, \n + * and others. + * + * RTAI/x86 rewrite over Adeos: \n + * Copyright © 2002,2003 Philippe Gerum. + * Major refactoring for Xenomai: \n + * Copyright © 2004,2005 Philippe Gerum. + * Arithmetic/conversion routines: \n + * Copyright © 2005 Gilles Chanteperdrix. + * + * Xenomai is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, Inc., 675 Mass Ave, + * Cambridge MA 02139, USA; either version 2 of the License, or (at + * your option) any later version. + * + * Xenomai is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Xenomai; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _XENO_ASM_I386_ARITH_H +#define _XENO_ASM_I386_ARITH_H + +#define __rthal_u64tou32(ull, h, l) ({ \ + unsigned long long _ull = (ull); \ + (l) = _ull & 0xffffffff; \ + (h) = _ull >> 32; \ +}) + +#define __rthal_u64fromu32(h, l) ({ \ + unsigned long long _ull; \ + asm ( "": "=A"(_ull) : "d"(h), "a"(l)); \ + _ull; \ +}) + +/* const helper for rthal_uldivrem, so that the compiler will eliminate + multiple calls with same arguments, at no additionnal cost. */ +static inline __attribute_const__ unsigned long long +__rthal_uldivrem(const unsigned long long ull, const unsigned long d) +{ + unsigned long long ret; + __asm__ ("divl %1" : "=A,A"(ret) : "r,?m"(d), "A,A"(ull)); + /* Exception if quotient does not fit on unsigned long. */ + return ret; +} + +/* Fast long long division: when the quotient and remainder fit on 32 bits. */ +static inline unsigned long __rthal_i386_uldivrem(unsigned long long ull, + const unsigned d, + unsigned long *const rp) +{ + unsigned long q, r; + ull = __rthal_uldivrem(ull, d); + __asm__ ( "": "=d"(r), "=a"(q) : "A"(ull)); + if(rp) + *rp = r; + return q; +} +#define rthal_uldivrem(ull, d, rp) __rthal_i386_uldivrem((ull),(d),(rp)) + +/* Division of an unsigned 96 bits ((h << 32) + l) by an unsigned 32 bits. + Building block for ulldiv. */ +static inline unsigned long long __rthal_div96by32 (const unsigned long long h, + const unsigned long l, + const unsigned long d, + unsigned long *const rp) +{ + u_long rh; + const u_long qh = rthal_uldivrem(h, d, &rh); + const unsigned long long t = __rthal_u64fromu32(rh, l); + const u_long ql = rthal_uldivrem(t, d, rp); + + return __rthal_u64fromu32(qh, ql); +} + +/* Slow long long division. Uses rthal_uldivrem, hence has the same property: + the compiler removes redundant calls. */ +static inline unsigned long long +__rthal_i386_ulldiv (const unsigned long long ull, + const unsigned d, + unsigned long *const rp) +{ + unsigned long h, l; + __rthal_u64tou32(ull, h, l); + return __rthal_div96by32(h, l, d, rp); +} +#define rthal_ulldiv(ull,d,rp) __rthal_i386_ulldiv((ull),(d),(rp)) + +#include <asm-generic/xenomai/arith.h> + +#endif /* _XENO_ASM_I386_ARITH_H */ Index: include/asm-x86_64/Makefile.in =================================================================== --- include/asm-x86_64/Makefile.in (revision 2454) +++ include/asm-x86_64/Makefile.in (working copy) @@ -230,8 +230,8 @@ target_os = @target_os@ target_vendor = @target_vendor@ includesubdir = $(includedir)/asm-x86_64 -includesub_HEADERS = atomic.h smi.h switch.h calibration.h features.h \ - hal.h syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h smi.h switch.h syscall.h system.h wrappers.h SUBDIRS = bits all: all-recursive Index: include/asm-x86_64/Makefile.am =================================================================== --- include/asm-x86_64/Makefile.am (revision 2454) +++ include/asm-x86_64/Makefile.am (working copy) @@ -1,6 +1,6 @@ includesubdir = $(includedir)/asm-x86_64 -includesub_HEADERS = atomic.h smi.h switch.h calibration.h features.h \ - hal.h syscall.h system.h wrappers.h fptest.h +includesub_HEADERS = arith.h atomic.h calibration.h features.h fptest.h \ + hal.h smi.h switch.h syscall.h system.h wrappers.h SUBDIRS = bits Index: include/asm-x86_64/arith.h =================================================================== --- include/asm-x86_64/arith.h (revision 0) +++ include/asm-x86_64/arith.h (revision 0) @@ -0,0 +1,6 @@ +#ifndef _XENO_ASM_X86_64_ARITH_H +#define _XENO_ASM_X86_64_ARITH_H + +#include <asm-generic/xenomai/arith.h> + +#endif /* _XENO_ASM_X86_64_ARITH_H */ Index: src/skins/psos+/init.c =================================================================== --- src/skins/psos+/init.c (revision 2454) +++ src/skins/psos+/init.c (working copy) @@ -27,6 +27,7 @@ { __psos_muxid = xeno_bind_skin(PSOS_SKIN_MAGIC, "psos", "xeno_psos"); + __psos_muxid = __xn_mux_shifted_id(__psos_muxid); } void k_fatal(u_long err_code, u_long flags) Index: src/skins/rtai/init.c =================================================================== --- src/skins/rtai/init.c (revision 2454) +++ src/skins/rtai/init.c (working copy) @@ -30,4 +30,5 @@ { __rtai_muxid = xeno_bind_skin(RTAI_SKIN_MAGIC, "RTAI", "xeno_rtai"); + __rtai_muxid = __xn_mux_shifted_id(__rtai_muxid); } Index: src/skins/posix/init.c =================================================================== --- src/skins/posix/init.c (revision 2454) +++ src/skins/posix/init.c (working copy) @@ -35,6 +35,7 @@ static int fork_handler_registered; int __wrap_pthread_setschedparam(pthread_t, int, const struct sched_param *); +void pse51_clock_init(int); static __attribute__ ((constructor)) void __init_posix_interface(void) @@ -42,9 +43,15 @@ struct sched_param parm; int muxid, err; - __pse51_muxid = + muxid = xeno_bind_skin(PSE51_SKIN_MAGIC, "POSIX", "xeno_posix"); +#ifdef CONFIG_XENO_HW_DIRECT_TSC + pse51_clock_init(muxid); +#endif /* CONFIG_XENO_HW_DIRECT_TSC */ + + __pse51_muxid = __xn_mux_shifted_id(muxid); + muxid = XENOMAI_SYSBIND(RTDM_SKIN_MAGIC, XENOMAI_FEAT_DEP, XENOMAI_ABI_REV, NULL); if (muxid > 0) { Index: src/skins/posix/clock.c =================================================================== --- src/skins/posix/clock.c (revision 2454) +++ src/skins/posix/clock.c (working copy) @@ -20,9 +20,24 @@ #include <pthread.h> /* For pthread_setcanceltype. */ #include <posix/syscall.h> #include <time.h> +#include <asm/xenomai/arith.h> extern int __pse51_muxid; +#ifdef CONFIG_XENO_HW_DIRECT_TSC +static xnsysinfo_t sysinfo; + +void pse51_clock_init(int muxid) +{ + int err = -XENOMAI_SYSCALL3(__xn_sys_info, muxid, &sysinfo); + if (err) { + fprintf(stderr, "Xenomai Posix skin init: " + "sys_info: %s\n", strerror(err)); + exit(EXIT_FAILURE); + } +} +#endif /* CONFIG_XENO_HW_DIRECT_TSC */ + int __wrap_clock_getres(clockid_t clock_id, struct timespec *tp) { int err = -XENOMAI_SKINCALL2(__pse51_muxid, @@ -39,11 +54,25 @@ int __wrap_clock_gettime(clockid_t clock_id, struct timespec *tp) { - int err = -XENOMAI_SKINCALL2(__pse51_muxid, - __pse51_clock_gettime, - clock_id, - tp); + int err; +#ifdef CONFIG_XENO_HW_DIRECT_TSC + if (clock_id == CLOCK_MONOTONIC) { + unsigned long long tsc, ns; + unsigned long rem; + tsc = __xn_rdtsc(); + ns = xnarch_llimd(tsc, 1000000000, sysinfo.cpufreq); + tp->tv_sec = xnarch_ulldiv(ns, 1000000000, &rem); + tp->tv_nsec = rem; + return 0; + } +#endif /* CONFIG_XENO_HW_DIRECT_TSC */ + + err = -XENOMAI_SKINCALL2(__pse51_muxid, + __pse51_clock_gettime, + clock_id, + tp); + if (!err) return 0; Index: src/skins/vrtx/init.c =================================================================== --- src/skins/vrtx/init.c (revision 2454) +++ src/skins/vrtx/init.c (working copy) @@ -43,6 +43,7 @@ __vrtx_muxid = xeno_bind_skin(VRTX_SKIN_MAGIC, "vrtx", "xeno_vrtx"); + __vrtx_muxid = __xn_mux_shifted_id(__vrtx_muxid); /* Allocate a TSD key for indexing self task pointers. */ Index: src/skins/vxworks/init.c =================================================================== --- src/skins/vxworks/init.c (revision 2454) +++ src/skins/vxworks/init.c (working copy) @@ -41,6 +41,7 @@ { __vxworks_muxid = xeno_bind_skin(VXWORKS_SKIN_MAGIC, "vxworks", "xeno_vxworks"); + __vxworks_muxid = __xn_mux_shifted_id(__vxworks_muxid); /* Allocate a TSD key for indexing self task pointers. */ Index: src/skins/native/init.c =================================================================== --- src/skins/native/init.c (revision 2454) +++ src/skins/native/init.c (working copy) @@ -30,6 +30,7 @@ pthread_key_t __native_tskey; int __native_muxid = -1; +void native_timer_init(int); static void __flush_tsd(void *tsd) { @@ -43,6 +44,12 @@ __native_muxid = xeno_bind_skin(XENO_SKIN_MAGIC, "native", "xeno_native"); +#ifdef CONFIG_XENO_HW_DIRECT_TSC + native_timer_init(__native_muxid); +#endif /* CONFIG_XENO_HW_DIRECT_TSC */ + + __native_muxid = __xn_mux_shifted_id(__native_muxid); + /* Allocate a TSD key for indexing self task pointers. */ if (pthread_key_create(&__native_tskey, &__flush_tsd) != 0) { Index: src/skins/native/timer.c =================================================================== --- src/skins/native/timer.c (revision 2454) +++ src/skins/native/timer.c (working copy) @@ -21,6 +21,20 @@ extern int __native_muxid; +#ifdef CONFIG_XENO_HW_DIRECT_TSC +static xnsysinfo_t sysinfo; + +void native_timer_init(int muxid) +{ + int err = XENOMAI_SYSCALL3(__xn_sys_info, muxid, &sysinfo); + if (err) { + fprintf(stderr, "Native skin init: " + "sys_info: %s\n", strerror(-err)); + exit(EXIT_FAILURE); + } +} +#endif /* CONFIG_XENO_HW_DIRECT_TSC */ + int rt_timer_set_mode(RTIME tickval) { return XENOMAI_SKINCALL1(__native_muxid, __native_timer_set_mode, @@ -68,7 +82,11 @@ { RTIME ticks; +#ifdef CONFIG_XENO_HW_DIRECT_TSC + ticks = xnarch_llimd(ns, sysinfo.cpufreq, 1000000000); +#else /* !CONFIG_XENO_HW_DIRECT_TSC */ XENOMAI_SKINCALL2(__native_muxid, __native_timer_ns2tsc, &ticks, &ns); +#endif /* !CONFIG_XENO_HW_DIRECT_TSC */ return ticks; } @@ -76,7 +94,11 @@ { SRTIME ns; +#ifdef CONFIG_XENO_HW_DIRECT_TSC + ticks = xnarch_llimd(ticks, 1000000000, sysinfo.cpufreq); +#else /* !CONFIG_XENO_HW_DIRECT_TSC */ XENOMAI_SKINCALL2(__native_muxid, __native_timer_tsc2ns, &ns, &ticks); +#endif /* !CONFIG_XENO_HW_DIRECT_TSC */ return ns; } Index: src/skins/rtdm/init.c =================================================================== --- src/skins/rtdm/init.c (revision 2454) +++ src/skins/rtdm/init.c (working copy) @@ -34,4 +34,6 @@ __rtdm_muxid = xeno_bind_skin_opt(RTDM_SKIN_MAGIC, "rtdm", "xeno_rtdm"); + __rtdm_muxid = __xn_mux_shifted_id(__rtdm_muxid); + } Index: ksrc/skins/posix/syscall.c =================================================================== --- ksrc/skins/posix/syscall.c (revision 2454) +++ ksrc/skins/posix/syscall.c (working copy) @@ -2891,7 +2891,7 @@ return NULL; } - + return ERR_PTR(-EINVAL); }
_______________________________________________ Xenomai-core mailing list Xenomai-core@gna.org https://mail.gna.org/listinfo/xenomai-core