aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/litmus_softirq.c
diff options
context:
space:
mode:
Diffstat (limited to 'litmus/litmus_softirq.c')
-rw-r--r--litmus/litmus_softirq.c158
1 files changed, 83 insertions, 75 deletions
diff --git a/litmus/litmus_softirq.c b/litmus/litmus_softirq.c
index d1ea833dc8c4..dbefcb560063 100644
--- a/litmus/litmus_softirq.c
+++ b/litmus/litmus_softirq.c
@@ -1,27 +1,14 @@
1/* much copied shamelessly from Linux's softirq.c 1/* much copied shamelessly from Linux's softirq.c
2 as well as PREEMPT_RT's softirq.c */ 2 as well as PREEMPT_RT's softirq.c */
3 3
4#include <linux/module.h>
5#include <linux/kernel_stat.h>
6#include <linux/interrupt.h> 4#include <linux/interrupt.h>
7#include <linux/init.h>
8#include <linux/mm.h>
9#include <linux/notifier.h>
10#include <linux/percpu.h> 5#include <linux/percpu.h>
11#include <linux/cpu.h> 6#include <linux/cpu.h>
12#include <linux/freezer.h>
13#include <linux/kthread.h> 7#include <linux/kthread.h>
14#include <linux/rcupdate.h>
15#include <linux/ftrace.h> 8#include <linux/ftrace.h>
16#include <linux/smp.h> 9#include <linux/smp.h>
17#include <linux/tick.h>
18#include <linux/slab.h> 10#include <linux/slab.h>
19 11
20#define CREATE_TRACE_POINTS
21#include <trace/events/irq.h>
22
23#include <asm/irq.h>
24
25#include <litmus/litmus.h> 12#include <litmus/litmus.h>
26#include <litmus/jobs.h> 13#include <litmus/jobs.h>
27#include <litmus/sched_plugin.h> 14#include <litmus/sched_plugin.h>
@@ -44,13 +31,12 @@ struct tasklet_head
44 struct tasklet_struct **tail; 31 struct tasklet_struct **tail;
45}; 32};
46 33
47// sys_sched_setscheduler(current->pid, SCHED_FIFO, &param);
48// TODO: current->extra_flags |= PFE_SOFTIRQ;
49
50struct klitirqd_info 34struct klitirqd_info
51{ 35{
52 struct task_struct* klitirqd; 36 struct task_struct* klitirqd;
53 raw_spinlock_t lock; 37 raw_spinlock_t lock;
38
39 u32 pending;
54 struct tasklet_head pending_tasklets; 40 struct tasklet_head pending_tasklets;
55 struct tasklet_head pending_tasklets_hi; 41 struct tasklet_head pending_tasklets_hi;
56}; 42};
@@ -79,41 +65,22 @@ inline unsigned int klitirqd_id(struct task_struct* tsk)
79 65
80inline static u32 litirq_pending_hi_irqoff(struct klitirqd_info* which) 66inline static u32 litirq_pending_hi_irqoff(struct klitirqd_info* which)
81{ 67{
82 u32 pending = 0; 68 return (which->pending & LIT_TASKLET_HI);
83
84 if(which->pending_tasklets_hi.head != NULL)
85 {
86 pending = LIT_TASKLET_HI;
87 }
88
89 return pending;
90}; 69};
91 70
92inline static u32 litirq_pending_low_irqoff(struct klitirqd_info* which) 71inline static u32 litirq_pending_low_irqoff(struct klitirqd_info* which)
93{ 72{
94 u32 pending = 0; 73 return (which->pending & LIT_TASKLET_LOW);
95
96 if(which->pending_tasklets.head != NULL)
97 {
98 pending = LIT_TASKLET_LOW;
99 }
100
101 return pending;
102}; 74};
103 75
104 76
105static u32 litirq_pending_irqoff(struct klitirqd_info* which) 77inline static u32 litirq_pending_irqoff(struct klitirqd_info* which)
106{ 78{
107 u32 pending = 0; 79 return(which->pending);
108
109 pending |= litirq_pending_hi_irqoff(which);
110 pending |= litirq_pending_low_irqoff(which);
111
112 return pending;
113}; 80};
114 81
115 82
116static u32 litirq_pending(struct klitirqd_info* which) 83inline static u32 litirq_pending(struct klitirqd_info* which)
117{ 84{
118 unsigned long flags; 85 unsigned long flags;
119 u32 pending; 86 u32 pending;
@@ -276,6 +243,13 @@ void trigger_litirqs(struct task_struct* tsk)
276} 243}
277#endif 244#endif
278 245
246/* forward declarations */
247static void ___litmus_tasklet_schedule(struct tasklet_struct *t,
248 struct klitirqd_info *which,
249 int wakeup);
250static void ___litmus_tasklet_hi_schedule(struct tasklet_struct *t,
251 struct klitirqd_info *which,
252 int wakeup);
279 253
280static void do_lit_tasklet(struct klitirqd_info* which, 254static void do_lit_tasklet(struct klitirqd_info* which,
281 struct tasklet_head* pending_tasklets) 255 struct tasklet_head* pending_tasklets)
@@ -285,11 +259,14 @@ static void do_lit_tasklet(struct klitirqd_info* which,
285 259
286 raw_spin_lock_irqsave(&which->lock, flags); 260 raw_spin_lock_irqsave(&which->lock, flags);
287 261
288 /* copy out the tasklets for our private use. */ 262 /* copy out the tasklets for our private use. */
289 list = pending_tasklets->head; 263 list = pending_tasklets->head;
290 pending_tasklets->head = NULL; 264 pending_tasklets->head = NULL;
291 pending_tasklets->tail = &pending_tasklets->head; 265 pending_tasklets->tail = &pending_tasklets->head;
292 266 which->pending &= (pending_tasklets == &which->pending_tasklets) ?
267 ~LIT_TASKLET_LOW :
268 ~LIT_TASKLET_HI;
269
293 raw_spin_unlock_irqrestore(&which->lock, flags); 270 raw_spin_unlock_irqrestore(&which->lock, flags);
294 271
295 while(list) 272 while(list)
@@ -314,17 +291,13 @@ static void do_lit_tasklet(struct klitirqd_info* which,
314 tasklet_unlock(t); 291 tasklet_unlock(t);
315 } 292 }
316 293
317 /* couldn't process tasklet. put it back at the end of the main queue. */
318 TRACE_CUR("%s: Could not invoke tasklet. Requeuing.\n", __FUNCTION__); 294 TRACE_CUR("%s: Could not invoke tasklet. Requeuing.\n", __FUNCTION__);
319 295
320 t->next = NULL; 296 /* couldn't process tasklet. put it back at the end of the queue. */
321 297 if(pending_tasklets == &which->pending_tasklets)
322 raw_spin_lock_irqsave(&which->lock, flags); 298 ___litmus_tasklet_schedule(t, which, 0);
323 299 else
324 *(pending_tasklets->tail) = t; 300 ___litmus_tasklet_hi_schedule(t, which, 0);
325 pending_tasklets->tail = &t->next;
326
327 raw_spin_unlock_irqrestore(&which->lock, flags);
328 } 301 }
329} 302}
330 303
@@ -519,6 +492,8 @@ void spawn_klitirqd(void)
519 /* init the tasklet queues */ 492 /* init the tasklet queues */
520 for(i = 0; i < NR_LITMUS_SOFTIRQD; ++i) 493 for(i = 0; i < NR_LITMUS_SOFTIRQD; ++i)
521 { 494 {
495 klitirqds[i].pending = 0;
496
522 klitirqds[i].pending_tasklets.head = NULL; 497 klitirqds[i].pending_tasklets.head = NULL;
523 klitirqds[i].pending_tasklets.tail = &klitirqds[i].pending_tasklets.head; 498 klitirqds[i].pending_tasklets.tail = &klitirqds[i].pending_tasklets.head;
524 499
@@ -561,12 +536,38 @@ int klitirqd_is_ready(void)
561 return(atomic_read(&num_ready_klitirqds) == NR_LITMUS_SOFTIRQD); 536 return(atomic_read(&num_ready_klitirqds) == NR_LITMUS_SOFTIRQD);
562} 537}
563 538
539int klitirqd_is_dead(void)
540{
541 return(atomic_read(&num_ready_klitirqds) == 0);
542}
564 543
565 544
566void __litmus_tasklet_schedule(struct tasklet_struct *t, unsigned int k_id) 545
546static void ___litmus_tasklet_schedule(struct tasklet_struct *t,
547 struct klitirqd_info *which,
548 int wakeup)
567{ 549{
568 unsigned long flags; 550 unsigned long flags;
551
552 t->next = NULL;
553
554 raw_spin_lock_irqsave(&which->lock, flags);
569 555
556 *(which->pending_tasklets.tail) = t;
557 which->pending_tasklets.tail = &t->next;
558
559 which->pending |= LIT_TASKLET_LOW;
560
561 if(wakeup)
562 {
563 wakeup_litirqd_locked(which); /* wake up the klitirqd */
564 }
565
566 raw_spin_unlock_irqrestore(&which->lock, flags);
567}
568
569void __litmus_tasklet_schedule(struct tasklet_struct *t, unsigned int k_id)
570{
570 if(unlikely((t->owner == NULL) || !is_realtime(t->owner))) 571 if(unlikely((t->owner == NULL) || !is_realtime(t->owner)))
571 { 572 {
572 TRACE("%s: No owner associated with this tasklet!\n", __FUNCTION__); 573 TRACE("%s: No owner associated with this tasklet!\n", __FUNCTION__);
@@ -579,24 +580,37 @@ void __litmus_tasklet_schedule(struct tasklet_struct *t, unsigned int k_id)
579 BUG(); 580 BUG();
580 } 581 }
581 582
582 raw_spin_lock_irqsave(&klitirqds[k_id].lock, flags); 583 ___litmus_tasklet_schedule(t, &klitirqds[k_id], 1);
583
584 t->next = NULL;
585 *klitirqds[k_id].pending_tasklets.tail = t;
586 klitirqds[k_id].pending_tasklets.tail = &t->next;
587
588 wakeup_litirqd_locked(&klitirqds[k_id]); /* wake up the klitirqd */
589
590 raw_spin_unlock_irqrestore(&klitirqds[k_id].lock, flags);
591} 584}
592 585
593EXPORT_SYMBOL(__litmus_tasklet_schedule); 586EXPORT_SYMBOL(__litmus_tasklet_schedule);
594 587
595 588
596void __litmus_tasklet_hi_schedule(struct tasklet_struct *t, unsigned int k_id) 589static void ___litmus_tasklet_hi_schedule(struct tasklet_struct *t,
590 struct klitirqd_info *which,
591 int wakeup)
597{ 592{
598 unsigned long flags; 593 unsigned long flags;
594
595 t->next = NULL;
596
597 raw_spin_lock_irqsave(&which->lock, flags);
598
599 *(which->pending_tasklets_hi.tail) = t;
600 which->pending_tasklets_hi.tail = &t->next;
599 601
602 which->pending |= LIT_TASKLET_HI;
603
604 if(wakeup)
605 {
606 wakeup_litirqd_locked(which); /* wake up the klitirqd */
607 }
608
609 raw_spin_unlock_irqrestore(&which->lock, flags);
610}
611
612void __litmus_tasklet_hi_schedule(struct tasklet_struct *t, unsigned int k_id)
613{
600 if(unlikely((t->owner == NULL) || !is_realtime(t->owner))) 614 if(unlikely((t->owner == NULL) || !is_realtime(t->owner)))
601 { 615 {
602 TRACE("%s: No owner associated with this tasklet!\n", __FUNCTION__); 616 TRACE("%s: No owner associated with this tasklet!\n", __FUNCTION__);
@@ -609,15 +623,7 @@ void __litmus_tasklet_hi_schedule(struct tasklet_struct *t, unsigned int k_id)
609 BUG(); 623 BUG();
610 } 624 }
611 625
612 raw_spin_lock_irqsave(&klitirqds[k_id].lock, flags); 626 ___litmus_tasklet_hi_schedule(t, &klitirqds[k_id], 1);
613
614 t->next = NULL;
615 *klitirqds[k_id].pending_tasklets_hi.tail = t;
616 klitirqds[k_id].pending_tasklets_hi.tail = &t->next;
617
618 wakeup_litirqd_locked(&klitirqds[k_id]); /* wake up the klitirqd */
619
620 raw_spin_unlock_irqrestore(&klitirqds[k_id].lock, flags);
621} 627}
622 628
623EXPORT_SYMBOL(__litmus_tasklet_hi_schedule); 629EXPORT_SYMBOL(__litmus_tasklet_hi_schedule);
@@ -642,7 +648,9 @@ void __litmus_tasklet_hi_schedule_first(struct tasklet_struct *t, unsigned int k
642 raw_spin_lock(&klitirqds[k_id].lock); 648 raw_spin_lock(&klitirqds[k_id].lock);
643 649
644 t->next = klitirqds[k_id].pending_tasklets_hi.head; 650 t->next = klitirqds[k_id].pending_tasklets_hi.head;
645 klitirqds[k_id].pending_tasklets_hi.head = t; 651 klitirqds[k_id].pending_tasklets_hi.head = t;
652
653 klitirqds[k_id].pending |= LIT_TASKLET_HI;
646 654
647 wakeup_litirqd_locked(&klitirqds[k_id]); /* wake up the klitirqd */ 655 wakeup_litirqd_locked(&klitirqds[k_id]); /* wake up the klitirqd */
648 656