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); }