Merge branch 'core-fixes-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'core-fixes-for-linus-2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: softirq: introduce tasklet_hrtimer infrastructure
This commit is contained in:
commit
612e900c28
2 changed files with 89 additions and 1 deletions
|
@ -14,6 +14,7 @@
|
||||||
#include <linux/irqflags.h>
|
#include <linux/irqflags.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
|
#include <linux/hrtimer.h>
|
||||||
|
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
@ -519,6 +520,31 @@ extern void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu);
|
||||||
extern void tasklet_init(struct tasklet_struct *t,
|
extern void tasklet_init(struct tasklet_struct *t,
|
||||||
void (*func)(unsigned long), unsigned long data);
|
void (*func)(unsigned long), unsigned long data);
|
||||||
|
|
||||||
|
struct tasklet_hrtimer {
|
||||||
|
struct hrtimer timer;
|
||||||
|
struct tasklet_struct tasklet;
|
||||||
|
enum hrtimer_restart (*function)(struct hrtimer *);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void
|
||||||
|
tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
|
||||||
|
enum hrtimer_restart (*function)(struct hrtimer *),
|
||||||
|
clockid_t which_clock, enum hrtimer_mode mode);
|
||||||
|
|
||||||
|
static inline
|
||||||
|
int tasklet_hrtimer_start(struct tasklet_hrtimer *ttimer, ktime_t time,
|
||||||
|
const enum hrtimer_mode mode)
|
||||||
|
{
|
||||||
|
return hrtimer_start(&ttimer->timer, time, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void tasklet_hrtimer_cancel(struct tasklet_hrtimer *ttimer)
|
||||||
|
{
|
||||||
|
hrtimer_cancel(&ttimer->timer);
|
||||||
|
tasklet_kill(&ttimer->tasklet);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Autoprobing for irqs:
|
* Autoprobing for irqs:
|
||||||
*
|
*
|
||||||
|
|
|
@ -345,7 +345,9 @@ void open_softirq(int nr, void (*action)(struct softirq_action *))
|
||||||
softirq_vec[nr].action = action;
|
softirq_vec[nr].action = action;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tasklets */
|
/*
|
||||||
|
* Tasklets
|
||||||
|
*/
|
||||||
struct tasklet_head
|
struct tasklet_head
|
||||||
{
|
{
|
||||||
struct tasklet_struct *head;
|
struct tasklet_struct *head;
|
||||||
|
@ -493,6 +495,66 @@ void tasklet_kill(struct tasklet_struct *t)
|
||||||
|
|
||||||
EXPORT_SYMBOL(tasklet_kill);
|
EXPORT_SYMBOL(tasklet_kill);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tasklet_hrtimer
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The trampoline is called when the hrtimer expires. If this is
|
||||||
|
* called from the hrtimer interrupt then we schedule the tasklet as
|
||||||
|
* the timer callback function expects to run in softirq context. If
|
||||||
|
* it's called in softirq context anyway (i.e. high resolution timers
|
||||||
|
* disabled) then the hrtimer callback is called right away.
|
||||||
|
*/
|
||||||
|
static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer)
|
||||||
|
{
|
||||||
|
struct tasklet_hrtimer *ttimer =
|
||||||
|
container_of(timer, struct tasklet_hrtimer, timer);
|
||||||
|
|
||||||
|
if (hrtimer_is_hres_active(timer)) {
|
||||||
|
tasklet_hi_schedule(&ttimer->tasklet);
|
||||||
|
return HRTIMER_NORESTART;
|
||||||
|
}
|
||||||
|
return ttimer->function(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper function which calls the hrtimer callback from
|
||||||
|
* tasklet/softirq context
|
||||||
|
*/
|
||||||
|
static void __tasklet_hrtimer_trampoline(unsigned long data)
|
||||||
|
{
|
||||||
|
struct tasklet_hrtimer *ttimer = (void *)data;
|
||||||
|
enum hrtimer_restart restart;
|
||||||
|
|
||||||
|
restart = ttimer->function(&ttimer->timer);
|
||||||
|
if (restart != HRTIMER_NORESTART)
|
||||||
|
hrtimer_restart(&ttimer->timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks
|
||||||
|
* @ttimer: tasklet_hrtimer which is initialized
|
||||||
|
* @function: hrtimer callback funtion which gets called from softirq context
|
||||||
|
* @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME)
|
||||||
|
* @mode: hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL)
|
||||||
|
*/
|
||||||
|
void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
|
||||||
|
enum hrtimer_restart (*function)(struct hrtimer *),
|
||||||
|
clockid_t which_clock, enum hrtimer_mode mode)
|
||||||
|
{
|
||||||
|
hrtimer_init(&ttimer->timer, which_clock, mode);
|
||||||
|
ttimer->timer.function = __hrtimer_tasklet_trampoline;
|
||||||
|
tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline,
|
||||||
|
(unsigned long)ttimer);
|
||||||
|
ttimer->function = function;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(tasklet_hrtimer_init);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remote softirq bits
|
||||||
|
*/
|
||||||
|
|
||||||
DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
|
DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
|
||||||
EXPORT_PER_CPU_SYMBOL(softirq_work_list);
|
EXPORT_PER_CPU_SYMBOL(softirq_work_list);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue