Commit c8304cca authored by Philippe Gerum's avatar Philippe Gerum

Introduce time bases

git-svn-id: svn+ssh://svn.gna.org/svn/xenomai/trunk@2021 c6d672ea-8702-0410-b560-f74c916a59fe
parent 4102fafa
2006-12-31 Philippe Gerum <rpm@xenomai.org>
* ksrc: Introduce time bases to allow skins to be clocked
separately and concurrently, either in aperiodic or periodic mode.
2006-12-28 Philippe Gerum <rpm@xenomai.org>
* ksrc/arch/*/hal.c: Get rid of periodic hw setup.
......
......@@ -29,7 +29,6 @@
#include <asm-generic/xenomai/system.h>
#include <asm/xenomai/syscall.h>
#define XNARCH_DEFAULT_TICK 1000000 /* ns, i.e. 1ms */
#define XNARCH_HOST_TICK (1000000000UL/HZ)
#define XNARCH_THREAD_STACKSZ 4096
......
......@@ -27,7 +27,6 @@
#include <asm/system.h>
#include <asm/processor.h>
#define XNARCH_DEFAULT_TICK 1000000 /* ns, i.e. 1ms */
/* The I-pipe frees the Blackfin core timer for us, therefore we don't
need any host tick relay service since the regular Linux time
source is still ticking in parallel at the normal pace through
......
......@@ -47,6 +47,9 @@
#define CONFIG_XENO_OPT_DEBUG_NUCLEUS 0
#endif
/* Time base export */
#define xnarch_declare_tbase(base) do { } while(0)
/* Tracer interface */
#define xnarch_trace_max_begin(v) rthal_trace_max_begin(v)
#define xnarch_trace_max_end(v) rthal_trace_max_end(v)
......@@ -177,27 +180,27 @@ typedef struct xnarch_heapcb {
extern "C" {
#endif
static inline long long xnarch_tsc_to_ns (long long ts)
static inline long long xnarch_tsc_to_ns(long long ts)
{
return xnarch_llimd(ts,1000000000,RTHAL_CPU_FREQ);
}
static inline long long xnarch_ns_to_tsc (long long ns)
static inline long long xnarch_ns_to_tsc(long long ns)
{
return xnarch_llimd(ns,RTHAL_CPU_FREQ,1000000000);
}
static inline unsigned long long xnarch_get_cpu_time (void)
static inline unsigned long long xnarch_get_cpu_time(void)
{
return xnarch_tsc_to_ns(xnarch_get_cpu_tsc());
}
static inline unsigned long long xnarch_get_cpu_freq (void)
static inline unsigned long long xnarch_get_cpu_freq(void)
{
return RTHAL_CPU_FREQ;
}
static inline unsigned xnarch_current_cpu (void)
static inline unsigned xnarch_current_cpu(void)
{
return rthal_processor_id();
}
......
......@@ -27,7 +27,6 @@
#include <linux/ptrace.h>
#include <asm-generic/xenomai/system.h>
#define XNARCH_DEFAULT_TICK 1000000 /* ns, i.e. 1ms */
#ifdef CONFIG_X86_LOCAL_APIC
/* When the local APIC is enabled, we do not need to relay the host
tick since 8254 interrupts are already flowing normally to Linux
......
......@@ -29,11 +29,6 @@
#include <asm-generic/xenomai/system.h>
#ifdef CONFIG_IA64_HP_SIM
#define XNARCH_DEFAULT_TICK 31250000 /* ns, i.e. 31ms */
#else
#define XNARCH_DEFAULT_TICK XNARCH_HOST_TICK
#endif
#define XNARCH_HOST_TICK (1000000000UL/HZ)
#define XNARCH_THREAD_STACKSZ KERNEL_STACK_SIZE
......
......@@ -28,7 +28,6 @@
#include <linux/ptrace.h>
#include <asm-generic/xenomai/system.h>
#define XNARCH_DEFAULT_TICK 1000000 /* ns, i.e. 1ms */
#define XNARCH_HOST_TICK (1000000000UL/HZ)
#ifdef CONFIG_PPC64
......
......@@ -34,6 +34,7 @@
struct xnthread;
struct xnsynch;
struct xntbase;
struct XenoThread;
struct mvm_displayctx;
struct mvm_displayctl;
......@@ -82,7 +83,6 @@ typedef unsigned long xnlock_t;
/* Should be equal to the value used for creating the mvmtimer object (mvm_start_timer). */
#define XNARCH_TIMER_IRQ 1
#define XNARCH_DEFAULT_TICK 10000000 /* ns, i.e. 10ms */
#define XNARCH_HOST_TICK 0 /* No host ticking service. */
#define XNARCH_THREAD_STACKSZ 0 /* Let the simulator choose. */
......@@ -263,6 +263,8 @@ int mvm_run(void *tcbarg,
void mvm_finalize_init(void);
void mvm_declare_tbase(struct xntbase *base);
void mvm_sleep(unsigned long ticks);
int mvm_hook_irq(unsigned irq,
......@@ -483,6 +485,9 @@ if (cond) \
__mvm_breakable(mvm_post_graph)(&(obj)->__mvm_display_context,state); \
while(0)
/* Time base export */
#define xnarch_declare_tbase(base) mvm_declare_tbase(base)
/* Tracer interface */
#define xnarch_trace_max_begin(v) ({int err = -ENOSYS; err; })
#define xnarch_trace_max_end(v) ({int err = -ENOSYS; err; })
......@@ -539,10 +544,4 @@ static inline long IS_ERR(const void *ptr)
return IS_ERR_VALUE((unsigned long)ptr);
}
/* Pre-set config switches. */
#define CONFIG_XENO_OPT_TIMING_PERIODIC 1
#define CONFIG_XENO_OPT_TIMER_HEAP 1
#define CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY 256
#endif /* !_XENO_ASM_SIM_SYSTEM_H */
......@@ -25,7 +25,6 @@
#include <nucleus/timer.h>
#include <native/types.h>
#define TM_UNSET XN_NO_TICK
#define TM_ONESHOT XN_APERIODIC_TICK
typedef struct rt_timer_info {
......@@ -36,6 +35,10 @@ typedef struct rt_timer_info {
} RT_TIMER_INFO;
#if defined(__KERNEL__) || defined(__XENO_SIM__)
extern xntbase_t *__native_tbase;
#endif /* __KERNEL__ || __XENO_SIM__ */
#ifdef __cplusplus
extern "C" {
#endif
......
......@@ -20,6 +20,7 @@ include_HEADERS = \
synch.h \
system.h \
thread.h \
timebase.h \
timer.h \
trace.h \
types.h \
......
......@@ -237,6 +237,7 @@ include_HEADERS = \
synch.h \
system.h \
thread.h \
timebase.h \
timer.h \
trace.h \
types.h \
......
......@@ -32,7 +32,7 @@
/* Visible priority range supported by the core pod. */
#define XNCORE_MIN_PRIO 0
#define XNCORE_MAX_PRIO 256
#define XNCORE_MAX_PRIO 257
/* Total number of priority levels (including the hidden root one) */
#define XNCORE_NR_PRIO (XNCORE_MAX_PRIO - XNCORE_MIN_PRIO + 2)
......@@ -54,7 +54,8 @@ int xncore_mount(void);
int xncore_umount(void);
int xncore_attach(void);
int xncore_attach(int minprio,
int maxprio);
void xncore_detach(int xtype);
......
......@@ -55,7 +55,7 @@ struct xnltt_evmap {
#define xeno_ev_cpumigrate 17
#define xeno_ev_sigdispatch 18
#define xeno_ev_thrboot 19
#define xeno_ev_tmtick 20
#define xeno_ev_tstick 20
#define xeno_ev_sleepon 21
#define xeno_ev_wakeup1 22
#define xeno_ev_wakeupx 23
......@@ -80,8 +80,8 @@ struct xnltt_evmap {
#define xeno_ev_remhook 42
#define xeno_ev_thrperiodic 43
#define xeno_ev_thrwait 44
#define xeno_ev_tmstart 45
#define xeno_ev_tmstop 46
#define xeno_ev_tsenable 45
#define xeno_ev_tsdisable 46
#define xeno_ev_mark 47
#define xeno_ev_watchdog 48
......
......@@ -39,12 +39,8 @@
/* Pod status flags */
#define XNRPRIO 0x00000002 /* Reverse priority scheme */
#define XNTIMED 0x00000004 /* Timer started */
#define XNTMSET 0x00000008 /* Pod time has been set */
#define XNTMPER 0x00000010 /* Periodic timing */
#define XNFATAL 0x00000020 /* Pod encountered a fatal error */
#define XNPIDLE 0x00000040 /* Pod is unavailable (initializing/shutting down) */
#define XNTLOCK 0x00000080 /* Timer lock pending */
#define XNFATAL 0x00000004 /* Pod encountered a fatal error */
#define XNPIDLE 0x00000008 /* Pod is unavailable (initializing/shutting down) */
/* Sched status flags */
#define XNKCOUT 0x80000000 /* Sched callout context */
......@@ -69,8 +65,6 @@
#define XNPOD_NORMAL_EXIT 0x0
#define XNPOD_FATAL_EXIT 0x1
#define XNPOD_DEFAULT_TICKHANDLER (&xnpod_announce_tick)
#define XNPOD_ALL_CPUS XNARCH_CPU_MASK_ALL
#define XNPOD_HEAPSIZE (CONFIG_XENO_OPT_SYS_HEAPSZ * 1024)
......@@ -123,17 +117,13 @@ typedef struct xnsched {
xnthread_t *runthread; /*!< Current thread (service or user). */
xnarch_cpumask_t resched; /*!< Mask of CPUs needing rescheduling. */
xnarch_cpumask_t resched; /*!< Mask of CPUs needing rescheduling. */
xnsched_queue_t readyq; /*!< Ready-to-run threads (prioritized). */
xntimerq_t timerqueue;
#ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
xntimer_t ptimer; /*!< Periodic timer. */
xnqueue_t timerwheel[XNTIMER_WHEELSIZE]; /*!< BSDish timer wheel. */
#endif /* CONFIG_XENO_OPT_TIMING_PERIODIC */
xntimerq_t timerqueue; /* !< Core timer queue. */
volatile unsigned inesting; /*!< Interrupt nesting level. */
volatile unsigned inesting; /*!< Interrupt nesting level. */
#ifdef CONFIG_XENO_HW_FPU
xnthread_t *fpuholder; /*!< Thread owning the current FPU context. */
......@@ -142,7 +132,7 @@ typedef struct xnsched {
#ifdef CONFIG_XENO_OPT_WATCHDOG
xntimer_t wdtimer; /*!< Watchdog timer object. */
int wdcount; /*!< Watchdog tick count. */
#endif /* CONFIG_XENO_OPT_WATCHDOG */
#endif /* CONFIG_XENO_OPT_WATCHDOG */
xnthread_t rootcb; /*!< Root thread control block. */
......@@ -150,7 +140,7 @@ typedef struct xnsched {
xnticks_t last_account_switch; /*!< Last account switch date (ticks). */
xnstat_runtime_t *current_account; /*!< Currently active account */
#endif /* CONFIG_XENO_OPT_STATS */
#endif /* CONFIG_XENO_OPT_STATS */
} xnsched_t;
......@@ -192,11 +182,6 @@ struct xnpod {
xnflags_t status; /*!< Status bitmask. */
xnticks_t jiffies; /*!< Periodic ticks elapsed since boot. */
xnticks_t wallclock_offset; /*!< Difference between wallclock time
and epoch in ticks. */
xntimer_t htimer; /*!< Host timer. */
xnsched_t sched[XNARCH_NR_CPUS]; /*!< Per-cpu scheduler slots. */
......@@ -215,26 +200,21 @@ struct xnpod {
int root_prio_base; /*!< Base priority of ROOT thread. */
u_long tickvalue; /*!< Tick duration (ns, 1 if aperiodic). */
u_long ticks2sec; /*!< Number of ticks per second (1e9
if aperiodic). */
int refcnt; /*!< Reference count. */
#ifdef __KERNEL__
atomic_counter_t timerlck; /*!< Timer lock depth. */
#endif /* __KERNEL__ */
#endif /* __KERNEL__ */
struct {
void (*settime) (xnticks_t newtime); /*!< Clock setting hook. */
void (*settime) (xntbase_t *tbase, xnticks_t newtime); /*!< Clock setting hook. */
int (*faulthandler) (xnarch_fltinfo_t *fltinfo); /*!< Trap/exception handler. */
int (*unload) (void); /*!< Unloading hook. */
} svctable; /*!< Table of overridable service entry points. */
#ifdef __XENO_SIM__
void (*schedhook) (xnthread_t *thread, xnflags_t mask); /*!< Internal scheduling hook. */
#endif /* __XENO_SIM__ */
#endif /* __XENO_SIM__ */
};
typedef struct xnpod xnpod_t;
......@@ -249,8 +229,6 @@ extern u_long nkschedlat;
extern u_long nktimerlat;
extern u_long nktickdef;
extern char *nkmsgbuf;
extern xnarch_cpumask_t nkaffinity;
......@@ -365,84 +343,63 @@ static inline void xnpod_renice_root(int prio)
#define xnpod_primary_p() \
(!(xnpod_asynch_p() || xnpod_root_p()))
#define xnpod_secondary_p() xnpod_root_p()
#define xnpod_secondary_p() xnpod_root_p()
#define xnpod_idle_p() xnpod_root_p()
#define xnpod_idle_p() xnpod_root_p()
#define xnpod_timeset_p() (!!testbits(nkpod->status,XNTMSET))
int xnpod_init(xnpod_t *pod,
int minpri,
int maxpri,
xnflags_t flags);
static inline u_long xnpod_get_ticks2sec(void)
{
return nkpod->ticks2sec;
}
int xnpod_enable_timesource(void);
static inline u_long xnpod_get_tickval(void)
{
/* Returns the duration of a tick in nanoseconds */
return nkpod->tickvalue;
}
static inline xntime_t xnpod_ticks2ns(xnticks_t ticks)
{
/* Convert a count of ticks in nanoseconds */
#ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
return ticks * xnpod_get_tickval();
#else /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
return ticks;
#endif /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
}
static inline xnticks_t xnpod_ns2ticks(xntime_t t)
{
#ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
return xnarch_ulldiv(t, xnpod_get_tickval(), NULL);
#else /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
return t;
#endif /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
}
int xnpod_init(xnpod_t *pod, int minpri, int maxpri, xnflags_t flags);
int xnpod_start_timer(u_long nstick, xnisr_t tickhandler);
void xnpod_stop_timer(void);
int xnpod_reset_timer(void);
void xnpod_disable_timesource(void);
void xnpod_shutdown(int xtype);
int xnpod_init_thread(xnthread_t *thread,
xntbase_t *tbase,
const char *name,
int prio, xnflags_t flags, unsigned stacksize);
int prio,
xnflags_t flags,
unsigned stacksize);
int xnpod_start_thread(xnthread_t *thread,
xnflags_t mode,
int imask,
xnarch_cpumask_t affinity,
void (*entry) (void *cookie), void *cookie);
void (*entry) (void *cookie),
void *cookie);
void xnpod_restart_thread(xnthread_t *thread);
void xnpod_delete_thread(xnthread_t *thread);
xnflags_t xnpod_set_thread_mode(xnthread_t *thread,
xnflags_t clrmask, xnflags_t setmask);
xnflags_t clrmask,
xnflags_t setmask);
void xnpod_suspend_thread(xnthread_t *thread,
xnflags_t mask,
xnticks_t timeout, int mode,
xnticks_t timeout,
int mode,
struct xnsynch *resource);
void xnpod_resume_thread(xnthread_t *thread, xnflags_t mask);
void xnpod_resume_thread(xnthread_t *thread,
xnflags_t mask);
int xnpod_unblock_thread(xnthread_t *thread);
void xnpod_renice_thread(xnthread_t *thread, int prio);
void xnpod_renice_thread(xnthread_t *thread,
int prio);
int xnpod_migrate_thread(int cpu);
void xnpod_rotate_readyq(int prio);
void xnpod_do_rr(void);
void xnpod_schedule(void);
void xnpod_dispatch_signals(void);
......@@ -479,14 +436,16 @@ void xnpod_activate_rr(xnticks_t quantum);
void xnpod_deactivate_rr(void);
void xnpod_set_time(xnticks_t newtime);
void xnpod_set_time(xntbase_t *tbase,
xnticks_t newtime);
int xnpod_set_thread_periodic(xnthread_t *thread,
xnticks_t idate, xnticks_t period);
xnticks_t idate,
xnticks_t period);
int xnpod_wait_thread_period(unsigned long *overruns_r);
xnticks_t xnpod_get_time(void);
xnticks_t xnpod_get_time(xntbase_t *tbase);
static inline xntime_t xnpod_get_cpu_time(void)
{
......
......@@ -261,7 +261,13 @@ typedef struct xnhook {
#define xnthread_handle(thread) ((thread)->registry.handle)
#define xnthread_set_magic(thread,m) do { (thread)->magic = (m); } while(0)
#define xnthread_get_magic(thread) ((thread)->magic)
#ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
#define xnthread_time_base(thread) ((thread)->rtimer.base)
#else /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
#define xnthread_time_base(thread) (&nktbase)
#endif /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
#define xnthread_signaled_p(thread) ((thread)->signals != 0)
#define xnthread_timed_p(thread) (!!testbits(xnthread_time_base(thread)->status, XNTBRUN))
#define xnthread_user_task(thread) xnarch_user_task(xnthread_archtcb(thread))
#define xnthread_user_pid(thread) \
(xnthread_test_state((thread),XNROOT) || !xnthread_user_task(thread) ? \
......@@ -272,6 +278,7 @@ extern "C" {
#endif
int xnthread_init(xnthread_t *thread,
xntbase_t *tbase,
const char *name,
int prio,
xnflags_t flags,
......
/*
* Copyright (C) 2006,2007 Philippe Gerum <rpm@xenomai.org>.
*
* 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; 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_NUCLEUS_TIMEBASE_H
#define _XENO_NUCLEUS_TIMEBASE_H
#include <nucleus/queue.h>
#if defined(__KERNEL__) || defined(__XENO_SIM__)
struct xntimer;
typedef struct xntbops {
int (*start_timer)(struct xntimer *timer,
xnticks_t value,
xnticks_t interval,
int mode);
void (*stop_timer)(struct xntimer *timer);
xnticks_t (*get_timer_date)(struct xntimer *timer);
xnticks_t (*get_timer_timeout)(struct xntimer *timer);
xnticks_t (*get_timer_interval)(struct xntimer *timer);
xnticks_t (*get_timer_raw_expiry)(struct xntimer *timer);
void (*move_timer)(struct xntimer *timer);
} xntbops_t;
#define XNTBRUN 0x00000001 /* Time base is running. */
#define XNTBSET 0x00000002 /* Time set in time base. */
#define XNTBLCK 0x00000004 /* Time base is locked. */
typedef struct xntbase {
struct xntbops *ops; /*!< Time base operations. */
xnticks_t jiffies; /*!< Ticks elapsed since init (remains null if aperiodic). */
void (*hook)(void); /*!< Hook routine called upon tick. */
xnticks_t wallclock_offset; /*!< (Wallclock time - epoch) in ticks. */
u_long tickvalue; /*!< Tick duration (ns, 1 if aperiodic). */
u_long ticks2sec; /*!< Number of ticks per second. */
u_long status; /*!< Status information. */
const char *name; /* !< Name of time base. */
xnholder_t link;
#define link2tbase(ln) container_of(ln, xntbase_t, link)
} xntbase_t;
#define xntbase_timeset_p(base) (!!testbits((base)->status,XNTBSET))
#ifdef __cplusplus
extern "C" {
#endif
extern xntbase_t nktbase;
extern xnqueue_t nktimebaseq;
static inline u_long xntbase_get_ticks2sec(xntbase_t *base)
{
return base->ticks2sec;
}
static inline u_long xntbase_get_tickval(xntbase_t *base)
{
/* Returns the duration of a tick in nanoseconds */
return base->tickvalue;
}
static inline void xntbase_set_hook(xntbase_t *base, void (*hook)(void))
{
base->hook = hook;
}
static inline int xntbase_enabled_p(xntbase_t *base)
{
return !!(base->status & XNTBRUN);
}
#ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
static inline xntime_t xntbase_ticks2ns(xntbase_t *base, xnticks_t ticks)
{
/* Convert a count of ticks in nanoseconds */
return ticks * xntbase_get_tickval(base);
}
static inline xnticks_t xntbase_ns2ticks(xntbase_t *base, xntime_t t)
{
return xnarch_ulldiv(t, xntbase_get_tickval(base), NULL);
}
static inline int xntbase_periodic_p(xntbase_t *base)
{
return base->tickvalue != 1;
}
static inline int xntbase_master_p(xntbase_t *base)
{
return base == &nktbase;
}
static inline xnticks_t xntbase_get_jiffies(xntbase_t *base)
{
return base->jiffies;
}
static inline xnticks_t xntbase_get_rawclock(xntbase_t *base)
{
return xntbase_get_jiffies(base);
}
int xntbase_alloc(const char *name,
u_long period,
xntbase_t **basep);
void xntbase_free(xntbase_t *base);
int xntbase_update(xntbase_t *base,
u_long period);
int xntbase_switch(const char *name,
u_long period,
xntbase_t **basep);
void xntbase_start(xntbase_t *base);
void xntbase_stop(xntbase_t *base);
void xntbase_tick(xntbase_t *base);
#else /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
void xntimer_tick_aperiodic(void);
static inline xntime_t xntbase_ticks2ns(xntbase_t *base, xnticks_t ticks)
{
return ticks;
}
static inline xnticks_t xntbase_ns2ticks(xntbase_t *base, xntime_t t)
{
return t;
}
static inline int xntbase_periodic_p(xntbase_t *base)
{
return 0;
}
static inline int xntbase_master_p(xntbase_t *base)
{
return 1;
}
static inline xnticks_t xntbase_get_jiffies(xntbase_t *base)
{
return xnarch_get_cpu_time();
}
static inline xnticks_t xntbase_get_rawclock(xntbase_t *base)
{
return xnarch_get_cpu_tsc();
}
static inline int xntbase_alloc(const char *name, u_long period, xntbase_t **basep)
{
*basep = &nktbase;
return 0;
}
static inline void xntbase_free(xntbase_t *base)
{
}
static inline int xntbase_update(xntbase_t *base, u_long period)
{
return 0;
}
static inline int xntbase_switch(const char *name, u_long period, xntbase_t **basep)
{
return period == XN_APERIODIC_TICK ? 0 : -ENODEV;
}
static inline void xntbase_start(xntbase_t *base)
{
}
static inline void xntbase_stop(xntbase_t *base)
{
}
static inline void xntbase_tick(xntbase_t *base)
{
xntimer_tick_aperiodic();
}
#endif /* !CONFIG_XENO_OPT_TIMING_PERIODIC */