aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/softirq.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/softirq.c')
-rw-r--r--kernel/softirq.c256
1 files changed, 238 insertions, 18 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c
index fca82c32042b..48d6bde692a1 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -29,6 +29,15 @@
29#include <trace/events/irq.h> 29#include <trace/events/irq.h>
30 30
31#include <asm/irq.h> 31#include <asm/irq.h>
32
33#include <litmus/litmus.h>
34#include <litmus/sched_trace.h>
35
36#ifdef CONFIG_LITMUS_NVIDIA
37#include <litmus/nvidia_info.h>
38#include <litmus/trace.h>
39#endif
40
32/* 41/*
33 - No shared variables, all the data are CPU local. 42 - No shared variables, all the data are CPU local.
34 - If a softirq needs serialization, let it serialize itself 43 - If a softirq needs serialization, let it serialize itself
@@ -67,7 +76,7 @@ char *softirq_to_name[NR_SOFTIRQS] = {
67 * to the pending events, so lets the scheduler to balance 76 * to the pending events, so lets the scheduler to balance
68 * the softirq load for us. 77 * the softirq load for us.
69 */ 78 */
70static void wakeup_softirqd(void) 79void wakeup_softirqd(void)
71{ 80{
72 /* Interrupts are disabled: no need to stop preemption */ 81 /* Interrupts are disabled: no need to stop preemption */
73 struct task_struct *tsk = __this_cpu_read(ksoftirqd); 82 struct task_struct *tsk = __this_cpu_read(ksoftirqd);
@@ -193,6 +202,7 @@ void local_bh_enable_ip(unsigned long ip)
193} 202}
194EXPORT_SYMBOL(local_bh_enable_ip); 203EXPORT_SYMBOL(local_bh_enable_ip);
195 204
205
196/* 206/*
197 * We restart softirq processing MAX_SOFTIRQ_RESTART times, 207 * We restart softirq processing MAX_SOFTIRQ_RESTART times,
198 * and we fall back to softirqd after that. 208 * and we fall back to softirqd after that.
@@ -204,14 +214,15 @@ EXPORT_SYMBOL(local_bh_enable_ip);
204 */ 214 */
205#define MAX_SOFTIRQ_RESTART 10 215#define MAX_SOFTIRQ_RESTART 10
206 216
207asmlinkage void __do_softirq(void) 217static void ____do_softirq(void)
208{ 218{
209 struct softirq_action *h;
210 __u32 pending; 219 __u32 pending;
211 int max_restart = MAX_SOFTIRQ_RESTART; 220
221 struct softirq_action *h;
212 int cpu; 222 int cpu;
213 223
214 pending = local_softirq_pending(); 224 pending = local_softirq_pending();
225
215 account_system_vtime(current); 226 account_system_vtime(current);
216 227
217 __local_bh_disable((unsigned long)__builtin_return_address(0), 228 __local_bh_disable((unsigned long)__builtin_return_address(0),
@@ -219,14 +230,13 @@ asmlinkage void __do_softirq(void)
219 lockdep_softirq_enter(); 230 lockdep_softirq_enter();
220 231
221 cpu = smp_processor_id(); 232 cpu = smp_processor_id();
222restart:
223 /* Reset the pending bitmask before enabling irqs */
224 set_softirq_pending(0);
225 233
234 set_softirq_pending(0);
235
226 local_irq_enable(); 236 local_irq_enable();
227 237
228 h = softirq_vec; 238 h = softirq_vec;
229 239
230 do { 240 do {
231 if (pending & 1) { 241 if (pending & 1) {
232 unsigned int vec_nr = h - softirq_vec; 242 unsigned int vec_nr = h - softirq_vec;
@@ -245,14 +255,23 @@ restart:
245 prev_count, preempt_count()); 255 prev_count, preempt_count());
246 preempt_count() = prev_count; 256 preempt_count() = prev_count;
247 } 257 }
248 258
249 rcu_bh_qs(cpu); 259 rcu_bh_qs(cpu);
250 } 260 }
251 h++; 261 h++;
252 pending >>= 1; 262 pending >>= 1;
253 } while (pending); 263 } while (pending);
254 264
255 local_irq_disable(); 265 local_irq_disable();
266}
267
268static void ___do_softirq(void)
269{
270 int max_restart = MAX_SOFTIRQ_RESTART;
271 __u32 pending;
272
273restart:
274 ____do_softirq();
256 275
257 pending = local_softirq_pending(); 276 pending = local_softirq_pending();
258 if (pending && --max_restart) 277 if (pending && --max_restart)
@@ -260,9 +279,38 @@ restart:
260 279
261 if (pending) 280 if (pending)
262 wakeup_softirqd(); 281 wakeup_softirqd();
282}
263 283
284asmlinkage void __do_softirq(void)
285{
286#ifdef LITMUS_THREAD_ALL_SOFTIRQ
287 /* Skip straight to wakeup_softirqd() if we're using
288 LITMUS_THREAD_ALL_SOFTIRQ (unless there's really high prio-stuff waiting.). */
289 struct task_struct *tsk = __get_cpu_var(ksoftirqd);
290
291 if(tsk)
292 {
293 __u32 pending = local_softirq_pending();
294 const __u32 high_prio_softirq = (1<<HI_SOFTIRQ) | (1<<TIMER_SOFTIRQ) | (1<<HRTIMER_SOFTIRQ);
295 if(pending && !(pending & high_prio_softirq))
296 {
297 wakeup_softirqd();
298 return;
299 }
300 }
301#endif
302
303 /*
304 * 'immediate' softirq execution:
305 */
306 __local_bh_disable((unsigned long)__builtin_return_address(0),
307 SOFTIRQ_OFFSET);
308 lockdep_softirq_enter();
309
310 ___do_softirq();
311
264 lockdep_softirq_exit(); 312 lockdep_softirq_exit();
265 313
266 account_system_vtime(current); 314 account_system_vtime(current);
267 __local_bh_enable(SOFTIRQ_OFFSET); 315 __local_bh_enable(SOFTIRQ_OFFSET);
268} 316}
@@ -402,8 +450,65 @@ struct tasklet_head
402static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec); 450static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
403static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec); 451static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);
404 452
453
405void __tasklet_schedule(struct tasklet_struct *t) 454void __tasklet_schedule(struct tasklet_struct *t)
406{ 455{
456#ifdef CONFIG_LITMUS_NVIDIA
457 if(is_nvidia_func(t->func))
458 {
459 u32 nvidia_device = get_tasklet_nv_device_num(t);
460 // TRACE("%s: Handling NVIDIA tasklet for device\t%u\tat\t%llu\n",
461 // __FUNCTION__, nvidia_device,litmus_clock());
462
463 unsigned long flags;
464 struct task_struct* device_owner;
465
466 lock_nv_registry(nvidia_device, &flags);
467
468 device_owner = get_nv_device_owner(nvidia_device);
469
470 if(device_owner==NULL)
471 {
472 t->owner = NULL;
473 }
474 else
475 {
476 if(is_realtime(device_owner))
477 {
478 TRACE("%s: Handling NVIDIA tasklet for device %u at %llu\n",
479 __FUNCTION__, nvidia_device,litmus_clock());
480 TRACE("%s: the owner task %d of NVIDIA Device %u is RT-task\n",
481 __FUNCTION__,device_owner->pid,nvidia_device);
482
483 t->owner = device_owner;
484 sched_trace_tasklet_release(t->owner);
485
486 if(likely(_litmus_tasklet_schedule(t,nvidia_device)))
487 {
488 unlock_nv_registry(nvidia_device, &flags);
489 return;
490 }
491 else
492 {
493 t->owner = NULL; /* fall through to normal scheduling */
494 }
495 }
496 else
497 {
498 t->owner = NULL;
499 }
500 }
501 unlock_nv_registry(nvidia_device, &flags);
502 }
503#endif
504
505 ___tasklet_schedule(t);
506}
507EXPORT_SYMBOL(__tasklet_schedule);
508
509
510void ___tasklet_schedule(struct tasklet_struct *t)
511{
407 unsigned long flags; 512 unsigned long flags;
408 513
409 local_irq_save(flags); 514 local_irq_save(flags);
@@ -413,11 +518,65 @@ void __tasklet_schedule(struct tasklet_struct *t)
413 raise_softirq_irqoff(TASKLET_SOFTIRQ); 518 raise_softirq_irqoff(TASKLET_SOFTIRQ);
414 local_irq_restore(flags); 519 local_irq_restore(flags);
415} 520}
521EXPORT_SYMBOL(___tasklet_schedule);
416 522
417EXPORT_SYMBOL(__tasklet_schedule);
418 523
419void __tasklet_hi_schedule(struct tasklet_struct *t) 524void __tasklet_hi_schedule(struct tasklet_struct *t)
420{ 525{
526#ifdef CONFIG_LITMUS_NVIDIA
527 if(is_nvidia_func(t->func))
528 {
529 u32 nvidia_device = get_tasklet_nv_device_num(t);
530 // TRACE("%s: Handling NVIDIA tasklet for device\t%u\tat\t%llu\n",
531 // __FUNCTION__, nvidia_device,litmus_clock());
532
533 unsigned long flags;
534 struct task_struct* device_owner;
535
536 lock_nv_registry(nvidia_device, &flags);
537
538 device_owner = get_nv_device_owner(nvidia_device);
539
540 if(device_owner==NULL)
541 {
542 t->owner = NULL;
543 }
544 else
545 {
546 if( is_realtime(device_owner))
547 {
548 TRACE("%s: Handling NVIDIA tasklet for device %u\tat %llu\n",
549 __FUNCTION__, nvidia_device,litmus_clock());
550 TRACE("%s: the owner task %d of NVIDIA Device %u is RT-task\n",
551 __FUNCTION__,device_owner->pid,nvidia_device);
552
553 t->owner = device_owner;
554 sched_trace_tasklet_release(t->owner);
555 if(likely(_litmus_tasklet_hi_schedule(t,nvidia_device)))
556 {
557 unlock_nv_registry(nvidia_device, &flags);
558 return;
559 }
560 else
561 {
562 t->owner = NULL; /* fall through to normal scheduling */
563 }
564 }
565 else
566 {
567 t->owner = NULL;
568 }
569 }
570 unlock_nv_registry(nvidia_device, &flags);
571 }
572#endif
573
574 ___tasklet_hi_schedule(t);
575}
576EXPORT_SYMBOL(__tasklet_hi_schedule);
577
578void ___tasklet_hi_schedule(struct tasklet_struct* t)
579{
421 unsigned long flags; 580 unsigned long flags;
422 581
423 local_irq_save(flags); 582 local_irq_save(flags);
@@ -427,19 +586,72 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
427 raise_softirq_irqoff(HI_SOFTIRQ); 586 raise_softirq_irqoff(HI_SOFTIRQ);
428 local_irq_restore(flags); 587 local_irq_restore(flags);
429} 588}
430 589EXPORT_SYMBOL(___tasklet_hi_schedule);
431EXPORT_SYMBOL(__tasklet_hi_schedule);
432 590
433void __tasklet_hi_schedule_first(struct tasklet_struct *t) 591void __tasklet_hi_schedule_first(struct tasklet_struct *t)
434{ 592{
435 BUG_ON(!irqs_disabled()); 593 BUG_ON(!irqs_disabled());
594#ifdef CONFIG_LITMUS_NVIDIA
595 if(is_nvidia_func(t->func))
596 {
597 u32 nvidia_device = get_tasklet_nv_device_num(t);
598 // TRACE("%s: Handling NVIDIA tasklet for device\t%u\tat\t%llu\n",
599 // __FUNCTION__, nvidia_device,litmus_clock());
600 unsigned long flags;
601 struct task_struct* device_owner;
602
603 lock_nv_registry(nvidia_device, &flags);
604
605 device_owner = get_nv_device_owner(nvidia_device);
606
607 if(device_owner==NULL)
608 {
609 t->owner = NULL;
610 }
611 else
612 {
613 if(is_realtime(device_owner))
614 {
615 TRACE("%s: Handling NVIDIA tasklet for device %u at %llu\n",
616 __FUNCTION__, nvidia_device,litmus_clock());
617
618 TRACE("%s: the owner task %d of NVIDIA Device %u is RT-task\n",
619 __FUNCTION__,device_owner->pid,nvidia_device);
620
621 t->owner = device_owner;
622 sched_trace_tasklet_release(t->owner);
623 if(likely(_litmus_tasklet_hi_schedule_first(t,nvidia_device)))
624 {
625 unlock_nv_registry(nvidia_device, &flags);
626 return;
627 }
628 else
629 {
630 t->owner = NULL; /* fall through to normal scheduling */
631 }
632 }
633 else
634 {
635 t->owner = NULL;
636 }
637 }
638 unlock_nv_registry(nvidia_device, &flags);
639 }
640#endif
641
642 ___tasklet_hi_schedule_first(t);
643}
644EXPORT_SYMBOL(__tasklet_hi_schedule_first);
645
646void ___tasklet_hi_schedule_first(struct tasklet_struct* t)
647{
648 BUG_ON(!irqs_disabled());
436 649
437 t->next = __this_cpu_read(tasklet_hi_vec.head); 650 t->next = __this_cpu_read(tasklet_hi_vec.head);
438 __this_cpu_write(tasklet_hi_vec.head, t); 651 __this_cpu_write(tasklet_hi_vec.head, t);
439 __raise_softirq_irqoff(HI_SOFTIRQ); 652 __raise_softirq_irqoff(HI_SOFTIRQ);
440} 653}
441 654EXPORT_SYMBOL(___tasklet_hi_schedule_first);
442EXPORT_SYMBOL(__tasklet_hi_schedule_first);
443 655
444static void tasklet_action(struct softirq_action *a) 656static void tasklet_action(struct softirq_action *a)
445{ 657{
@@ -495,6 +707,7 @@ static void tasklet_hi_action(struct softirq_action *a)
495 if (!atomic_read(&t->count)) { 707 if (!atomic_read(&t->count)) {
496 if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) 708 if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
497 BUG(); 709 BUG();
710
498 t->func(t->data); 711 t->func(t->data);
499 tasklet_unlock(t); 712 tasklet_unlock(t);
500 continue; 713 continue;
@@ -518,8 +731,13 @@ void tasklet_init(struct tasklet_struct *t,
518 t->next = NULL; 731 t->next = NULL;
519 t->state = 0; 732 t->state = 0;
520 atomic_set(&t->count, 0); 733 atomic_set(&t->count, 0);
734
521 t->func = func; 735 t->func = func;
522 t->data = data; 736 t->data = data;
737
738#ifdef CONFIG_LITMUS_SOFTIRQD
739 t->owner = NULL;
740#endif
523} 741}
524 742
525EXPORT_SYMBOL(tasklet_init); 743EXPORT_SYMBOL(tasklet_init);
@@ -534,6 +752,7 @@ void tasklet_kill(struct tasklet_struct *t)
534 yield(); 752 yield();
535 } while (test_bit(TASKLET_STATE_SCHED, &t->state)); 753 } while (test_bit(TASKLET_STATE_SCHED, &t->state));
536 } 754 }
755
537 tasklet_unlock_wait(t); 756 tasklet_unlock_wait(t);
538 clear_bit(TASKLET_STATE_SCHED, &t->state); 757 clear_bit(TASKLET_STATE_SCHED, &t->state);
539} 758}
@@ -808,6 +1027,7 @@ void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu)
808 for (i = &per_cpu(tasklet_vec, cpu).head; *i; i = &(*i)->next) { 1027 for (i = &per_cpu(tasklet_vec, cpu).head; *i; i = &(*i)->next) {
809 if (*i == t) { 1028 if (*i == t) {
810 *i = t->next; 1029 *i = t->next;
1030
811 /* If this was the tail element, move the tail ptr */ 1031 /* If this was the tail element, move the tail ptr */
812 if (*i == NULL) 1032 if (*i == NULL)
813 per_cpu(tasklet_vec, cpu).tail = i; 1033 per_cpu(tasklet_vec, cpu).tail = i;