aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched.c162
-rw-r--r--kernel/sched_features.h10
2 files changed, 150 insertions, 22 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index 8f03817e7dd3..b59a44e1ea44 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -68,6 +68,8 @@
68#include <linux/hrtimer.h> 68#include <linux/hrtimer.h>
69#include <linux/tick.h> 69#include <linux/tick.h>
70#include <linux/bootmem.h> 70#include <linux/bootmem.h>
71#include <linux/debugfs.h>
72#include <linux/ctype.h>
71 73
72#include <asm/tlb.h> 74#include <asm/tlb.h>
73#include <asm/irq_regs.h> 75#include <asm/irq_regs.h>
@@ -732,32 +734,148 @@ static void update_rq_clock(struct rq *rq)
732/* 734/*
733 * Debugging: various feature bits 735 * Debugging: various feature bits
734 */ 736 */
737
738#define SCHED_FEAT(name, enabled) \
739 __SCHED_FEAT_##name ,
740
735enum { 741enum {
736 SCHED_FEAT_NEW_FAIR_SLEEPERS = 1, 742#include "sched_features.h"
737 SCHED_FEAT_WAKEUP_PREEMPT = 2,
738 SCHED_FEAT_START_DEBIT = 4,
739 SCHED_FEAT_AFFINE_WAKEUPS = 8,
740 SCHED_FEAT_CACHE_HOT_BUDDY = 16,
741 SCHED_FEAT_SYNC_WAKEUPS = 32,
742 SCHED_FEAT_HRTICK = 64,
743 SCHED_FEAT_DOUBLE_TICK = 128,
744 SCHED_FEAT_NORMALIZED_SLEEPER = 256,
745 SCHED_FEAT_DEADLINE = 512,
746}; 743};
747 744
745#undef SCHED_FEAT
746
747#define SCHED_FEAT(name, enabled) \
748 (1UL << __SCHED_FEAT_##name) * enabled |
749
748const_debug unsigned int sysctl_sched_features = 750const_debug unsigned int sysctl_sched_features =
749 SCHED_FEAT_NEW_FAIR_SLEEPERS * 1 | 751#include "sched_features.h"
750 SCHED_FEAT_WAKEUP_PREEMPT * 1 | 752 0;
751 SCHED_FEAT_START_DEBIT * 1 | 753
752 SCHED_FEAT_AFFINE_WAKEUPS * 1 | 754#undef SCHED_FEAT
753 SCHED_FEAT_CACHE_HOT_BUDDY * 1 | 755
754 SCHED_FEAT_SYNC_WAKEUPS * 1 | 756#ifdef CONFIG_SCHED_DEBUG
755 SCHED_FEAT_HRTICK * 1 | 757#define SCHED_FEAT(name, enabled) \
756 SCHED_FEAT_DOUBLE_TICK * 0 | 758 #name ,
757 SCHED_FEAT_NORMALIZED_SLEEPER * 1 | 759
758 SCHED_FEAT_DEADLINE * 1; 760__read_mostly char *sched_feat_names[] = {
759 761#include "sched_features.h"
760#define sched_feat(x) (sysctl_sched_features & SCHED_FEAT_##x) 762 NULL
763};
764
765#undef SCHED_FEAT
766
767int sched_feat_open(struct inode *inode, struct file *filp)
768{
769 filp->private_data = inode->i_private;
770 return 0;
771}
772
773static ssize_t
774sched_feat_read(struct file *filp, char __user *ubuf,
775 size_t cnt, loff_t *ppos)
776{
777 char *buf;
778 int r = 0;
779 int len = 0;
780 int i;
781
782 for (i = 0; sched_feat_names[i]; i++) {
783 len += strlen(sched_feat_names[i]);
784 len += 4;
785 }
786
787 buf = kmalloc(len + 2, GFP_KERNEL);
788 if (!buf)
789 return -ENOMEM;
790
791 for (i = 0; sched_feat_names[i]; i++) {
792 if (sysctl_sched_features & (1UL << i))
793 r += sprintf(buf + r, "%s ", sched_feat_names[i]);
794 else
795 r += sprintf(buf + r, "no_%s ", sched_feat_names[i]);
796 }
797
798 r += sprintf(buf + r, "\n");
799 WARN_ON(r >= len + 2);
800
801 r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
802
803 kfree(buf);
804
805 return r;
806}
807
808static ssize_t
809sched_feat_write(struct file *filp, const char __user *ubuf,
810 size_t cnt, loff_t *ppos)
811{
812 char buf[64];
813 char *cmp = buf;
814 int neg = 0;
815 int i;
816
817 if (cnt > 63)
818 cnt = 63;
819
820 if (copy_from_user(&buf, ubuf, cnt))
821 return -EFAULT;
822
823 buf[cnt] = 0;
824
825 if (strncmp(buf, "no_", 3) == 0) {
826 neg = 1;
827 cmp += 3;
828 }
829
830 for (i = 0; sched_feat_names[i]; i++) {
831 int len = strlen(sched_feat_names[i]);
832
833 if (strncmp(cmp, sched_feat_names[i], len) == 0) {
834 if (neg)
835 sysctl_sched_features &= ~(1UL << i);
836 else
837 sysctl_sched_features |= (1UL << i);
838 break;
839 }
840 }
841
842 if (!sched_feat_names[i])
843 return -EINVAL;
844
845 filp->f_pos += cnt;
846
847 return cnt;
848}
849
850static struct file_operations sched_feat_fops = {
851 .open = sched_feat_open,
852 .read = sched_feat_read,
853 .write = sched_feat_write,
854};
855
856static __init int sched_init_debug(void)
857{
858 int i, j, len;
859
860 for (i = 0; sched_feat_names[i]; i++) {
861 len = strlen(sched_feat_names[i]);
862
863 for (j = 0; j < len; j++) {
864 sched_feat_names[i][j] =
865 tolower(sched_feat_names[i][j]);
866 }
867 }
868
869 debugfs_create_file("sched_features", 0644, NULL, NULL,
870 &sched_feat_fops);
871
872 return 0;
873}
874late_initcall(sched_init_debug);
875
876#endif
877
878#define sched_feat(x) (sysctl_sched_features & (1UL << __SCHED_FEAT_##x))
761 879
762/* 880/*
763 * Number of tasks to iterate in a single balance run. 881 * Number of tasks to iterate in a single balance run.
diff --git a/kernel/sched_features.h b/kernel/sched_features.h
new file mode 100644
index 000000000000..1c7283cb9581
--- /dev/null
+++ b/kernel/sched_features.h
@@ -0,0 +1,10 @@
1SCHED_FEAT(NEW_FAIR_SLEEPERS, 1)
2SCHED_FEAT(WAKEUP_PREEMPT, 1)
3SCHED_FEAT(START_DEBIT, 1)
4SCHED_FEAT(AFFINE_WAKEUPS, 1)
5SCHED_FEAT(CACHE_HOT_BUDDY, 1)
6SCHED_FEAT(SYNC_WAKEUPS, 1)
7SCHED_FEAT(HRTICK, 1)
8SCHED_FEAT(DOUBLE_TICK, 0)
9SCHED_FEAT(NORMALIZED_SLEEPER, 1)
10SCHED_FEAT(DEADLINE, 1)