aboutsummaryrefslogblamecommitdiffstats
path: root/litmus/color_proc.c
blob: d770123c5f024b6fb8c0772b3c1a5e55fcb521bc (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11



                         
                               





                                                            
                                           

                                   











                                                          
 

                                                      
 

                          


                             
                                                                      


                                       







                                                                           




                                                   







                                                               






                                                   






                                                         











                                              
 


                                              
                                       




                                               

                                                                            

                                     




                                                                            

                                                 



                                                                          

                              
 
                                                                 



                 


                                             
                                                                         


                                                                             

                              

                                                    

                   

 







                                                              
                                           

 

                                                             
 
                                             


                                                   


                                                           
 


                                                         
                               
                                      



                 
                                           
 
                         
                                    
                                     

                                  




                                                          
         

                   


 



                                               
                    
 
                                                                 


                                                                              

                              
         
                                      


                         
                                    

                         



                                               
                                       


                                   
                                                                              


                                                              

                   


                                
#include <linux/module.h>
#include <linux/sysctl.h>
#include <linux/slab.h>

#include <litmus/sched_trace.h>
#include <litmus/color.h>

extern int color_sysctl_add_pages_data; /* litmus/color.c */

static int zero = 0;
static int one = 1;
/* used as names for server proc entries */
static char *period_str = "period";
static char *wcet_str = "wcet";

/* servers have a WCET and period */
#define NR_SERVER_PARAMS 2
#define CPU_NAME_LEN     3
struct color_cpu_server {
	char name[CPU_NAME_LEN];
	unsigned long wcet;
	unsigned long period;
	/* the + 1 is for the sentinel element */
	struct ctl_table table[NR_SERVER_PARAMS + 1];
};
static struct color_cpu_server color_cpu_servers[NR_CPUS];

/* the + 1 is for the sentinel element */
static struct ctl_table color_cpu_tables[NR_CPUS + 1];

unsigned long color_chunk;

#define INFO_BUFFER_SIZE 100
static char info_buffer[100];

#define NR_PAGES_INDEX 0 /* location of nr_pages in the table below */
static struct ctl_table color_table[] =
{
	{
		/* you MUST update NR_PAGES_INDEX if you move this entry */
		.procname	= "nr_pages",
		.mode		= 0444,
		.proc_handler	= color_nr_pages_handler,
		.data		= NULL,		/* dynamically set later */
		.maxlen		= 0,		/* also set later */
	},
	{
		.procname	= "servers",
		.mode		= 0555,
		.child          = color_cpu_tables,
	},
	{
		.procname	= "add_pages",
		.data		= &color_sysctl_add_pages_data,
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= color_add_pages_handler,
		.extra1		= &zero,
		.extra2		= &one,
	},
	{
		.procname	= "cache_info",
		.mode		= 0444,
		.proc_handler	= proc_dostring,
		.data		= info_buffer,
		.maxlen		= INFO_BUFFER_SIZE,
	},
	{
		.procname	= "chunk_size",
		.mode		= 0666,
		.proc_handler	= proc_doulongvec_minmax,
		.data           = &color_chunk,
		.maxlen		= sizeof(color_chunk),
	},
	{ }
};

static struct ctl_table litmus_table[] =
{
	{
		.procname	= "color",
		.mode		= 0555,
		.child		= color_table,
	},
	{ }
};

static struct ctl_table litmus_dir_table[] = {
	{
		.procname	= "litmus",
 		.mode		= 0555,
		.child		= litmus_table,
	},
	{ }
};

int color_server_params(int cpu, unsigned long *wcet, unsigned long *period)
{
	struct color_cpu_server *svr;

	if (cpu >= num_online_cpus()) {
		printk(KERN_WARNING "Cannot access illegal CPU: %d\n", cpu);
		return -EFAULT;
	}

	svr = &color_cpu_servers[cpu];
	if (svr->wcet == 0 || svr->period == 0) {
		printk(KERN_WARNING "Server %d is uninitialized!\n", cpu);
		return -EPERM;
	}

	*wcet = svr->wcet;
	*period = svr->period;

	TRACE("For %d: %lu, %lu\n", cpu, svr->wcet, svr->period);

	return 0;
}

/* must be called AFTER nr_colors is set */
static int __init init_sysctl_nr_colors(void)
{
	int ret = 0, maxlen = ONE_COLOR_LEN * color_cache_info.nr_colors;
	color_table[NR_PAGES_INDEX].data = kmalloc(maxlen, GFP_KERNEL);
	if (!color_table[NR_PAGES_INDEX].data) {
		printk(KERN_WARNING "Could not allocate nr_pages buffer.\n");
		ret = -ENOMEM;
		goto out;
	}
	color_table[NR_PAGES_INDEX].maxlen = maxlen;
out:
	return ret;
}

static void __init init_server_entry(struct ctl_table *entry,
				     unsigned long *parameter,
				     char *name)
{
	entry->procname = name;
	entry->mode = 0666;
	entry->proc_handler = proc_doulongvec_minmax;
	entry->data = parameter;
	entry->maxlen = sizeof(*parameter);
}

static int __init init_cpu_entry(struct ctl_table *cpu_table,
		struct color_cpu_server *svr, int cpu)
{
	struct ctl_table *entry = svr->table;

	printk(KERN_INFO "Creating cpu %d\n", cpu);

	init_server_entry(entry, &svr->wcet, wcet_str);
	entry++;
	init_server_entry(entry, &svr->period, period_str);

	/* minus one for the null byte */
	snprintf(svr->name, CPU_NAME_LEN - 1, "%d", cpu);
	cpu_table->procname = svr->name;
	cpu_table->mode = 0555;
	cpu_table->child = svr->table;

	return 0;
}

static int __init init_server_entries(void)
{
	int cpu, err = 0;
	struct ctl_table *cpu_table;
	struct color_cpu_server *svr;

	for_each_online_cpu(cpu) {
		cpu_table = &color_cpu_tables[cpu];
		svr = &color_cpu_servers[cpu];
		err = init_cpu_entry(cpu_table, svr, cpu);
		if (err)
			goto out;
	}
out:
	return err;
}


static struct ctl_table_header *litmus_sysctls;

static int __init litmus_sysctl_init(void)
{
	int ret = 0;

	printk(KERN_INFO "Registering LITMUS^RT proc sysctl.\n");
	litmus_sysctls = register_sysctl_table(litmus_dir_table);
	if (!litmus_sysctls) {
		printk(KERN_WARNING "Could not register LITMUS^RT sysctl.\n");
		ret = -EFAULT;
		goto out;
	}
	ret = init_sysctl_nr_colors();
	if (ret)
		goto out;

	ret = init_server_entries();
	if (ret)
		goto out;

	snprintf(info_buffer, INFO_BUFFER_SIZE,
		 "Cache size\t: %lu B\n"
		 "Line size\t: %lu B\n"
		 "Page size\t: %lu B\n"
		 "Ways\t\t: %lu\n"
		 "Sets\t\t: %lu\n"
		 "Colors\t\t: %lu",
		 color_cache_info.size, color_cache_info.line_size, PAGE_SIZE,
		 color_cache_info.ways, color_cache_info.sets,
		 color_cache_info.nr_colors);

out:
	return ret;
}

module_init(litmus_sysctl_init);