# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/08/16 23:51:06-04:00 jeffpc@optonline.net # [WATCH64] Fixed syntax error in watch64.h # # Signed-off-by: Josef 'Jeff' Sipek # # include/linux/watch64.h # 2004/08/16 23:50:55-04:00 jeffpc@optonline.net +1 -1 # Fixed syntax error # # ChangeSet # 2004/07/15 09:18:51-04:00 jeffpc@optonline.net # [WATCH64] Update due to RCU API change # # Signed-off-by: Josef 'Jeff' Sipek # # kernel/watch64.c # 2004/07/14 16:41:26-04:00 jeffpc@optonline.net +3 -3 # Update due to RCU API change # # include/linux/watch64.h # 2004/07/14 16:41:26-04:00 jeffpc@optonline.net +1 -1 # Update due to RCU API change # # ChangeSet # 2004/06/27 02:02:40-04:00 jeffpc@optonline.net # Merge optonline.net:/home/jeffpc/linux/linux-2.5 # into optonline.net:/home/jeffpc/linux/watch64 # # kernel/Makefile # 2004/06/27 02:02:36-04:00 jeffpc@optonline.net +0 -0 # Auto merged # # ChangeSet # 2004/06/22 22:04:13-04:00 jeffpc@optonline.net # Merge optonline.net:/home/jeffpc/linux/linux-2.5 # into optonline.net:/home/jeffpc/linux/watch64 # # kernel/Makefile # 2004/06/22 22:04:10-04:00 jeffpc@optonline.net +0 -0 # Auto merged # # ChangeSet # 2004/06/06 15:08:21-04:00 jeffpc@optonline.net # Merge optonline.net:/home/jeffpc/linux/linux-2.5 # into optonline.net:/home/jeffpc/linux/watch64 # # kernel/Makefile # 2004/06/06 15:08:16-04:00 jeffpc@optonline.net +0 -0 # Auto merged # # ChangeSet # 2004/03/18 19:49:27-05:00 jeffpc@optonline.net # Merge # # Documentation/00-INDEX # 2004/03/18 19:49:24-05:00 jeffpc@optonline.net +0 -0 # SCCS merged # # kernel/Makefile # 2004/03/18 19:46:04-05:00 jeffpc@optonline.net +0 -0 # Auto merged # # ChangeSet # 2004/02/19 13:58:11-05:00 jeffpc@optonline.net # [WATCH64] Use u_int64_t, it is the standard # # kernel/watch64.c # 2004/02/19 13:58:03-05:00 jeffpc@optonline.net +4 -4 # Use u_int64_t, it is the standard # # include/linux/watch64.h # 2004/02/19 13:58:03-05:00 jeffpc@optonline.net +2 -2 # Use u_int64_t, it is the standard # # Documentation/watch64.txt # 2004/02/19 13:58:03-05:00 jeffpc@optonline.net +1 -1 # Use u_int64_t, it is the standard # # ChangeSet # 2004/02/19 13:22:58-05:00 jeffpc@optonline.net # Fixed merge conflict # # kernel/Makefile # 2004/02/19 13:22:50-05:00 jeffpc@optonline.net +1 -3 # Fixed merge conflict # # ChangeSet # 2004/01/09 06:43:13-05:00 jeffpc@optonline.net # [WATCH64] Use u64 instead of u_int64_t # # kernel/watch64.c # 2004/01/09 06:43:06-05:00 jeffpc@optonline.net +4 -4 # Use u64 instead of u_int64_t # # include/linux/watch64.h # 2004/01/09 06:43:06-05:00 jeffpc@optonline.net +2 -2 # Use u64 instead of u_int64_t # # Documentation/watch64.txt # 2004/01/09 06:43:06-05:00 jeffpc@optonline.net +1 -1 # Use u64 instead of u_int64_t # # ChangeSet # 2003/10/20 06:56:02-04:00 jeffpc@jeff.home # Added watch64 API description (Documentation/watch64.txt) # # Documentation/00-INDEX # 2003/10/20 06:55:56-04:00 jeffpc@jeff.home +2 -0 # watch64 API description added # # Documentation/watch64.txt # 2003/10/20 06:55:03-04:00 jeffpc@jeff.home +35 -0 # # Documentation/watch64.txt # 2003/10/20 06:55:03-04:00 jeffpc@jeff.home +0 -0 # BitKeeper file /home/jeffpc/linux/linux-watch64-work/Documentation/watch64.txt # # ChangeSet # 2003/10/16 22:13:56-04:00 jeffpc@jeff.home # Merge jeff.home:/home/jeffpc/linux/linux-2.5 # into jeff.home:/home/jeffpc/linux/linux-watch64 # # kernel/Makefile # 2003/10/16 22:13:51-04:00 jeffpc@jeff.home +0 -0 # Auto merged # # ChangeSet # 2003/09/27 20:54:43-04:00 jeffpc@optonline.net # __foo() for watch64_find(), watch64_disable(), watch64_enable() # Removed unneeded error check (from very old code) # Fix rcu_read_{un,}lock() bugs # # kernel/watch64.c # 2003/09/27 20:54:35-04:00 jeffpc@optonline.net +84 -21 # __foo() for watch64_find(), watch64_disable(), watch64_enable() # Removed unneeded error check (from very old code) # Fix rcu_read_{un,}lock() bugs # # include/linux/watch64.h # 2003/09/27 20:54:35-04:00 jeffpc@optonline.net +3 -0 # __foo() for watch64_find(), watch64_disable(), watch64_enable() # # ChangeSet # 2003/09/27 18:44:16-04:00 jeffpc@optonline.net # RCU # # kernel/watch64.c # 2003/09/27 18:44:08-04:00 jeffpc@optonline.net +25 -15 # RCU # # include/linux/watch64.h # 2003/09/27 18:44:08-04:00 jeffpc@optonline.net +3 -1 # RCU # # ChangeSet # 2003/09/21 11:27:35-04:00 jeffpc@jeff.home # Added copyright notice # # kernel/watch64.c # 2003/09/21 11:27:27-04:00 jeffpc@jeff.home +11 -0 # Added copyright notice # # include/linux/watch64.h # 2003/09/21 11:27:27-04:00 jeffpc@jeff.home +11 -0 # Added copyright notice # # ChangeSet # 2003/09/21 11:05:26-04:00 jeffpc@jeff.home # watch64.patch # # kernel/watch64.c # 2003/09/20 23:09:22-04:00 jeffpc@jeff.home +308 -0 # Import patch watch64.patch # # kernel/watch64.c # 2003/09/20 23:09:22-04:00 jeffpc@jeff.home +0 -0 # BitKeeper file /home/jeffpc/linux/linux-watch64/kernel/watch64.c # # kernel/Makefile # 2003/09/20 23:07:26-04:00 jeffpc@jeff.home +2 -1 # Import patch watch64.patch # # include/linux/watch64.h # 2003/09/20 23:13:02-04:00 jeffpc@jeff.home +47 -0 # Import patch watch64.patch # # include/linux/watch64.h # 2003/09/20 23:13:02-04:00 jeffpc@jeff.home +0 -0 # BitKeeper file /home/jeffpc/linux/linux-watch64/include/linux/watch64.h # diff -Nru a/Documentation/00-INDEX b/Documentation/00-INDEX --- a/Documentation/00-INDEX 2004-08-17 00:43:20 -04:00 +++ b/Documentation/00-INDEX 2004-08-17 00:43:20 -04:00 @@ -250,6 +250,8 @@ - directory with info regarding video/TV/radio cards and linux. vm/ - directory with info on the Linux vm code. +watch64.txt + - watch64 API description watchdog/ - how to auto-reboot Linux if it has "fallen and can't get up". ;-) x86_64/ diff -Nru a/Documentation/watch64.txt b/Documentation/watch64.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/watch64.txt 2004-08-17 00:43:20 -04:00 @@ -0,0 +1,35 @@ +int watch64_register(unsigned long* ptr, unsigned int interval); + + - Registers *ptr to be monitored every interval jiffies. + - If interval==0, WATCH64_INTERVAL will be used (HZ/10 by default) + +int watch64_unregister(unsigned long* ptr, struct watch64* st); + + - Unregister *ptr + - st is optional pointer to the struct containing the registration + information + - if st==NULL, it will be looked up automatically + +struct watch64* watch64_find(unsigned long* ptr); + + - Return struct with registration information of *ptr + +int watch64_disable(unsigned long* ptr, struct watch64* st); + + - Disable *ptr from being monitored, without removing it from the list + - st is optional (see watch64_unregister for more information) + +int watch64_enable(unsigned long* ptr, struct watch64* st); + + - Enable *ptr from being monitored (opposite of watch64_disable) + - st is optional (see watch64_unregister for more information) + +int watch64_toggle(unsigned long* ptr, struct watch64* st); + + - Toggle the enable/disable status + - st is optional (see watch64_unregister for more information) + +inline u_int64_t watch64_getval(unsigned long* ptr, struct watch64* st); + + - Return the whole 64-bit counter + - st is optional (see watch64_unregister for more information) diff -Nru a/include/linux/watch64.h b/include/linux/watch64.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/linux/watch64.h 2004-08-17 00:43:20 -04:00 @@ -0,0 +1,63 @@ +/* + * inclue/linux/watch64.h + * + * Copyright (C) 2003 Josef "Jeff" Sipek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef _LINUX_64WATCH_H +#define _LINUX_64WATCH_H + +#include +#include +#include +#include +#include + +#define WATCH64_INTERVAL (HZ/10) +#define WATCH64_MINIMUM (HZ/20) +#define WATCH64_MAGIC 0x573634 + +#if (BITS_PER_LONG == 64) + +struct watch64 { +}; + +#else + +struct watch64 { + struct list_head list; + unsigned long *ptr; + unsigned long oldval; + u_int64_t total; + unsigned int interval; + int active; + seqlock_t lock; + struct rcu_head rcuhead; +}; + +#endif /* (BITS_PER_LONG == 64) */ + +/* + * Prototypes + */ + +void watch64_init(void); +void watch64_run(unsigned long var); +int watch64_register(unsigned long* ptr, unsigned int interval); +int watch64_unregister(unsigned long* ptr, struct watch64* st); +void watch64_rcufree(struct rcu_head* p); +struct watch64* watch64_find(unsigned long* ptr); +inline struct watch64* __watch64_find(unsigned long* ptr); +int watch64_disable(unsigned long* ptr, struct watch64* st); +inline int __watch64_disable(unsigned long* ptr, struct watch64* st); +int watch64_enable(unsigned long* ptr, struct watch64* st); +inline int __watch64_enable(unsigned long* ptr, struct watch64* st); +int watch64_toggle(unsigned long* ptr, struct watch64* st); +inline u_int64_t watch64_getval(unsigned long* ptr, struct watch64* st); + +#endif /* _LINUX_WATCH64_H */ diff -Nru a/kernel/Makefile b/kernel/Makefile --- a/kernel/Makefile 2004-08-17 00:43:19 -04:00 +++ b/kernel/Makefile 2004-08-17 00:43:19 -04:00 @@ -7,7 +7,7 @@ sysctl.o capability.o ptrace.o timer.o user.o \ signal.o sys.o kmod.o workqueue.o pid.o \ rcupdate.o intermodule.o extable.o params.o posix-timers.o \ - kthread.o + kthread.o watch64.o obj-$(CONFIG_FUTEX) += futex.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o diff -Nru a/kernel/watch64.c b/kernel/watch64.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/kernel/watch64.c 2004-08-17 00:43:20 -04:00 @@ -0,0 +1,392 @@ +/* + * kernel/watch64.c + * + * Copyright (C) 2003 Josef "Jeff" Sipek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Watch64 global variables + */ + +spinlock_t watch64_biglock = SPIN_LOCK_UNLOCKED; +LIST_HEAD(watch64_head); +struct timer_list watch64_timer; +int watch64_setup; + +#if (BITS_PER_LONG == 64) + +void watch64_init(void) +{ +} + +void watch64_run(unsigned long var) +{ +} + +int watch64_register(unsigned long* ptr, unsigned int interval) +{ + return 0; +} + +int watch64_unregister(unsigned long* ptr, struct watch64* st) +{ + return 0; +} + +void watch64_rcufree(void* p) +{ +} + +struct watch64* watch64_find(unsigned long* ptr) +{ + return NULL; +} + +struct watch64* __watch64_find(unsigned long* ptr) +{ + return NULL; +} + +int watch64_disable(unsigned long* ptr, struct watch64* st) +{ + return 0; +} + +int __watch64_disable(unsigned long* ptr, struct watch64* st) +{ + return 0; +} + +int watch64_enable(unsigned long* ptr, struct watch64* st) +{ + return 0; +} + +int __watch64_enable(unsigned long* ptr, struct watch64* st) +{ + return 0; +} + +int watch64_toggle(unsigned long* ptr, struct watch64* st) +{ + return 0; +} + +inline u_int64_t watch64_getval(unsigned long* ptr, struct watch64* st) +{ + return (u_int64_t) *ptr; +} + +#else + +/* + * Initiate watch64 system + */ + +void watch64_init(void) +{ + spin_lock(&watch64_biglock); + + if (watch64_setup==WATCH64_MAGIC) { + spin_unlock(&watch64_biglock); + return; + } + + printk(KERN_WARNING "watch64: 2003/08/22 Josef 'Jeff' Sipek \n"); + printk(KERN_WARNING "watch64: Enabling Watch64 extensions..."); + + init_timer(&watch64_timer); + watch64_timer.function = watch64_run; + watch64_timer.data = (unsigned long) NULL; + watch64_timer.expires = jiffies + WATCH64_MINIMUM; + add_timer(&watch64_timer); + + printk("done.\n"); + + watch64_setup = WATCH64_MAGIC; + + spin_unlock(&watch64_biglock); +} + +/* + * Go through the list of registered variables and check them for changes + */ + +void watch64_run(unsigned long var) +{ + struct list_head* entry; + struct watch64* watch_struct; + unsigned long tmp; + + rcu_read_lock(); + list_for_each_rcu(entry, &watch64_head) { + watch_struct = list_entry(entry, struct watch64, list); + if (*watch_struct->ptr != watch_struct->oldval) { + tmp = *watch_struct->ptr; + if (tmp > watch_struct->oldval) { + write_seqlock(&watch_struct->lock); + watch_struct->total += tmp - watch_struct->oldval; + write_sequnlock(&watch_struct->lock); + } else if (tmp < watch_struct->oldval) { + write_seqlock(&watch_struct->lock); + watch_struct->total += ((u_int64_t) 1<oldval + tmp; + write_sequnlock(&watch_struct->lock); + } + watch_struct->oldval = tmp; + } + } + rcu_read_unlock(); + + mod_timer(&watch64_timer, jiffies + WATCH64_MINIMUM); +} + +/* + * Register a new variable with watch64 + */ + +int watch64_register(unsigned long* ptr, unsigned int interval) +{ + struct watch64* temp; + + temp = (struct watch64*) kmalloc(sizeof(struct watch64),GFP_ATOMIC); + + if (!temp) + return -ENOMEM; + + if (watch64_setup!=WATCH64_MAGIC) + watch64_init(); + + temp->ptr = ptr; + temp->oldval = 0; + temp->total = 0; + if (interval==0) + temp->interval = WATCH64_INTERVAL; + else if (intervalinterval = WATCH64_MINIMUM; + printk("watch64: attempted to add new watch with interval below %d jiffies",WATCH64_MINIMUM); + } else + temp->interval = interval; + + temp->active = 0; + + seqlock_init(&temp->lock); + + list_add_rcu(&temp->list, &watch64_head); + + return 0; +} + +/* + * Unregister a variable with watch64 + */ + +int watch64_unregister(unsigned long* ptr, struct watch64* st) +{ + rcu_read_lock(); + if (!st) + st = __watch64_find(ptr); + + if (!st) + return -EINVAL; + + __watch64_disable(ptr, st); + list_del_rcu(&st->list); + + call_rcu(&st->rcuhead, watch64_rcufree); + rcu_read_unlock(); + + return 0; +} + +/* + * Free memory via RCU + */ + +void watch64_rcufree(struct rcu_head* p) +{ + kfree(container_of(p, struct watch64, rcuhead)); +} + +/* + * Find watch64 structure with RCU lock + */ + +struct watch64* watch64_find(unsigned long* ptr) +{ + struct watch64* tmp; + + rcu_read_lock(); + tmp = __watch64_find(ptr); + rcu_read_unlock(); + + return tmp; +} + +/* + * Find watch64 structure without RCU lock + */ + +inline struct watch64* __watch64_find(unsigned long* ptr) +{ + struct list_head* tmp; + struct watch64* watch64_struct; + + list_for_each_rcu(tmp, &watch64_head) { + watch64_struct = list_entry(tmp, struct watch64, list); + if (watch64_struct->ptr==ptr) + return watch64_struct; + } + + return NULL; +} + +/* + * Disable a variable watch with RCU lock + */ + +int watch64_disable(unsigned long* ptr, struct watch64* st) +{ + int tmp; + + rcu_read_lock(); + tmp = __watch64_disable(ptr,st); + rcu_read_unlock(); + + return tmp; +} + +/* + * Disable a variable watch without RCU lock + */ + +inline int __watch64_disable(unsigned long* ptr, struct watch64* st) +{ + if (!st) + st = watch64_find(ptr); + + if (!st) + return -EINVAL; + + st->active = 0; + + return 0; +} + +/* + * Enable a variable watch with RCU lock + */ + +int watch64_enable(unsigned long* ptr, struct watch64* st) +{ + int tmp; + + rcu_read_lock(); + tmp = __watch64_enable(ptr,st); + rcu_read_unlock(); + + return tmp; +} + +/* + * Enable a variable watch without RCU lock + */ + +inline int __watch64_enable(unsigned long* ptr, struct watch64* st) +{ + if (!st) + st = __watch64_find(ptr); + + if (!st) + return -EINVAL; + + st->oldval = *ptr; + write_seqlock(&st->lock); + st->total = (u_int64_t) st->oldval; + write_sequnlock(&st->lock); + st->active = 1; + + return 0; +} + +/* + * Toggle a variable watch + */ + +int watch64_toggle(unsigned long* ptr, struct watch64* st) +{ + rcu_read_lock(); + if (!st) + st = __watch64_find(ptr); + + if (!st) { + rcu_read_unlock(); + return -EINVAL; + } + + if (st->active) + __watch64_disable(ptr,st); + else + __watch64_enable(ptr,st); + rcu_read_unlock(); + + return 0; +} + +/* + * Return the total 64-bit value + */ + +inline u_int64_t watch64_getval(unsigned long* ptr, struct watch64* st) +{ + unsigned int seq; + u_int64_t total; + + rcu_read_lock(); + if (!st) + st = __watch64_find(ptr); + + if (!st) { + rcu_read_unlock(); + return *ptr; + } + + do { + seq = read_seqbegin(&st->lock); + total = st->total; + } while (read_seqretry(&st->lock, seq)); + rcu_read_unlock(); + + return total; +} + +#endif /* (BITS_PER_LONG == 64) */ + +/* + * Export all the necessary symbols + */ + +EXPORT_SYMBOL(watch64_register); +EXPORT_SYMBOL(watch64_unregister); +EXPORT_SYMBOL(watch64_find); +EXPORT_SYMBOL(watch64_disable); +EXPORT_SYMBOL(watch64_enable); +EXPORT_SYMBOL(watch64_toggle); +EXPORT_SYMBOL(watch64_getval);