#include #include #include #include #define SPERIOD_LEN 7 #define SPERIOD_FILE "period" #define SWCET_LEN 5 #define SWCET_FILE "wcet" static unsigned long *server_wcet; static unsigned long *server_period; static struct ctl_table litmus_table[] = { { .procname = "color", .mode = 0555, }, { } }; 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) { if (cpu >= num_online_cpus()) { printk(KERN_WARNING "Cannot access illegal CPU: %d\n", cpu); return -EFAULT; } if (server_wcet[cpu] == ULONG_MAX || server_period[cpu] == ULONG_MAX) { printk(KERN_WARNING "Server %d is uninitialized!\n", cpu); return -EPERM; } *wcet = server_wcet[cpu]; *period = server_period[cpu]; TRACE("For %d: %lu, %lu\n", cpu, server_wcet[cpu], server_period[cpu]); return 0; } 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(unsigned long); } static int __init init_cpu_entry(struct ctl_table *cpu_table, int cpu) { char *name; size_t size; struct ctl_table *server_table, *entry; server_wcet[cpu] = ULONG_MAX; server_period[cpu] = ULONG_MAX; printk(KERN_INFO "Creating cpu %d\n", cpu); size = sizeof(ctl_table) * 3; server_table = kmalloc(size, GFP_ATOMIC); if (!server_table) { printk(KERN_WARNING "Could not allocate " "color server proc for CPU %d.\n", cpu); return -ENOMEM; } memset(server_table, 0, size); /* Server WCET */ name = kmalloc(SWCET_LEN, GFP_ATOMIC); if (!name) { return -ENOMEM; } strcpy(name, SWCET_FILE); entry = &server_table[0]; init_server_entry(entry, &server_wcet[cpu], name); /* Server period */ name = kmalloc(SPERIOD_LEN, GFP_ATOMIC); if (!name) { return -ENOMEM; } strcpy(name, SPERIOD_FILE); entry = &server_table[1]; init_server_entry(entry, &server_period[cpu], name); name = kmalloc(3, GFP_ATOMIC); if (!name) { return -ENOMEM; } snprintf(name, 2, "%d", cpu); cpu_table->procname = name; cpu_table->mode = 0555; cpu_table->child = server_table; return 0; } static int __init init_server_entries(struct ctl_table *cpu_tables) { size_t size; int ret, cpu; struct ctl_table *cpu_table; size = sizeof(unsigned long) * num_online_cpus(); server_wcet = kmalloc(size, GFP_ATOMIC); server_period = kmalloc(size, GFP_ATOMIC); if (!server_wcet || !server_period) { printk(KERN_WARNING "Could not allocate server parameters.\n"); return -ENOMEM; } for_each_online_cpu(cpu) { cpu_table = &cpu_tables[cpu]; ret = init_cpu_entry(cpu_table, cpu); if (ret) { return ret; } } return 0; } static struct ctl_table_header *litmus_sysctls; static int __init litmus_sysctl_init(void) { int ret; size_t size; struct ctl_table *cpu_tables; printk(KERN_INFO "Registering LITMUS^RT sysctl.\n"); size = sizeof(ctl_table) * (num_online_cpus() + 2); cpu_tables = kmalloc(size, GFP_ATOMIC); if (!cpu_tables) { printk(KERN_WARNING "Could not allocate color CPU proc.\n"); } memset(cpu_tables, 0, size); ret = init_server_entries(cpu_tables); if (ret) { return ret; } litmus_table->child = cpu_tables; litmus_sysctls = register_sysctl_table(litmus_dir_table); if (!litmus_sysctls) { printk(KERN_WARNING "Could not register LITMUS^RT sysctl.\n"); return -EFAULT; } return 0; } module_init(litmus_sysctl_init);