|  | /* Copyright (c) 2011 The Regents of the University of California | 
|  | * Barret Rhoden <brho@cs.berkeley.edu> | 
|  | * See LICENSE for details. | 
|  | * | 
|  | * Alarms.  This includes various ways to sleep for a while or defer work on a | 
|  | * specific timer.  These can be per-core, global or whatever.  Deferred work | 
|  | * is a function pointer which runs in interrupt context when the alarm goes off | 
|  | * (picture running the ksched then).  The other style is to block/sleep on the | 
|  | * awaiter after the alarm is set. | 
|  | * | 
|  | * Like with most systems, you won't wake up til after the time you specify (for | 
|  | * now).  This might change, esp if we tweak things to coalesce alarms. | 
|  | * | 
|  | * All tchains come with locks.  Originally, I left these out, since the pcpu | 
|  | * tchains didn't need them (disable_irq was sufficient).  However, disabling | 
|  | * alarms remotely (a valid use case) is a real pain without locks, so now | 
|  | * everyone has locks.  As an added benefit, you can submit an alarm to another | 
|  | * core's pcpu tchain (though it probably costs an extra IRQ).  Note there is a | 
|  | * lock ordering, tchains before awaiters (when they are grabbed together). | 
|  | * | 
|  | * There are two options for pcpu alarms: hard IRQ and routine KMSG (RKM). | 
|  | * IRQ alarms are run directly in the timer interrupt handler and take a hw_tf | 
|  | * parameter in addition to the standard alarm_waiter.  RKM alarms are executed | 
|  | * when kernel messages are executed, which is out of IRQ context.  RKMs are | 
|  | * safer, since you can sleep (qlock, some kmalloc, etc) and you do not need | 
|  | * irqsave locks. | 
|  | * | 
|  | * Another important difference between IRQ and RKM alarms comes when cancelling | 
|  | * or unsetting an alarm.  When you cancel (unset or reset) an alarm, the alarm | 
|  | * is yanked off the tchain.  If the waiter was on the chain, then it will not | 
|  | * fire for both IRQ and RKM alarms.  If the waiter was not on the chain, then | 
|  | * for IRQ alarms, this means that the alarm has already fired.  However, for | 
|  | * RKM alarms, the alarm may have already fired or it may still be waiting to | 
|  | * fire (sitting in an RKM queue).  It will fire at some point, but perhaps it | 
|  | * has not fired yet.  It is also possibly (though extremely unlikely) that if | 
|  | * you reset an RKM alarm that the new alarm actually happens before the old one | 
|  | * (if the new RKM was sent to another core). | 
|  | * | 
|  | * To use an IRQ alarm, init the waiter with init_awaiter_irq(). | 
|  | * | 
|  | * Quick howto, using the pcpu tchains: | 
|  | * 	struct timer_chain *tchain = &per_cpu_info[core_id()].tchain; | 
|  | * 1) To block your kthread on an alarm: | 
|  | * 	struct alarm_waiter a_waiter; | 
|  | * 	init_awaiter(&a_waiter, 0); // or init_awaiter_irq() for IRQ ctx alarms | 
|  | * 	set_awaiter_rel(&a_waiter, USEC); | 
|  | * 	set_alarm(tchain, &a_waiter); | 
|  | * 	sleep_on_awaiter(&a_waiter); | 
|  | * 2) To set a handler to run on an alarm: | 
|  | * 	struct alarm_waiter *waiter = kmalloc(sizeof(struct alarm_waiter), 0); | 
|  | * 	init_awaiter(waiter, HANDLER); | 
|  | * 	set_awaiter_rel(waiter, USEC); | 
|  | * 	set_alarm(tchain, waiter); | 
|  | * If you want the HANDLER to run again, do this at the end of it: | 
|  | * 	set_awaiter_rel(waiter, USEC);	// or whenever you want it to fire | 
|  | * 	set_alarm(tchain, waiter); | 
|  | * or: | 
|  | * 	reset_alarm_rel(tchain, waiter, USEC); | 
|  | * | 
|  | * Don't forget to manage your memory at some (safe) point: | 
|  | * 	kfree(waiter); | 
|  | * In the future, we might have a slab for these.  You can get it from wherever | 
|  | * you want, just don't use the stack for handler style, since you'll usually | 
|  | * return and pop up the stack after setting the alarm. | 
|  | * */ | 
|  |  | 
|  | #ifndef ROS_KERN_ALARM_H | 
|  | #define ROS_KERN_ALARM_H | 
|  |  | 
|  | #include <ros/common.h> | 
|  | #include <sys/queue.h> | 
|  | #include <kthread.h> | 
|  |  | 
|  | /* These structures allow code to block or defer work for a certain amount of | 
|  | * time.  Timer chains (like off a per-core timer) are made of lists/trees of | 
|  | * these. | 
|  | * | 
|  | * If you have a func pointer, that handler will run when the alarm goes off. | 
|  | * If you don't have a func pointer, you sleep on the semaphore and block your | 
|  | * kthread.  In the latter case, you ought to allocate space for them on the | 
|  | * stack of the thread you're about to block on. */ | 
|  | struct alarm_waiter { | 
|  | uint64_t 					wake_up_time;	/* ugh, this is a TSC for now */ | 
|  | union { | 
|  | void (*func) (struct alarm_waiter *waiter); | 
|  | void (*func_irq) (struct alarm_waiter *waiter, | 
|  | struct hw_trapframe *hw_tf); | 
|  | struct semaphore			sem;		/* kthread will sleep on this */ | 
|  | }; | 
|  | void						*data; | 
|  | TAILQ_ENTRY(alarm_waiter)	next; | 
|  | bool						on_tchain; | 
|  | bool						irq_ok; | 
|  | bool						holds_tchain_lock; | 
|  | bool						has_func; | 
|  | }; | 
|  | TAILQ_HEAD(awaiters_tailq, alarm_waiter);		/* ideally not a LL */ | 
|  |  | 
|  | typedef void (*alarm_handler)(struct alarm_waiter *waiter); | 
|  |  | 
|  | /* One of these per alarm source, such as a per-core timer.  All tchains come | 
|  | * with a lock, even if its rarely needed (like the pcpu tchains). | 
|  | * set_interrupt() is a method for setting the interrupt source. */ | 
|  | struct timer_chain { | 
|  | spinlock_t					lock; | 
|  | struct awaiters_tailq		waiters; | 
|  | uint64_t					earliest_time; | 
|  | uint64_t					latest_time; | 
|  | void (*set_interrupt) (uint64_t time, struct timer_chain *); | 
|  | }; | 
|  |  | 
|  | /* Called once per timer chain, currently in per_cpu_init() */ | 
|  | void init_timer_chain(struct timer_chain *tchain, | 
|  | void (*set_interrupt) (uint64_t, struct timer_chain *)); | 
|  | /* For fresh alarm waiters.  func == 0 for kthreads */ | 
|  | void init_awaiter(struct alarm_waiter *waiter, | 
|  | void (*func) (struct alarm_waiter *)); | 
|  | void init_awaiter_irq(struct alarm_waiter *waiter, | 
|  | void (*func_irq) (struct alarm_waiter *awaiter, | 
|  | struct hw_trapframe *hw_tf)); | 
|  | /* Sets the time an awaiter goes off */ | 
|  | void set_awaiter_abs(struct alarm_waiter *waiter, uint64_t abs_time); | 
|  | void set_awaiter_rel(struct alarm_waiter *waiter, uint64_t usleep); | 
|  | void set_awaiter_inc(struct alarm_waiter *waiter, uint64_t usleep); | 
|  | /* Arms/disarms the alarm. */ | 
|  | void set_alarm(struct timer_chain *tchain, struct alarm_waiter *waiter); | 
|  | bool unset_alarm(struct timer_chain *tchain, struct alarm_waiter *waiter); | 
|  | bool reset_alarm_abs(struct timer_chain *tchain, struct alarm_waiter *waiter, | 
|  | uint64_t abs_time); | 
|  | bool reset_alarm_rel(struct timer_chain *tchain, struct alarm_waiter *waiter, | 
|  | uint64_t usleep); | 
|  |  | 
|  | /* Blocks on the alarm waiter */ | 
|  | int sleep_on_awaiter(struct alarm_waiter *waiter); | 
|  | /* Interrupt handlers need to call this.  Don't call it directly. */ | 
|  | void __trigger_tchain(struct timer_chain *tchain, struct hw_trapframe *hw_tf); | 
|  | /* How to set a specific alarm: the per-cpu timer interrupt */ | 
|  | void set_pcpu_alarm_interrupt(uint64_t time, struct timer_chain *tchain); | 
|  |  | 
|  | /* Debugging */ | 
|  | #define ALARM_POISON_TIME 12345				/* could use some work */ | 
|  | void print_chain(struct timer_chain *tchain); | 
|  | void print_pcpu_chains(void); | 
|  |  | 
|  | #endif /* ROS_KERN_ALARM_H */ |