From dba374516ed396633659dec571b6a44b03da8ad1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2016 21:16:09 -0800 Subject: [PATCH] altos/lisp: Add save/restore infrastructure. Needs OS support to work. This sticks a few globals past the end of the heap and then asks the OS to save the heap. On restore, the heap is re-populated by the OS and then various global variables reset. Signed-off-by: Keith Packard --- src/lisp/Makefile | 1 + src/lisp/ao_lisp.h | 39 ++++++++++++++++++++++-- src/lisp/ao_lisp_builtin.c | 5 +++ src/lisp/ao_lisp_eval.c | 18 +++++++++++ src/lisp/ao_lisp_make_const.c | 2 ++ src/lisp/ao_lisp_save.c | 57 +++++++++++++++++++++++++++++++++++ 6 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 src/lisp/ao_lisp_save.c diff --git a/src/lisp/Makefile b/src/lisp/Makefile index aa542021..dac11f66 100644 --- a/src/lisp/Makefile +++ b/src/lisp/Makefile @@ -20,6 +20,7 @@ SRCS=\ ao_lisp_lambda.c \ ao_lisp_eval.c \ ao_lisp_rep.c \ + ao_lisp_save.c \ ao_lisp_error.c OBJS=$(SRCS:.c=.o) diff --git a/src/lisp/ao_lisp.h b/src/lisp/ao_lisp.h index 7a165cd8..44838a34 100644 --- a/src/lisp/ao_lisp.h +++ b/src/lisp/ao_lisp.h @@ -20,6 +20,26 @@ //#include #include +typedef uint16_t ao_poly; +typedef int16_t ao_signed_poly; + +#ifdef AO_LISP_SAVE + +struct ao_lisp_os_save { + ao_poly ao_lisp_atoms; + ao_poly ao_lisp_globals; +}; + +#define AO_LISP_POOL (AO_LISP_POOL_TOTAL - sizeof (struct ao_lisp_os_save)) + +int +ao_lisp_os_save(void); + +int +ao_lisp_os_restore(void); + +#endif + #ifdef AO_LISP_MAKE_CONST #define AO_LISP_POOL_CONST 16384 extern uint8_t ao_lisp_const[AO_LISP_POOL_CONST]; @@ -85,9 +105,6 @@ extern uint16_t ao_lisp_top; extern uint8_t ao_lisp_exception; -typedef uint16_t ao_poly; -typedef int16_t ao_signed_poly; - static inline int ao_lisp_is_const(ao_poly poly) { return poly & AO_LISP_CONST; @@ -228,6 +245,8 @@ enum ao_lisp_builtin_id { builtin_flush, builtin_delay, builtin_led, + builtin_save, + builtin_restore, _builtin_last }; @@ -468,6 +487,12 @@ ao_lisp_poly_move(ao_poly *p, uint8_t note_cons); /* eval */ +void +ao_lisp_eval_clear_globals(void); + +int +ao_lisp_eval_restart(void); + ao_poly ao_lisp_eval(ao_poly p); @@ -542,6 +567,14 @@ ao_lisp_macro(struct ao_lisp_cons *cons); ao_poly ao_lisp_lambda_eval(void); +/* save */ + +ao_poly +ao_lisp_save(struct ao_lisp_cons *cons); + +ao_poly +ao_lisp_restore(struct ao_lisp_cons *cons); + /* error */ void diff --git a/src/lisp/ao_lisp_builtin.c b/src/lisp/ao_lisp_builtin.c index 30631980..ebc69f77 100644 --- a/src/lisp/ao_lisp_builtin.c +++ b/src/lisp/ao_lisp_builtin.c @@ -82,6 +82,9 @@ static const ao_poly builtin_names[] = { [builtin_flush] = _ao_lisp_atom_flush, [builtin_delay] = _ao_lisp_atom_delay, [builtin_led] = _ao_lisp_atom_led, + [builtin_save] = _ao_lisp_atom_save, + [builtin_restore] = _ao_lisp_atom_restore, + }; static char * @@ -591,5 +594,7 @@ const ao_lisp_func_t ao_lisp_builtins[] = { [builtin_flush] = ao_lisp_flush, [builtin_led] = ao_lisp_led, [builtin_delay] = ao_lisp_delay, + [builtin_save] = ao_lisp_save, + [builtin_restore] = ao_lisp_restore, }; diff --git a/src/lisp/ao_lisp_eval.c b/src/lisp/ao_lisp_eval.c index 1c929869..f945bc16 100644 --- a/src/lisp/ao_lisp_eval.c +++ b/src/lisp/ao_lisp_eval.c @@ -546,6 +546,24 @@ static int (*const evals[])(void) = { [eval_while_test] = ao_lisp_eval_while_test, }; +/* + * Called at restore time to reset all execution state + */ + +void +ao_lisp_eval_clear_globals(void) +{ + ao_lisp_stack = NULL; + ao_lisp_frame_current = NULL; + ao_lisp_v = AO_LISP_NIL; +} + +int +ao_lisp_eval_restart(void) +{ + return ao_lisp_stack_push(); +} + ao_poly ao_lisp_eval(ao_poly _v) { diff --git a/src/lisp/ao_lisp_make_const.c b/src/lisp/ao_lisp_make_const.c index 0b3e25a6..0a8c9d07 100644 --- a/src/lisp/ao_lisp_make_const.c +++ b/src/lisp/ao_lisp_make_const.c @@ -67,6 +67,8 @@ struct builtin_func funcs[] = { "flush", AO_LISP_FUNC_LAMBDA, builtin_flush, "delay", AO_LISP_FUNC_LAMBDA, builtin_delay, "led", AO_LISP_FUNC_LEXPR, builtin_led, + "save", AO_LISP_FUNC_LAMBDA, builtin_save, + "restore", AO_LISP_FUNC_LAMBDA, builtin_restore, }; #define N_FUNC (sizeof funcs / sizeof funcs[0]) diff --git a/src/lisp/ao_lisp_save.c b/src/lisp/ao_lisp_save.c new file mode 100644 index 00000000..2b19fdcb --- /dev/null +++ b/src/lisp/ao_lisp_save.c @@ -0,0 +1,57 @@ +/* + * Copyright © 2016 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include + +ao_poly +ao_lisp_save(struct ao_lisp_cons *cons) +{ +#ifdef AO_LISP_SAVE + struct ao_lisp_os_save *os = (struct ao_lisp_os_save *) &ao_lisp_pool[AO_LISP_POOL]; + + ao_lisp_collect(); + os->ao_lisp_atoms = ao_lisp_atom_poly(ao_lisp_atoms); + os->ao_lisp_globals = ao_lisp_frame_poly(ao_lisp_frame_global); + if (ao_lisp_os_save()) + return _ao_lisp_atom_t; +#endif + return AO_LISP_NIL; +} + +ao_poly +ao_lisp_restore(struct ao_lisp_cons *cons) +{ +#ifdef AO_LISP_SAVE + struct ao_lisp_os_save *os = (struct ao_lisp_os_save *) &ao_lisp_pool[AO_LISP_POOL]; + + if (ao_lisp_os_restore()) { + + ao_lisp_atoms = ao_lisp_poly_atom(os->ao_lisp_atoms); + ao_lisp_frame_global = ao_lisp_poly_frame(os->ao_lisp_globals); + + /* Clear the eval global variabls */ + ao_lisp_eval_clear_globals(); + + /* Reset the allocator */ + ao_lisp_top = AO_LISP_POOL; + ao_lisp_collect(); + + /* Re-create the evaluator stack */ + if (!ao_lisp_eval_restart()) + return AO_LISP_NIL; + return _ao_lisp_atom_t; + } +#endif + return AO_LISP_NIL; +} -- 2.30.2