All pastes #1446072 Raw Edit

Cyclictest-Kernel

public c v1 · immutable
#1446072 ·published 2009-06-03 11:13 UTC
rendered paste body
/* * Cyclictest-Kernel * (c) 2009 Stefan Agner */#include <linux/module.h>	/* Needed by all modules */#include <linux/kernel.h>	/* Needed for KERN_ALERT */#include <linux/sched.h>	/* Scheduling */#include <linux/kthread.h>	/* Kernel Threading */#include <linux/init.h>#include <linux/smp_lock.h>#include <linux/delay.h>#include <linux/hrtimer.h>	/* High Resolution Timers */#include "cyclictest.h"#include "proc.h"static char *interval = "1000000";unsigned long long intervalus = 1000000;module_param(interval, charp, 0);MODULE_PARM_DESC(interval, "The interval in microseconds, you can use m,s,M,h,d");static char *duration = "0";static unsigned long long durationus = 0;module_param(duration, charp, 0);MODULE_PARM_DESC(duration, "Limit testing time in microseconds, you can use m,s,M,h,d");wait_queue_head_t latencyvalues_queue;int shutdown = 0;struct task_struct *timer_thread;static ktime_t interval_time;static ktime_t next;static ktime_t now;static ktime_t stop;static unsigned long diff;struct timer_stat *stat;int bufmsk = 0;/* * Timerthread */static int *timerthread(void *data){	int ret;/*	daemonize("cyclictest-kernel-thread");	allow_signal(SIGKILL);*/	now = ktime_get();	/* Set stop time */	stop = ktime_add(now, ns_to_ktime(durationus*NSEC_PER_USEC));		next = ktime_add(now, interval_time);	while(!shutdown && !kthread_should_stop())	{		set_current_state(TASK_UNINTERRUPTIBLE);		ret = schedule_hrtimeout(&next, HRTIMER_MODE_ABS);		if(ret == -EINTR)		{			printk(KERN_INFO KLOG_PREFIX "Thread aborted\n");			break;		}		now = ktime_get();	        stat->cycles++;		/* Latency Statistic */		diff = ktime_to_us(ktime_sub(now, next));		stat->act = diff;		stat->avg += diff;		if (diff < stat->min && stat->cycles > 1)			stat->min = diff;		if (diff > stat->max)			stat->max = diff;		if(bufmsk)			stat->values[stat->cycles & bufmsk] = diff;		/* Wakeup proc call */		wake_up_interruptible_sync(&latencyvalues_queue);		next = ktime_add(next, interval_time);				/* Stop thread when duration is set and expired */		if(durationus && (ktime_to_ns(ktime_sub(now, stop)) >= 0))		{			shutdown++;			printk(KERN_INFO KLOG_PREFIX "Duration reached, reload module to start again\n");		}	}	return 0;}/* * parse an input value as a base10 value followed by an optional * suffix. The input value is presumed to be in microseconds, unless * followed by a modifier suffix: m=miliseconds,  * s=seconds, M=minutes, h=hours, d=days * * the return value is a value in microseconds */unsigned long long parse_time_string(char *val){        char *end;        unsigned long long t = simple_strtoull(val, &end, 10);        if (end) {                switch (*end) {                case 'm':			t *= USEC_PER_MSEC;			break;                case 's':                case 'S':			t *= USEC_PER_SEC;			break;                case 'M':                        t *= (unsigned long long)60*USEC_PER_SEC;                        break;                case 'h':                case 'H':                        t *= (unsigned long long)60*60 * USEC_PER_SEC;                        break;                case 'd':                case 'D':                        t *= (unsigned long long)24*60*60 * USEC_PER_SEC;                        break;                }        }        return t;}/* * Kernel Module initialization */int __init cyclictest_init(void){	struct sched_param param= { .sched_priority = 80 } ;	/* Waitqueue for proc latency values */	init_waitqueue_head(&latencyvalues_queue);	/* Init Space for stat structure */	stat = kmalloc(sizeof(struct timer_stat), GFP_KERNEL);	stat->cycles = 0;	stat->cyclesread = 0;	stat->min = 10000000;	stat->avg = 0;	stat->max = 0;	stat->act = 0;	stat->values = kmalloc(VALBUF_SIZE * sizeof(long), GFP_KERNEL);	/* Set the cycle 0 to 0 (same behaviour in cyclictest) */	stat->values[0] = 0; 	bufmsk = VALBUF_SIZE - 1;	if(proc_init())		return -1;	printk(KERN_INFO KLOG_PREFIX "Proc initialized\n");	/* Set timer interval */	intervalus = parse_time_string(interval);	interval_time = ns_to_ktime(intervalus*NSEC_PER_USEC);	/* Parse duration time... */        durationus = parse_time_string(duration);	/* Create Kernel Thread */        timer_thread = kthread_create((void *)timerthread,                                       NULL,                                       "cyclictest");	/* Set scheduling policy and priority */	sched_setscheduler(timer_thread, SCHED_FIFO, &param);	/* Start the thread by waking it up */	wake_up_process(timer_thread);	printk(KERN_INFO KLOG_PREFIX "Cyclictest loaded\n");	return 0;}/* * Module Cleanup Method */void __exit cyclictest_cleanup(void){	if(!shutdown)		kthread_stop(timer_thread);		proc_exit();	printk(KERN_INFO KLOG_PREFIX "Cyclictest unloaded\n");}/* Define init and cleanup functions */module_init(cyclictest_init);module_exit(cyclictest_cleanup);/* * Module informations... */MODULE_LICENSE("GPL");MODULE_AUTHOR("Stefan Agner <stefan.nospam.remove@agner.ch>");MODULE_DESCRIPTION("Cyclictest Module");