altos/lisp: Add save/restore infrastructure. Needs OS support to work.
authorKeith Packard <keithp@keithp.com>
Sat, 12 Nov 2016 05:16:09 +0000 (21:16 -0800)
committerKeith Packard <keithp@keithp.com>
Fri, 18 Nov 2016 06:18:39 +0000 (22:18 -0800)
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 <keithp@keithp.com>
src/lisp/Makefile
src/lisp/ao_lisp.h
src/lisp/ao_lisp_builtin.c
src/lisp/ao_lisp_eval.c
src/lisp/ao_lisp_make_const.c
src/lisp/ao_lisp_save.c [new file with mode: 0644]

index aa54202172d0df977c7b13e28d2af8172bb6fd24..dac11f66f310a22686cc62403d8e054bbceafba0 100644 (file)
@@ -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)
index 7a165cd8b47ef1bcf94004eec2aeb0813426fb52..44838a3419b814c81450efe3aae78520a9f12bcf 100644 (file)
 //#include <stdio.h>
 #include <ao_lisp_os.h>
 
+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
index 30631980500df974f6a6a9cb4a58f469c5f3a072..ebc69f7759ec0d348f427c2480b3682170173061 100644 (file)
@@ -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,
 };
 
index 1c9298691b273eb001bb38438e5792e5b9c4b2ed..f945bc163a35cbef1925ca6aa1c124e1376af971 100644 (file)
@@ -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)
 {
index 0b3e25a6df079787182787abecf0dc120d1b07ae..0a8c9d0752ce6603a40695b56d68406416819077 100644 (file)
@@ -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 (file)
index 0000000..2b19fdc
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * 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_lisp.h>
+
+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;
+}