aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2011-02-14 18:07:17 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2011-02-14 18:31:52 -0500
commit151977577ad96d8c614ddbd9df480c89cd98a1dc (patch)
tree74d5c80222af1ab69c1651b079c7fd22a74f54bb
parent08b72aceacca166015d518738f9e300546b969ef (diff)
A few small enhacements to litmus softirqs and added framework
for managing the nvidia module information.
-rw-r--r--include/litmus/litmus_softirq.h13
-rw-r--r--include/litmus/nvidia_info.h13
-rw-r--r--litmus/Kconfig9
-rw-r--r--litmus/Makefile1
-rw-r--r--litmus/litmus_softirq.c158
-rw-r--r--litmus/nvidia_info.c55
-rw-r--r--litmus/sched_gsn_edf.c8
7 files changed, 180 insertions, 77 deletions
diff --git a/include/litmus/litmus_softirq.h b/include/litmus/litmus_softirq.h
index 6d1f85c2e093..712c8119ae15 100644
--- a/include/litmus/litmus_softirq.h
+++ b/include/litmus/litmus_softirq.h
@@ -1,3 +1,6 @@
1#ifndef __LITMUS_SOFTIRQ_H
2#define __LITMUS_SOFTIRQ_H
3
1#include <linux/interrupt.h> 4#include <linux/interrupt.h>
2 5
3/* 6/*
@@ -57,8 +60,12 @@ void kill_klitirqd(void);
57 to handle tasklets. 0, otherwise.*/ 60 to handle tasklets. 0, otherwise.*/
58int klitirqd_is_ready(void); 61int klitirqd_is_ready(void);
59 62
63/* Returns 1 if no NR_LITMUS_SOFTIRQD klitirqs are ready
64 to handle tasklets. 0, otherwise.*/
65int klitirqd_is_dead(void);
66
60 67
61void __litmus_tasklet_schedule( 68extern void __litmus_tasklet_schedule(
62 struct tasklet_struct *t, 69 struct tasklet_struct *t,
63 unsigned int k_id); 70 unsigned int k_id);
64 71
@@ -96,4 +103,6 @@ static inline void litmus_tasklet_hi_schedule_first(
96{ 103{
97 if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) 104 if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
98 __litmus_tasklet_hi_schedule_first(t, k_id); 105 __litmus_tasklet_hi_schedule_first(t, k_id);
99} \ No newline at end of file 106}
107
108#endif \ No newline at end of file
diff --git a/include/litmus/nvidia_info.h b/include/litmus/nvidia_info.h
new file mode 100644
index 000000000000..f28d8f0a7f40
--- /dev/null
+++ b/include/litmus/nvidia_info.h
@@ -0,0 +1,13 @@
1#ifndef __LITMUS_NVIDIA_H
2#define __LITMUS_NVIDIA_H
3
4#include <litmus/litmus_softirq.h>
5
6int init_nvidia_info(void);
7
8int is_nvidia_func(void *func);
9
10int is_nvidia_in_callstack(void);
11
12
13#endif
diff --git a/litmus/Kconfig b/litmus/Kconfig
index 58137f3e374e..42c5ff67c8c1 100644
--- a/litmus/Kconfig
+++ b/litmus/Kconfig
@@ -205,6 +205,15 @@ config NR_LITMUS_SOFTIRQD
205 help 205 help
206 Should be <= to the number of CPUs in your system. 206 Should be <= to the number of CPUs in your system.
207 207
208config LITMUS_NVIDIA
209 bool "Litmus handling of NVIDIA interrupts."
210 depends on LITMUS_SOFTIRQD
211 default n
212 help
213 Direct tasklets from NVIDIA devices to Litmus's klitirqd.
214
215 If unsure, say No.
216
208endmenu 217endmenu
209 218
210endmenu 219endmenu
diff --git a/litmus/Makefile b/litmus/Makefile
index 0d0214c54896..3d3139609878 100644
--- a/litmus/Makefile
+++ b/litmus/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_SCHED_DEBUG_TRACE) += sched_trace.o
28obj-$(CONFIG_SCHED_OVERHEAD_TRACE) += trace.o 28obj-$(CONFIG_SCHED_OVERHEAD_TRACE) += trace.o
29 29
30obj-$(CONFIG_LITMUS_SOFTIRQD) += litmus_softirq.o 30obj-$(CONFIG_LITMUS_SOFTIRQD) += litmus_softirq.o
31obj-$(CONFIG_LITMUS_NVIDIA) += nvidia_info.o
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
diff --git a/litmus/nvidia_info.c b/litmus/nvidia_info.c
new file mode 100644
index 000000000000..05f8356a8117
--- /dev/null
+++ b/litmus/nvidia_info.c
@@ -0,0 +1,55 @@
1
2#include <linux/module.h>
3
4#include <litmus/sched_trace.h>
5#include <litmus/nvidia_info.h>
6
7static struct module* nvidia_mod = NULL;
8
9int init_nvidia_info(void)
10{
11 mutex_lock(&module_mutex);
12 nvidia_mod = find_module("nvidia");
13 mutex_unlock(&module_mutex);
14
15 if(nvidia_mod != NULL)
16 {
17 TRACE("%s : Found NVIDIA module. Core Code: %x to %x\n", __FUNCTION__,
18 (void*)(nvidia_mod->module_core),
19 (void*)(nvidia_mod->module_core) + nvidia_mod->core_size);
20 return(0);
21 }
22 else
23 {
24 TRACE("%s : Could not find NVIDIA module! Loaded?\n", __FUNCTION__);
25 return(-1);
26 }
27}
28
29
30/* works with pointers to static data inside the module too. */
31int is_nvidia_func(void *func_addr)
32{
33 int ret = 0;
34 if(nvidia_mod)
35 {
36 ret = within_module_core((long unsigned int)func_addr, nvidia_mod);
37
38 TRACE("%s : %x is in NVIDIA module : %d\n",
39 __FUNCTION__, func_addr, ret);
40 }
41 else
42 {
43 TRACE("%s : No NVIDIA module info loaded!\n", __FUNCTION__);
44 }
45
46 return(ret);
47}
48
49int is_nvidia_in_callstack(void)
50{
51 /* TODO -- Walk back through the callstack, running each called
52 function through is_nvidia_func() */
53 TRACE("%s : NOT IMPLEMENTED!\n", __FUNCTION__);
54 return(1);
55}
diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c
index 586b7c3f7de1..99813698ee17 100644
--- a/litmus/sched_gsn_edf.c
+++ b/litmus/sched_gsn_edf.c
@@ -29,6 +29,10 @@
29#include <litmus/litmus_softirq.h> 29#include <litmus/litmus_softirq.h>
30#endif 30#endif
31 31
32#ifdef CONFIG_LITMUS_NVIDIA
33#include <litmus/nvidia_info.h>
34#endif
35
32/* Overview of GSN-EDF operations. 36/* Overview of GSN-EDF operations.
33 * 37 *
34 * For a detailed explanation of GSN-EDF have a look at the FMLP paper. This 38 * For a detailed explanation of GSN-EDF have a look at the FMLP paper. This
@@ -967,6 +971,10 @@ static long gsnedf_activate_plugin(void)
967 spawn_klitirqd(); 971 spawn_klitirqd();
968#endif 972#endif
969 973
974#ifdef CONFIG_LITMUS_NVIDIA
975 init_nvidia_info();
976#endif
977
970 return 0; 978 return 0;
971} 979}
972 980