diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 162 |
1 files changed, 140 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 | |||
735 | enum { | 741 | enum { |
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 | |||
748 | const_debug unsigned int sysctl_sched_features = | 750 | const_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 | |||
767 | int sched_feat_open(struct inode *inode, struct file *filp) | ||
768 | { | ||
769 | filp->private_data = inode->i_private; | ||
770 | return 0; | ||
771 | } | ||
772 | |||
773 | static ssize_t | ||
774 | sched_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 | |||
808 | static ssize_t | ||
809 | sched_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 | |||
850 | static struct file_operations sched_feat_fops = { | ||
851 | .open = sched_feat_open, | ||
852 | .read = sched_feat_read, | ||
853 | .write = sched_feat_write, | ||
854 | }; | ||
855 | |||
856 | static __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 | } | ||
874 | late_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. |