On Sat, 24 Mar 2007 16:51:38 -0700 Wink Saville wrote:

> This is the Trec driver, Makefile, header files.
> Enable trec in Kernel hacking configuration menu.
> 
> Signed-off-by: Wink Saville <[EMAIL PROTECTED]>
> ---

> diff --git a/drivers/trec/trec.c b/drivers/trec/trec.c
> new file mode 100644
> index 0000000..0b04b71
> --- /dev/null
> +++ b/drivers/trec/trec.c
> @@ -0,0 +1,404 @@
...
> +
> +struct trec_dev_struct
> +{
> +     struct  cdev            cdev;                   /* Character device 
> structure */

Fit in 80 columns, please.

> +};
> +
> +MODULE_AUTHOR("Wink Saville");
> +MODULE_LICENSE("Dual BSD/GPL");
> +
> +/*
> + * Module parameters
> + */
> +int major = 240;     /* 240 a "local/expermental" device number for the 
> moment */
> +int minor = 1;
> +
> +module_param(major, int, S_IRUGO);
> +module_param(minor, int, S_IRUGO);
> +
> +/*
> + * Forward declarations
> + */
> +static int trec_open(struct inode *inode, struct file *file);
> +static int trec_release(struct inode *inode, struct file *file);
> +
> +/*
> + * File operations
> + */
> +struct file_operations trec_f_ops = {
> +     .owner          =       THIS_MODULE,
> +     .open           =       trec_open,
> +     .release        =       trec_release,
> +};
> +
> +struct trec_struct {
> +     uint64_t        tsc;
> +     unsigned long   pc;
> +     unsigned long   tsk;
> +     unsigned int    pid;
> +     unsigned long   v1;
> +     unsigned long   v2;
> +};
> +
> +/*
> + * Change trec_buffer_struct.data to be a pointer to a PAGE in the future
> + */
> +#define TREC_DATA_SIZE 0x200
> +struct trec_buffer_struct {
> +     struct trec_buffer_struct *     next;
> +     struct trec_struct *            cur;
> +     struct trec_struct *            end;
> +     struct trec_struct              data[TREC_DATA_SIZE];

Kernel style is:
        sturct trec_struct              *cur;

> +};
> +
> +/*
> + * Number of buffers must be a multiple of two so we can
> + * snapshot the buffers and the minimum should be 4.
> + */
> +#define      TREC_COUNT 2
> +struct trec_buffer_struct    trec_buffers[2][TREC_COUNT];
> +int                          trec_idx = 0;
> +spinlock_t                   trec_lock = SPIN_LOCK_UNLOCKED;
> +
> +struct trec_buffer_struct *  trec_buffer_cur = NULL;
> +struct trec_buffer_struct *  trec_buffer_snapshot = NULL;

Pointer style.  + don't init to NULL.

> +
> +struct trec_dev_struct               trec_dev;
> +
> +/**
> + * Print an address symbol if available to the buffer
> + * this is from traps.c
> + */

Don't use kernel-doc indicator ("/**") unless the function block
comment is actually in kernel-doc syntax (see
Documentation/kernel-doc-nano-HOWTO.txt).

> +static int snprint_address(char *b, int bsize, unsigned long address)
> +{
> +#ifdef CONFIG_KALLSYMS
> +     unsigned long offset = 0, symsize;
> +     const char *symname;
> +     char *modname;
> +     char *delim = ":";
> +     int n;
> +     char namebuf[128];
> +
> +     symname = kallsyms_lookup(address, &symsize, &offset, &modname, 
> namebuf);
> +     if (!symname) {
> +             n = 0;
> +     } else {
> +             if (!modname)
> +                     modname = delim = "";           
> +             n = snprintf(b, bsize, "0x%016lx %s%s%s%s+0x%lx/0x%lx",
> +                     address, delim, modname, delim, symname, offset, 
> symsize);
> +     }
> +     return n;
> +#else
> +     return snprintf(b, bsize, "0x%016lx", address);
> +#endif
> +}

> +/*
> + * Snapshot the current trecs
> + */
> +void trec_snapshot(void)
> +{
> +     int flags;
> +
> +     spin_lock_irqsave(&trec_lock, flags);
> +     trec_buffer_snapshot = trec_buffer_cur;
> +     trec_idx = trec_idx ^ 1;
> +     trec_buffer_cur = &trec_buffers[trec_idx][0];
> +     spin_unlock_irqrestore(&trec_lock, flags);
> +}
> +EXPORT_SYMBOL(trec_snapshot);

What (if anything) prevents multiple snapshots from overwriting
each other, or from being overwritten while one is printing?

> +/*
> + * trec_print
> + */
> +void trec_print_snapshot(void)
> +{
> +     int i;
> +     struct trec_buffer_struct *cur_buffer;
> +
> +     if (!trec_buffer_snapshot)
> +             trec_snapshot();
> +
> +     cur_buffer = trec_buffer_snapshot->next;
> +     for (i = 0; i < TREC_COUNT; i++) {
> +             struct trec_struct *cur;
> +
> +             for (cur = &cur_buffer->data[0];
> +                     cur < cur_buffer->cur;
> +                     cur += 1) {
> +                     char b[256];
> +                     int n;
> +                     
> +                     n = snprintf(b, sizeof(b), KERN_ERR "t=%20llu pid=%5u 
> tsk=%p v1=%p v2=%p ",
> +                             cur->tsc, cur->pid, (void *)cur->tsk, (void 
> *)cur->v1, (void *)cur->v2);
> +                     n += snprint_address(b+n, sizeof(b)-n, cur->pc);
> +                     printk("%s\n", b);
> +             }
> +             cur_buffer = cur_buffer->next;
> +     }
> +}
> +EXPORT_SYMBOL(trec_print_snapshot);
> +
> +/*
> + * Sysrq support for trec's
> + */
> +#ifdef CONFIG_MAGIC_SYSRQ
> +/*
> + * trec print snapshot handler for sysrq
> + */
> +static void sysrq_handle_trec_print_snapshot(int key, struct tty_struct 
> *tty) 
> +{
> +     trec_print_snapshot();
> +}
> +
> +/*
> + * trec snapshot handler for sysrq
> + */
> +static void sysrq_handle_trec_snapshot(int key, struct tty_struct *tty) 
> +{
> +     trec_snapshot();
> +}
> +
> +static struct sysrq_key_op sysrq_trec_snapshot_op = 
> +{
> +     .handler =      sysrq_handle_trec_snapshot,
> +     .help_msg =     "Trec snapshot(Y)",
> +     .action_msg =   "Trec snapshot",
> +};
> +
> +static struct sysrq_key_op sysrq_trec_print_snapshot_op = 
> +{
> +     .handler =      sysrq_handle_trec_print_snapshot,
> +     .help_msg =     "Print current trec snapshot",

(Z) should be on the help_msg, not on the action_msg.

> +     .action_msg =   "Trec print snapshot(Z)",
> +};
> +
> +/*
> + * Initilize trec sysrq support

      Initialize

> + */
> +static int __init setup_trec_sysrq(void)
> +{
> +     DPK("setup_trec_sysrq y=trec_snapshot z=trec_print_snapshot\n");
> +     register_sysrq_key('y', &sysrq_trec_snapshot_op);
> +     register_sysrq_key('z', &sysrq_trec_print_snapshot_op);
> +     return 0;
> +}
> +__initcall(setup_trec_sysrq);
> +#endif /* CONFIG_MAGIC_SYSRQ */

> +/*
> + * Init routine for the trec device
> + */
> +static int __init trec_device_init(void)
> +{
> +     int             result;
> +     dev_t           dev_number = 0;
> +     static struct   class *trec_class;
> +
> +     DPK("trec_device_init: E\n");
> +
> +     if (major) {
> +             dev_number = MKDEV(major, minor);
> +             result = register_chrdev_region(dev_number, 1, "trec");
> +             DPK("trec_device_init: static major result=%d\n", result);
> +     } else {
> +             result = alloc_chrdev_region(&dev_number, minor, 1, "trec");
> +             major = MAJOR(dev_number);
> +             DPK("trec_device_init: dynamic major result=%d\n", result);
> +     }       
> +
> +     if (result < 0) {
> +             printk(KERN_WARNING "trec: can't get major %d\n", major);
> +             goto err;
> +     }
> +
> +     cdev_init(&trec_dev.cdev, &trec_f_ops);
> +     trec_dev.cdev.owner = THIS_MODULE;
> +     trec_dev.cdev.ops = &trec_f_ops;
> +     
> +     result = cdev_add(&trec_dev.cdev, dev_number, 1);
> +     if (result)
> +     {
> +             DPK("trec_device_init: cdev_add failed\n");
> +             goto err;
> +     }
> +
> +     /*
> +      * Make a trec class and create the device
> +      */
> +     trec_class = class_create(THIS_MODULE, "trec");
> +     class_device_create(trec_class, NULL, dev_number, NULL, "trec");
> +
> +     /*
> +      * If the trec buffers have not been initialized do so
> +      */
> +     if (trec_buffer_cur == NULL) {
> +             trec_init();
> +     }

Style: no braces on one-statement "blocks".

> +}

> diff --git a/include/asm-i386/trec.h b/include/asm-i386/trec.h
> new file mode 100644
> index 0000000..1de4dc6
> --- /dev/null
> +++ b/include/asm-i386/trec.h
> @@ -0,0 +1,33 @@
> +/*
> + * Copyright (C) 2007 Saville Software, Inc.
> + *
> + * This code may be used for any purpose whatsoever, but
> + * no warranty of any kind is provided.
> + */
> +
> +#ifndef _ASM_I386_TREC_H
> +#define _ASM_I386_TREC_H
> +
> +#ifndef __ASSEMBLY__
> +
> +#if CONFIG_X86_TSC 
> +#include <asm/msr.h>
> +
> +/*
> + * read x86 time stamp counter.
> + */
> +static uint64_t inline rd_tsc(void)
> +{
> +     volatile uint64_t value;
> +
> +     rdtscll(value);
> +
> +     return value;
> +}
> +#else
> +     #define rd_tsc() (0)

We don't typically indent (#if/) #else block contents like this.

> +#endif /* CONFIG_X86_TSC */
> +
> +#endif /* !__ASSEMBLY__ */
> +
> +#endif /* _ASM_I386_TREC_H */

> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index 3f3e740..db53fdb 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -303,6 +303,13 @@ config STACKTRACE
>       depends on DEBUG_KERNEL
>       depends on STACKTRACE_SUPPORT
>  
> +config TREC
> +     def_bool n
> +     bool "Trace record support"
> +     depends on DEBUG_KERNEL
> +     help
> +       Trace records are a light weight tracing facility

                              lightweight   ...    facility.

> +
>  config DEBUG_KOBJECT
>       bool "kobject debugging"
>       depends on DEBUG_KERNEL


---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to