diff options
-rw-r--r-- | include/linux/rt_param.h | 8 | ||||
-rw-r--r-- | kernel/litmus.c | 90 |
2 files changed, 62 insertions, 36 deletions
diff --git a/include/linux/rt_param.h b/include/linux/rt_param.h index 8936d2c22f..426a929187 100644 --- a/include/linux/rt_param.h +++ b/include/linux/rt_param.h | |||
@@ -101,14 +101,6 @@ typedef struct task_rt_param { | |||
101 | */ | 101 | */ |
102 | unsigned int subject_to_srp:1; | 102 | unsigned int subject_to_srp:1; |
103 | 103 | ||
104 | /* Ready to receive scheduler signals? */ | ||
105 | unsigned int signal_ready:1; | ||
106 | |||
107 | /* scheduler signal list head */ | ||
108 | unsigned int in_sig_list:1; | ||
109 | unsigned int signal:8; | ||
110 | struct list_head sig_list; | ||
111 | |||
112 | /* user controlled parameters */ | 104 | /* user controlled parameters */ |
113 | rt_param_t basic_params; | 105 | rt_param_t basic_params; |
114 | 106 | ||
diff --git a/kernel/litmus.c b/kernel/litmus.c index 438b2e7942..ee1e09a627 100644 --- a/kernel/litmus.c +++ b/kernel/litmus.c | |||
@@ -499,62 +499,96 @@ asmlinkage int sys_scheduler_setup(int cmd, void __user *parameter) | |||
499 | { | 499 | { |
500 | int ret = -EINVAL; | 500 | int ret = -EINVAL; |
501 | 501 | ||
502 | switch (cmd) { | 502 | ret = curr_sched_plugin->scheduler_setup(cmd, parameter); |
503 | case ENABLE_WEIGHT_CHANGE_SIGNAL: | ||
504 | current->rt_param.signal_ready = 1; | ||
505 | ret = 0; | ||
506 | break; | ||
507 | default: | ||
508 | ret = curr_sched_plugin->scheduler_setup(cmd, parameter); | ||
509 | }; | ||
510 | 503 | ||
511 | return ret; | 504 | return ret; |
512 | } | 505 | } |
513 | 506 | ||
514 | /* only call with interrupts disabled! */ | 507 | struct sched_sig { |
515 | void scheduler_signal(struct task_struct *t, unsigned int signo) | 508 | struct list_head list; |
509 | struct task_struct* task; | ||
510 | unsigned int signal:31; | ||
511 | int force:1; | ||
512 | }; | ||
513 | |||
514 | static void __scheduler_signal(struct task_struct *t, unsigned int signo, | ||
515 | int force) | ||
516 | { | 516 | { |
517 | struct sched_sig* sig; | ||
518 | |||
519 | sig = kmalloc(GFP_ATOMIC, sizeof(struct sched_sig)); | ||
520 | if (!sig) { | ||
521 | TRACE_TASK(t, "dropping signal: %u\n", t); | ||
522 | return; | ||
523 | } | ||
524 | |||
517 | spin_lock(&sched_sig_list_lock); | 525 | spin_lock(&sched_sig_list_lock); |
518 | 526 | ||
519 | if (!t->rt_param.in_sig_list) { | 527 | sig->signal = signo; |
520 | get_task_struct(t); | 528 | sig->force = force; |
521 | t->rt_param.signal = signo; | 529 | sig->task = t; |
522 | t->rt_param.in_sig_list = 1; | 530 | get_task_struct(t); |
523 | list_add(&t->rt_param.sig_list, &sched_sig_list); | 531 | list_add(&sig->list, &sched_sig_list); |
524 | } else | ||
525 | TRACE_TASK(t, "dropping signal: %u\n", t); | ||
526 | 532 | ||
527 | spin_unlock(&sched_sig_list_lock); | 533 | spin_unlock(&sched_sig_list_lock); |
528 | } | 534 | } |
529 | 535 | ||
536 | void scheduler_signal(struct task_struct *t, unsigned int signo) | ||
537 | { | ||
538 | __scheduler_signal(t, signo, 0); | ||
539 | } | ||
540 | |||
541 | void force_scheduler_signal(struct task_struct *t, unsigned int signo) | ||
542 | { | ||
543 | __scheduler_signal(t, signo, 1); | ||
544 | } | ||
545 | |||
530 | void send_scheduler_signals(void) | 546 | void send_scheduler_signals(void) |
531 | { | 547 | { |
532 | unsigned long flags; | 548 | unsigned long flags; |
533 | struct list_head *p, *extra; | 549 | struct list_head *p, *extra; |
534 | struct siginfo info; | 550 | struct siginfo info; |
551 | struct sched_sig* sig; | ||
535 | struct task_struct* t; | 552 | struct task_struct* t; |
536 | /* | 553 | struct list_head claimed; |
554 | |||
537 | if (spin_trylock_irqsave(&sched_sig_list_lock, flags)) { | 555 | if (spin_trylock_irqsave(&sched_sig_list_lock, flags)) { |
556 | if (list_empty(&sched_sig_list)) | ||
557 | p = NULL; | ||
558 | else { | ||
559 | p = sched_sig_list.next; | ||
560 | list_del(&sched_sig_list); | ||
561 | INIT_LIST_HEAD(&sched_sig_list); | ||
562 | } | ||
563 | spin_unlock_irqrestore(&sched_sig_list_lock, flags); | ||
564 | |||
565 | /* abort if there are no signals */ | ||
566 | if (!p) | ||
567 | return; | ||
538 | 568 | ||
539 | list_for_each_safe(p, extra, &sched_sig_list) { | 569 | /* take signal list we just obtained */ |
570 | list_add(&claimed, p); | ||
571 | |||
572 | list_for_each_safe(p, extra, &claimed) { | ||
540 | list_del(p); | 573 | list_del(p); |
541 | t = list_entry(p, struct task_struct, | 574 | sig = list_entry(p, struct sched_sig, list); |
542 | rt_param.sig_list); | 575 | t = sig->task; |
543 | t->rt_param.in_sig_list = 0; | 576 | info.si_signo = sig->signal; |
544 | info.si_signo = t->rt_param.signal; | ||
545 | info.si_errno = 0; | 577 | info.si_errno = 0; |
546 | info.si_code = SI_KERNEL; | 578 | info.si_code = SI_KERNEL; |
547 | info.si_pid = 1; | 579 | info.si_pid = 1; |
548 | info.si_uid = 0; | 580 | info.si_uid = 0; |
549 | TRACE("sending signal %d to %d\n", info.si_signo, | 581 | TRACE("sending signal %d to %d\n", info.si_signo, |
550 | t->pid); | 582 | t->pid); |
551 | force_sig_info(t->rt_param.signal, &info, t); | 583 | if (sig->force) |
584 | force_sig_info(sig->signal, &info, t); | ||
585 | else | ||
586 | send_sig_info(sig->signal, &info, t); | ||
552 | put_task_struct(t); | 587 | put_task_struct(t); |
588 | kfree(sig); | ||
553 | } | 589 | } |
554 | |||
555 | spin_unlock_irqrestore(&sched_sig_list_lock, flags); | ||
556 | } | 590 | } |
557 | */ | 591 | |
558 | } | 592 | } |
559 | 593 | ||
560 | static inline void np_mem_error(struct task_struct* t, const char* reason) | 594 | static inline void np_mem_error(struct task_struct* t, const char* reason) |
@@ -562,7 +596,7 @@ static inline void np_mem_error(struct task_struct* t, const char* reason) | |||
562 | if (t->state != TASK_DEAD && !(t->flags & PF_EXITING)) { | 596 | if (t->state != TASK_DEAD && !(t->flags & PF_EXITING)) { |
563 | TRACE("np section: %s => %s/%d killed\n", | 597 | TRACE("np section: %s => %s/%d killed\n", |
564 | reason, t->comm, t->pid); | 598 | reason, t->comm, t->pid); |
565 | scheduler_signal(t, SIGKILL); | 599 | force_scheduler_signal(t, SIGKILL); |
566 | } | 600 | } |
567 | } | 601 | } |
568 | 602 | ||