Remove the alarm-with-no-func use case
The old version allowed you to just block on a semaphore if you passed '0'
for the function. No one was using it, and it complicated the
implementation. Its functionality has been superceded by functions like
kthread_usleep().
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/include/alarm.h b/kern/include/alarm.h
index 2b62360..b0bb52c 100644
--- a/kern/include/alarm.h
+++ b/kern/include/alarm.h
@@ -5,8 +5,7 @@
* 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.
+ * (picture running the ksched then).
*
* 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.
@@ -40,17 +39,14 @@
*
* 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:
+ * To block your kthread on an alarm:
* struct alarm_waiter *waiter = kmalloc(sizeof(struct alarm_waiter), 0);
- * init_awaiter(waiter, HANDLER);
+ * struct alarm_waiter a_waiter; // or use the stack
+ *
+ * init_awaiter(waiter, HANDLER); // or init_awaiter_irq() for IRQ ctx alarms
* 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);
@@ -60,9 +56,7 @@
* 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.
- * */
+ * you want, just be careful if you use the stack. */
#pragma once
@@ -70,28 +64,20 @@
#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. */
+/* These structures allow code to defer work for a certain amount of time.
+ * Timer chains (like off a per-core timer) are made of lists/trees of these. */
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 */
@@ -129,8 +115,6 @@
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);
/* Sets the timer chain interrupt according to the next timer in the chain. */
diff --git a/kern/src/alarm.c b/kern/src/alarm.c
index 1fbf7d2..df1efba 100644
--- a/kern/src/alarm.c
+++ b/kern/src/alarm.c
@@ -2,10 +2,9 @@
* 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. Like with most
- * systems, you won't wake up til after the time you specify. (for now, this
- * might change).
+ * Alarms. This includes ways to defer work on a specific timer. These can be
+ * per-core, global or whatever. Like with most systems, you won't wake up til
+ * after the time you specify. (for now, this might change).
*
* TODO:
* - have a kernel sense of time, instead of just the TSC or whatever timer the
@@ -46,23 +45,19 @@
reset_tchain_times(tchain);
}
-/* Initializes a new awaiter. Pass 0 for the function if you want it to be a
- * kthread-alarm, and sleep on it after you set the alarm later. */
static void __init_awaiter(struct alarm_waiter *waiter)
{
waiter->wake_up_time = ALARM_POISON_TIME;
waiter->on_tchain = FALSE;
waiter->holds_tchain_lock = FALSE;
- if (!waiter->has_func)
- sem_init_irqsave(&waiter->sem, 0);
}
void init_awaiter(struct alarm_waiter *waiter,
void (*func) (struct alarm_waiter *awaiter))
{
waiter->irq_ok = FALSE;
- waiter->has_func = func ? TRUE : FALSE;
- waiter->func = func; /* if !func, this is a harmless zeroing */
+ assert(func);
+ waiter->func = func;
__init_awaiter(waiter);
}
@@ -71,8 +66,8 @@
struct hw_trapframe *hw_tf))
{
waiter->irq_ok = TRUE;
- waiter->has_func = func_irq ? TRUE : FALSE;
- waiter->func_irq = func_irq; /* if !func, this is a harmless zeroing */
+ assert(func_irq);
+ waiter->func_irq = func_irq;
__init_awaiter(waiter);
}
@@ -129,22 +124,16 @@
waiter->func(waiter);
}
-/* When an awaiter's time has come, this gets called. If it was a kthread, it
- * will wake up. o/w, it will call the func ptr stored in the awaiter. */
static void wake_awaiter(struct alarm_waiter *waiter,
struct hw_trapframe *hw_tf)
{
- if (waiter->has_func) {
- if (waiter->irq_ok) {
- waiter->holds_tchain_lock = TRUE;
- waiter->func_irq(waiter, hw_tf);
- waiter->holds_tchain_lock = FALSE;
- } else {
- send_kernel_message(core_id(), __run_awaiter, (long)waiter,
- 0, 0, KMSG_ROUTINE);
- }
+ if (waiter->irq_ok) {
+ waiter->holds_tchain_lock = TRUE;
+ waiter->func_irq(waiter, hw_tf);
+ waiter->holds_tchain_lock = FALSE;
} else {
- sem_up(&waiter->sem); /* IRQs are disabled, can call sem_up directly */
+ send_kernel_message(core_id(), __run_awaiter, (long)waiter,
+ 0, 0, KMSG_ROUTINE);
}
}
@@ -350,20 +339,6 @@
return ret;
}
-/* Attempts to sleep on the alarm. Could fail if you aren't allowed to kthread
- * (process limit, etc). Don't call it on a waiter that is an event-handler. */
-int sleep_on_awaiter(struct alarm_waiter *waiter)
-{
- int8_t irq_state = 0;
- if (waiter->has_func)
- panic("Tried blocking on a waiter %p with a func %p!", waiter,
- waiter->func);
- /* Put the kthread to sleep. TODO: This can fail (or at least it will be
- * able to in the future) and we'll need to handle that. */
- sem_down_irqsave(&waiter->sem, &irq_state);
- return 0;
-}
-
/* Sets the timer interrupt for the timer chain passed as parameter.
* The next interrupt will be scheduled at the nearest timer available in the
* chain.
@@ -432,23 +407,17 @@
tchain->earliest_time,
tchain->latest_time);
TAILQ_FOREACH(i, &tchain->waiters, next) {
- if (i->has_func) {
- uintptr_t f;
- if (i->irq_ok)
- f = (uintptr_t)i->func_irq;
- else
- f = (uintptr_t)i->func;
- char *f_name = get_fn_name(f);
- printk("\tWaiter %p, time %llu, func %p (%s)\n", i,
- i->wake_up_time, f, f_name);
- kfree(f_name);
- continue;
- }
- struct kthread *kthread = TAILQ_FIRST(&i->sem.waiters);
- printk("\tWaiter %p, time: %llu, kthread: %p (%p) %s\n", i,
- i->wake_up_time, kthread, (kthread ? kthread->proc : 0),
- (kthread ? kthread->name : 0));
+ uintptr_t f;
+ char *f_name;
+ if (i->irq_ok)
+ f = (uintptr_t)i->func_irq;
+ else
+ f = (uintptr_t)i->func;
+ f_name = get_fn_name(f);
+ printk("\tWaiter %p, time %llu, func %p (%s)\n", i,
+ i->wake_up_time, f, f_name);
+ kfree(f_name);
}
spin_unlock_irqsave(&tchain->lock);
}