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 <linux@xxxxxxxxxx> --- 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);