Commit a72792f9 authored by Charlie Jacobsen's avatar Charlie Jacobsen
Browse files

Add mechanism to abort awe's.

See THCAbort, THCStopAllAwes, THCShouldStop. Like kthread_stop
in the Linux kernel, stopping is voluntary.

Add abort example.

Not built or tested yet.
parent f173e637
Pipeline #642 skipped
......@@ -1136,6 +1136,66 @@ THCFinish(void) {
}
EXPORT_SYMBOL(THCFinish);
void
LIBASYNC_FUNC_ATTR
THCStopAllAwes(void)
{
PTS()->awes_should_stop = 1;
}
EXPORT_SYMBOL(THCStopAllAwes);
int
LIBASYNC_FUNC_ATTR
THCShouldStop(void)
{
return PTS()->awes_should_stop;
}
EXPORT_SYMBOL(THCShouldStop);
void
LIBASYNC_FUNC_ATTR
THCAbort(void) {
PTState_t *pts = PTS();
finish_t *fb = PTS()->current_fb;
assert(fb != NULL);
// Walk back and see if there are any awe's/continuations
// to set up for the code that comes immediately
// after our enclosing asyncs. (This is necessary because
// someone may have called THCAbort before they ever
// yielded. If we didn't initialize any awe_t's that
// came prior, we wouldn't execute any code that follows
// our enclosing ASYNC.)
check_for_lazy_awe(__builtin_frame_address(0));
#ifndef NDEBUG
pts->asyncCallsEnded ++;
#endif
DEBUGPRINTF("Aborting awe in finish block %p\n", fb);
assert(fb->count > 0);
fb->count --;
// Check if we were the last awe to finish in the do-finish block,
// and if someone was waiting for us to finish.
if (fb->count == 0) {
if (fb->finish_awe) {
DEBUGPRINTF("Enclosing finish block reached zero awes; scheduling finish awe %p\n",
fb->finish_awe);
thc_schedule_local(fb->finish_awe);
fb->finish_awe = NULL;
}
}
// Switch to dispatch. Don't try to free stacks. (THCAbort is called
// under exceptional circumstances.)
thc_dispatch(pts);
NOT_REACHED;
}
EXPORT_SYMBOL(THCAbort);
__attribute__ ((unused))
static void thc_suspend_with_cont(void *a, void *arg) {
awe_t *awe = (awe_t*)a;
......
......@@ -291,8 +291,35 @@ void THCSchedule(awe_t *awe_ptr);
void THCScheduleBack(awe_t *awe_ptr);
// Finish the current AWE, returning to the scheduler.
//
// NOTE: If we were waiting for this awe to finish in order to exit
// a do-finish block (there is a do-finish awe that is waiting for the
// do-finish's awe count to reach zero), this *will not* schedule that
// awe. I'm not sure why this wasn't done in the first place.
//
// And so, TODO: clean up enclosing do-finish if we are the last awe.
void THCFinish(void);
// Invoke this to signal to all awe's that they should exit. Right now,
// exiting is voluntary: An awe should call THCShouldStop to detect
// if should terminate. Likely, the awe will want to call THCAbort (see
// below).
void THCStopAllAwes(void);
// Returns non-zero if the calling awe should terminate as soon as
// possible. The awe should probably call THCAbort.
int THCShouldStop(void);
// Like THCFinish, but if we are the last awe in our enclosing do-finish,
// and the do-finish is waiting for us, we schedule the do-finish awe.
//
// XXX: This should only be called in exceptional conditions. It doesn't
// try to free stacks like _thc_endasync. (The stacks will be freed when
// the runtime exits. It's possible to check if we are on a "lazy stack"
// and free it when we're in the LAZY case, but for EAGER, there's no
// marker we can walk back to.)
void THCAbort(void);
// Yields and saves awe_ptr to correspond to the provided id number
void THCYieldAndSave(uint32_t id_num);
......
......@@ -164,6 +164,9 @@ struct ptstate_t {
// Map for resolving integer IDs to awe's. This is used in the
// async ipc code.
struct awe_table *awe_map;
// Set to non-zero when all awe's should stop.
int awes_should_stop;
};
PTState_t *PTS(void);
......
......@@ -3,4 +3,6 @@ obj-m += simple/
obj-m += dispatch/
obj-m += ctx-switch/
obj-m += async-msg-benchmarks/
obj-m += abort/
......@@ -5,3 +5,4 @@ install-tests:
cp $(LIBASYNC_TESTS_KBUILD)/dispatch/libfipc_test_dispatch_loop.ko $(D)
cp $(LIBASYNC_TESTS_KBUILD)/ctx-switch/ctx_switch_test.ko $(D)
cp $(LIBASYNC_TESTS_KBUILD)/async-msg-benchmarks/libasync_test_msgs.ko $(D)
cp $(LIBASYNC_TESTS_KBUILD)/abort/libasync_test_abort.ko $(D)
# @ASYNC_AUTOCONF_NOTICE@
# Magic line so we can do out-of-source build
src = @abs_top_srcdir@/src/tests/abort
obj-m = libasync_test_abort.o
# Paths are relative to abort/ build dir
libasync_test_abort-y += main.o
# LIBASYNC_PATH and LIBFIPC_LIB are defined (and exported) in
# src/Makefile.am.
libasync_test_abort-y += ../../$(LIBASYNC_PATH)
libasync_test_abort-y += ../../$(LIBFIPC_LIB)
ccflags-y += $(CFLAGS) $(AM_CPPFLAGS) $(AM_CFLAGS)
/*
* main.c
*/
#include <libfipc.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <thc.h>
MODULE_LICENSE("GPL");
static int __init abort_example_init(void)
{
DO_FINISH(
ASYNC(
int i;
printk(KERN_ERR "ASYNC 0 started\n");
for (i = 0; i < 4; i++) {
printk(KERN_ERR "ASYNC 0 scheduled\n");
}
printk(KERN_ERR "ASYNC 0 signaling all awe's\n");
THCStopAllAwes();
printk(KERN_ERR "ASYNC 0 aborting\n");
THCAbort();
);
ASYNC(
printk(KERN_ERR "ASYNC 1 started\n");
while(!THCShouldStop())
THCYield();
printk(KERN_ERR "ASYNC 1 aborting\n");
THCAbort();
);
ASYNC(
printk(KERN_ERR "ASYNC 2 started\n");
while(!THCShouldStop())
THCYield();
printk(KERN_ERR "ASYNC 2 aborting\n");
THCAbort();
);
ASYNC(
printk(KERN_ERR "ASYNC 3 started and aborting\n");
THCAbort();
);
printk(KERN_ERR "Successfully ran code after async\n");
// We will hit end of do-finish, which sets up an awe
// for when all contained async's are done.
);
printk(KERN_ERR "Exited do finish\n");
return 0;
}
static void __exit abort_example_rmmod(void)
{
return;
}
module_init(abort_example_init);
module_exit(abort_example_rmmod);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment