Commit f00b45c145981b43c7e7f66315ac77534c938cbf

Authored by Peter Zijlstra
Committed by Ingo Molnar
1 parent 06379aba52

sched: /debug/sched_features

provide a text based interface to the scheduler features; this saves the
'user' from setting bits using decimal arithmetic.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

Showing 2 changed files with 150 additions and 22 deletions Side-by-side Diff

... ... @@ -68,6 +68,8 @@
68 68 #include <linux/hrtimer.h>
69 69 #include <linux/tick.h>
70 70 #include <linux/bootmem.h>
  71 +#include <linux/debugfs.h>
  72 +#include <linux/ctype.h>
71 73  
72 74 #include <asm/tlb.h>
73 75 #include <asm/irq_regs.h>
74 76  
75 77  
76 78  
77 79  
... ... @@ -732,32 +734,148 @@
732 734 /*
733 735 * Debugging: various feature bits
734 736 */
  737 +
  738 +#define SCHED_FEAT(name, enabled) \
  739 + __SCHED_FEAT_##name ,
  740 +
735 741 enum {
736   - SCHED_FEAT_NEW_FAIR_SLEEPERS = 1,
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,
  742 +#include "sched_features.h"
746 743 };
747 744  
  745 +#undef SCHED_FEAT
  746 +
  747 +#define SCHED_FEAT(name, enabled) \
  748 + (1UL << __SCHED_FEAT_##name) * enabled |
  749 +
748 750 const_debug unsigned int sysctl_sched_features =
749   - SCHED_FEAT_NEW_FAIR_SLEEPERS * 1 |
750   - SCHED_FEAT_WAKEUP_PREEMPT * 1 |
751   - SCHED_FEAT_START_DEBIT * 1 |
752   - SCHED_FEAT_AFFINE_WAKEUPS * 1 |
753   - SCHED_FEAT_CACHE_HOT_BUDDY * 1 |
754   - SCHED_FEAT_SYNC_WAKEUPS * 1 |
755   - SCHED_FEAT_HRTICK * 1 |
756   - SCHED_FEAT_DOUBLE_TICK * 0 |
757   - SCHED_FEAT_NORMALIZED_SLEEPER * 1 |
758   - SCHED_FEAT_DEADLINE * 1;
  751 +#include "sched_features.h"
  752 + 0;
759 753  
760   -#define sched_feat(x) (sysctl_sched_features & SCHED_FEAT_##x)
  754 +#undef SCHED_FEAT
  755 +
  756 +#ifdef CONFIG_SCHED_DEBUG
  757 +#define SCHED_FEAT(name, enabled) \
  758 + #name ,
  759 +
  760 +__read_mostly char *sched_feat_names[] = {
  761 +#include "sched_features.h"
  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 881 * Number of tasks to iterate in a single balance run.
kernel/sched_features.h
  1 +SCHED_FEAT(NEW_FAIR_SLEEPERS, 1)
  2 +SCHED_FEAT(WAKEUP_PREEMPT, 1)
  3 +SCHED_FEAT(START_DEBIT, 1)
  4 +SCHED_FEAT(AFFINE_WAKEUPS, 1)
  5 +SCHED_FEAT(CACHE_HOT_BUDDY, 1)
  6 +SCHED_FEAT(SYNC_WAKEUPS, 1)
  7 +SCHED_FEAT(HRTICK, 1)
  8 +SCHED_FEAT(DOUBLE_TICK, 0)
  9 +SCHED_FEAT(NORMALIZED_SLEEPER, 1)
  10 +SCHED_FEAT(DEADLINE, 1)