jit.c

http://code.google.com/p/ldd3/source/browse/trunk/misc-modules/jit.c?r=2
/*
 * jit.c -- the just-in-time module
 *
 * Copyright (C) 2001,2003 Alessandro Rubini and Jonathan Corbet
 * Copyright (C) 2001,2003 O'Reilly & Associates
 *
 * The source code in this file can be freely used, adapted,
 * and redistributed in source or binary form, so long as an
 * acknowledgment appears in derived source files.  The citation
 * should list that the code comes from the book "Linux Device
 * Drivers" by Alessandro Rubini and Jonathan Corbet, published
 * by O'Reilly & Associates.   No warranty is attached;
 * we cannot take responsibility for errors or fitness for use.
 *
 * $Id: jit.c,v 1.16 2004/09/26 07:02:43 gregkh Exp $
 */

#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>

#include <linux/time.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>

#include <asm/hardirq.h>
/*
 * This module is a silly one: it only embeds short code fragments
 * that show how time delays can be handled in the kernel.
 */

int delay = HZ; /* the default delay, expressed in jiffies */

module_param(delay, int, 0);

MODULE_AUTHOR("Alessandro Rubini");
MODULE_LICENSE("Dual BSD/GPL");

/* use these as data pointers, to implement four files in one function */
enum jit_files {
        JIT_BUSY,
        JIT_SCHED,
        JIT_QUEUE,
        JIT_SCHEDTO
};

/*
 * This function prints one line of data, after sleeping one second.
 * It can sleep in different ways, according to the data pointer
 */
int jit_fn(char *buf, char **start, off_t offset,
              int len, int *eof, void *data)
{
        unsigned long j0, j1; /* jiffies */
        wait_queue_head_t wait;

        init_waitqueue_head (&wait);
        j0 = jiffies;
        j1 = j0 + delay;

        switch((long)data) {
                case JIT_BUSY:
                        while (time_before(jiffies, j1))
                                cpu_relax();
                        break;
                case JIT_SCHED:
                        while (time_before(jiffies, j1)) {
                                schedule();
                        }
                        break;
                case JIT_QUEUE:
                        wait_event_interruptible_timeout(wait, 0, delay);
                        break;
                case JIT_SCHEDTO:
                        set_current_state(TASK_INTERRUPTIBLE);
                        schedule_timeout (delay);
                        break;
        }
        j1 = jiffies; /* actual value after we delayed */

        len = sprintf(buf, "%9li %9li\n", j0, j1);
        *start = buf;
        return len;
}

/*
 * This file, on the other hand, returns the current time forever
 */
int jit_currentime(char *buf, char **start, off_t offset,
                   int len, int *eof, void *data)
{
        struct timeval tv1;
        struct timespec tv2;
        unsigned long j1;
        u64 j2;

        /* get them four */
        j1 = jiffies;
        j2 = get_jiffies_64();
        do_gettimeofday(&tv1);
        tv2 = current_kernel_time();

        /* print */
        len=0;
        len += sprintf(buf,"0x%08lx 0x%016Lx %10i.%06i\n"
                       "%40i.%09i\n",
                       j1, j2,
                       (int) tv1.tv_sec, (int) tv1.tv_usec,
                       (int) tv2.tv_sec, (int) tv2.tv_nsec);
        *start = buf;
        return len;
}

/*
 * The timer example follows
 */

int tdelay = 10;
module_param(tdelay, int, 0);

/* This data structure used as "data" for the timer and tasklet functions */
struct jit_data {
        struct timer_list timer;
        struct tasklet_struct tlet;
        int hi; /* tasklet or tasklet_hi */
        wait_queue_head_t wait;
        unsigned long prevjiffies;
        unsigned char *buf;
        int loops;
};
#define JIT_ASYNC_LOOPS 5

void jit_timer_fn(unsigned long arg)
{
        struct jit_data *data = (struct jit_data *)arg;
        unsigned long j = jiffies;
        data->buf += sprintf(data->buf, "%9li  %3li     %i    %6i   %i   %s\n",
                             j, j - data->prevjiffies, in_interrupt() ? 1 : 0,
                             current->pid, smp_processor_id(), current->comm);

        if (--data->loops) {
                data->timer.expires += tdelay;
                data->prevjiffies = j;
                add_timer(&data->timer);
        } else {
                wake_up_interruptible(&data->wait);
        }
}

/* the /proc function: allocate everything to allow concurrency */
int jit_timer(char *buf, char **start, off_t offset,
              int len, int *eof, void *unused_data)
{
        struct jit_data *data;
        char *buf2 = buf;
        unsigned long j = jiffies;

        data = kmalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;

        init_timer(&data->timer);
        init_waitqueue_head (&data->wait);

        /* write the first lines in the buffer */
        buf2 += sprintf(buf2, "   time   delta  inirq    pid   cpu command\n");
        buf2 += sprintf(buf2, "%9li  %3li     %i    %6i   %i   %s\n",
                        j, 0L, in_interrupt() ? 1 : 0,
                        current->pid, smp_processor_id(), current->comm);

        /* fill the data for our timer function */
        data->prevjiffies = j;
        data->buf = buf2;
        data->loops = JIT_ASYNC_LOOPS;
        
        /* register the timer */
        data->timer.data = (unsigned long)data;
        data->timer.function = jit_timer_fn;
        data->timer.expires = j + tdelay; /* parameter */
        add_timer(&data->timer);

        /* wait for the buffer to fill */
        wait_event_interruptible(data->wait, !data->loops);
        if (signal_pending(current))
                return -ERESTARTSYS;
        buf2 = data->buf;
        kfree(data);
        *eof = 1;
        return buf2 - buf;
}

void jit_tasklet_fn(unsigned long arg)
{
        struct jit_data *data = (struct jit_data *)arg;
        unsigned long j = jiffies;
        data->buf += sprintf(data->buf, "%9li  %3li     %i    %6i   %i   %s\n",
                             j, j - data->prevjiffies, in_interrupt() ? 1 : 0,
                             current->pid, smp_processor_id(), current->comm);

        if (--data->loops) {
                data->prevjiffies = j;
                if (data->hi)
                        tasklet_hi_schedule(&data->tlet);
                else
                        tasklet_schedule(&data->tlet);
        } else {
                wake_up_interruptible(&data->wait);
        }
}

/* the /proc function: allocate everything to allow concurrency */
int jit_tasklet(char *buf, char **start, off_t offset,
              int len, int *eof, void *arg)
{
        struct jit_data *data;
        char *buf2 = buf;
        unsigned long j = jiffies;
        long hi = (long)arg;

        data = kmalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;

        init_waitqueue_head (&data->wait);

        /* write the first lines in the buffer */
        buf2 += sprintf(buf2, "   time   delta  inirq    pid   cpu command\n");
        buf2 += sprintf(buf2, "%9li  %3li     %i    %6i   %i   %s\n",
                        j, 0L, in_interrupt() ? 1 : 0,
                        current->pid, smp_processor_id(), current->comm);

        /* fill the data for our tasklet function */
        data->prevjiffies = j;
        data->buf = buf2;
        data->loops = JIT_ASYNC_LOOPS;
        
        /* register the tasklet */
        tasklet_init(&data->tlet, jit_tasklet_fn, (unsigned long)data);
        data->hi = hi;
        if (hi)
                tasklet_hi_schedule(&data->tlet);
        else
                tasklet_schedule(&data->tlet);

        /* wait for the buffer to fill */
        wait_event_interruptible(data->wait, !data->loops);

        if (signal_pending(current))
                return -ERESTARTSYS;
        buf2 = data->buf;
        kfree(data);
        *eof = 1;
        return buf2 - buf;
}



int __init jit_init(void)
{
        create_proc_read_entry("currentime", 0, NULL, jit_currentime, NULL);
        create_proc_read_entry("jitbusy", 0, NULL, jit_fn, (void *)JIT_BUSY);
        create_proc_read_entry("jitsched",0, NULL, jit_fn, (void *)JIT_SCHED);
        create_proc_read_entry("jitqueue",0, NULL, jit_fn, (void *)JIT_QUEUE);
        create_proc_read_entry("jitschedto", 0, NULL, jit_fn, (void *)JIT_SCHEDTO);

        create_proc_read_entry("jitimer", 0, NULL, jit_timer, NULL);
        create_proc_read_entry("jitasklet", 0, NULL, jit_tasklet, NULL);
        create_proc_read_entry("jitasklethi", 0, NULL, jit_tasklet, (void *)1);

        return 0; /* success */
}

void __exit jit_cleanup(void)
{
        remove_proc_entry("currentime", NULL);
        remove_proc_entry("jitbusy", NULL);
        remove_proc_entry("jitsched", NULL);
        remove_proc_entry("jitqueue", NULL);
        remove_proc_entry("jitschedto", NULL);

        remove_proc_entry("jitimer", NULL);
        remove_proc_entry("jitasklet", NULL);
        remove_proc_entry("jitasklethi", NULL);
}

module_init(jit_init);
module_exit(jit_cleanup);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值