Hello Darren, Juergen and Ingo,
> > All I need is one IRQ at priority 51, all other can still run at 50. And I
> > don't want to search at system's runtime for the right PID of driver's
> > thread to set its priority via "chrt". There is no user at this system, its
> > an embedded one.
>
> It seems reasonable then, for such a specialized case, to consider Remy's
> reply to my previous mail:
>
> "To suit my needs, I did this by just patching the kernel thread
> priorities at the places where they are started.
Attached I have put my patch to change the priorities of the
soft-irq's and the IRQ threads.
Maybe Juergen can use it so suit his needs. (Sorry for attaching
instead of inlining, but I have not find a way to inline a patch
without corrupting it while using Gmail from within Firefox)
But, I think that the mechanism to change the soft-irq priorities can
be integrated in the mainline RT-patch, I have modified the
softirq_info struct with the soft-irq thread names such that it also
contains the thread priority per soft-irq. For customisation it is
easier to adapt this struct, than to apply the entire patch over and
over. Until now the code seems to change that frequently that I have
to reimplement this patch over and over...
Maybe Ingo can look at it, and find a way to implement it more
generic? (In the softirq_info struct we could default set all prios
back to 50, and than from functional point of view there will be no
change for other RT-patch users, but makes Embedded-users life easier.
While looking at the IRQ-threads: Notice that setting all IRQ-threads
priorities to 50 with SCHED_FIFO is a bit strange to begin with,
because on a non-RT kernel all IRQ's have different priorities and a
higher prio irq can preempt a lower prio one. (on X86) The current
implementation will not preempt another irq-thread due to the same
prios and fifo scheduling.
The implementation I have in this patch follows the original behaviour
more closely, but changing that also could lead to some discussion...
Kind Regards,
Remy
This patch changes the soft-irq priority for all kernel daemon threads
like Interrupt threads and soft-irqs to match them with our
applications.
Signed-off-by: Remy Bohmer <[EMAIL PROTECTED]>
---
kernel/irq/manage.c | 12 +++++++++--
kernel/softirq.c | 53 +++++++++++++++++++++++++++++++++-------------------
2 files changed, 44 insertions(+), 21 deletions(-)
Index: linux-2.6.22/kernel/irq/manage.c
===================================================================
--- linux-2.6.22.orig/kernel/irq/manage.c 2007-07-24 16:40:15.000000000 +0200
+++ linux-2.6.22/kernel/irq/manage.c 2007-07-24 16:46:52.000000000 +0200
@@ -757,10 +757,13 @@ static void do_hardirq(struct irq_desc *
wake_up(&desc->wait_for_handler);
}
+#define base_irq_prio 45
+
static int do_irqd(void * __desc)
{
struct sched_param param = { 0, };
struct irq_desc *desc = __desc;
+ int irq = desc - irq_desc;
#ifdef CONFIG_SMP
cpumask_t cpus_allowed, mask;
@@ -776,12 +779,17 @@ static int do_irqd(void * __desc)
current->flags |= PF_NOFREEZE | PF_HARDIRQ;
/*
- * Set irq thread priority to SCHED_FIFO/50:
+ * Use a custom irq thread priority mechanism:
*/
- param.sched_priority = MAX_USER_RT_PRIO/2;
+ param.sched_priority = base_irq_prio - irq;
+ if (param.sched_priority < 1)
+ param.sched_priority = 1;
sys_sched_setscheduler(current->pid, SCHED_FIFO, ¶m);
+ printk(KERN_INFO "[IRQ-%d] started with prio:%i\n",
+ irq, param.sched_priority);
+
while (!kthread_should_stop()) {
local_irq_disable_nort();
do {
Index: linux-2.6.22/kernel/softirq.c
===================================================================
--- linux-2.6.22.orig/kernel/softirq.c 2007-07-24 16:40:15.000000000 +0200
+++ linux-2.6.22/kernel/softirq.c 2007-07-24 16:49:05.000000000 +0200
@@ -764,10 +764,30 @@ EXPORT_SYMBOL(tasklet_unlock_wait);
#endif
+static struct
+{
+ const char *name;
+ const int prio;
+} softirq_info [] =
+{
+ [HI_SOFTIRQ] = {"high", 33},
+ [SCHED_SOFTIRQ] = {"sched", 73},
+ [TIMER_SOFTIRQ] = {"timer", 72},
+ [NET_TX_SOFTIRQ] = {"net-tx", 20},
+ [NET_RX_SOFTIRQ] = {"net-rx", 20},
+ [BLOCK_SOFTIRQ] = {"block", 32},
+ [TASKLET_SOFTIRQ] = {"tasklet", 31},
+#ifdef CONFIG_HIGH_RES_TIMERS
+ [HRTIMER_SOFTIRQ] = {"hrtimer", 72},
+#endif
+ [RCU_SOFTIRQ] = {"rcu", 20}
+};
+
static int ksoftirqd(void * __data)
{
- struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2 };
struct softirqdata *data = __data;
+ struct sched_param param = {
+ .sched_priority = softirq_info[data->nr].prio };
u32 softirq_mask = (1 << data->nr);
struct softirq_action *h;
int cpu = data->cpu;
@@ -776,6 +796,16 @@ static int ksoftirqd(void * __data)
init_waitqueue_head(&data->wait);
#endif
+ if ( (param.sched_priority < 1) ||
+ (param.sched_priority > MAX_RT_PRIO) ) {
+ BUG();
+ param.sched_priority = 1;
+ }
+
+ printk(KERN_INFO "softirq-%s/%lu started up, pid:%d, RT prio: %d.\n",
+ softirq_info[data->nr].name, data->cpu,
+ current->pid, param.sched_priority);
+
sys_sched_setscheduler(current->pid, SCHED_FIFO, ¶m);
current->flags |= PF_NOFREEZE | PF_SOFTIRQ;
@@ -906,21 +936,6 @@ void takeover_tasklets(unsigned int cpu)
}
#endif /* CONFIG_HOTPLUG_CPU */
-static const char *softirq_names [] =
-{
- [HI_SOFTIRQ] = "high",
- [SCHED_SOFTIRQ] = "sched",
- [TIMER_SOFTIRQ] = "timer",
- [NET_TX_SOFTIRQ] = "net-tx",
- [NET_RX_SOFTIRQ] = "net-rx",
- [BLOCK_SOFTIRQ] = "block",
- [TASKLET_SOFTIRQ] = "tasklet",
-#ifdef CONFIG_HIGH_RES_TIMERS
- [HRTIMER_SOFTIRQ] = "hrtimer",
-#endif
- [RCU_SOFTIRQ] = "rcu",
-};
-
static int __cpuinit cpu_callback(struct notifier_block *nfb,
unsigned long action,
void *hcpu)
@@ -938,9 +953,9 @@ static int __cpuinit cpu_callback(struct
}
for (i = 0; i < MAX_SOFTIRQ; i++) {
p = kthread_create(ksoftirqd,
- &per_cpu(ksoftirqd, hotcpu)[i],
- "softirq-%s/%d", softirq_names[i],
- hotcpu);
+ &per_cpu(ksoftirqd, hotcpu)[i],
+ "softirq-%s/%d", softirq_info[i].name,
+ hotcpu);
if (IS_ERR(p)) {
printk("ksoftirqd %d for %i failed\n", i,
hotcpu);