gforth
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Embedding wishlist


From: Bernd Paysan
Subject: Re: Embedding wishlist
Date: Tue, 07 Feb 2023 22:25:41 +0100

Am Dienstag, 7. Februar 2023, 14:17:55 CET schrieb Anton Ertl:
> On Mon, Feb 06, 2023 at 07:09:49PM -0600, Ulf Herrman wrote:
> > I'm considering embedding gforth in a C program that uses an event
> > loop. I need to be able to suspend the current forth task and return to
> > C. I *think* the right primitive for this is (bye), unless I'm
> > mistaken. But once it's been suspended, I'd like to be able to resume
> > it. This could be done by having a forth wrapper word around (bye) which
> > will push the succeeding ip onto the return stack, and then executing
> > EXIT when it's time to resume. But I'd like it if I could resume
> > directly from what invoked (bye). I see that there's a saved_ip, but is
> > it current after returning from gforth_engine? I don't see a place where
> > it would be kept up to date... would (bye) have to be modified to store
> > it?
> 
> saved_ip is kept current in the engine gforth (through the macro NAME
> called at the start of every primitive), but not in gforth-fast.  It's
> there in order to report the primitive that caused an exception when
> producing a backtrace.  If you want to go through (bye), the idea of
> wrapping it in a colon definition, and then continuing at a ;S (the
> primitive for EXIT) sounds good.
> 
> For resuming you also need to save the stack pointers and restore them
> on returning.

That's not a problem, (BYE) does that — in the stackpointers format that is 
passed to engine().  That is done so that you can call different entry points 
into Forth with the same stackpointers argument, and pass data from one call 
to the next within Forth, or to use the stack pointer access macros to get the 
data into C.  The IP is not saved, because in the usual Gforth environment, 
there is no need for that.

To save the IP, the Forth side definition would be a simple high level 
definition:

: pause ( -- ) 0 (bye) ;

(or use a different return value to indicate continue, as 0 (bye) would be the 
normal exit), and in the C code that calls gforth_engine(), you use 
*gforth_RP++ to get the return address (the next word after calling PAUSE).  
This should be good enough.

> You can call a C function from within Gforth using the C interface.
> If you can arrange your C program such that you can call the C parts
> as a function rather than as a coroutine, that would be the way to go.
> 
> Otherwise you can
> 
> a) look for a C library for coroutining or somesuch, and call that, or

The way Gforth as library is used on Android is to create a new thread for 
Gforth, and run it there.

> b) pursue the approach of calling (BYE), saving and then restoring the
>    stack pointers and IP there.
> 
> c) you could also try the approach of calling (BYE), but somehow
>    arrange to get the stack pointers saved in a C structure
>    "stackpointers" (possibly by calling a dummy C functionthat you then pass
> to gforth_engine for resuming.
> > Also, it would be nice if gforth could be initialized without having to
> > install signal handlers.

A number of functions simply depend on those signal handlers.  But you can 
take a copy gforth_init() and delete install_signal_handlers() and see how far 
you get.

> > It would also be nice if gforth_stacks could be instructed to leave out
> > the guard pages and page-alignment requirements. This would allow for
> > tasks that are known to only require small stacks to be very compact. At
> > present this isn't even configurable at compile-time: totalsize is
> > always at least 10 pages large.
> 
> It seems that you want to replace some parts of the Gforth
> initialization with your own.  With the development Gforth this is
> entirely possible and I think you do not even need a change to Gforth
> source code.  You just need to do your own main (which you will do
> anyway), link with engine/libgforth.la (or engine/libgforth-fast.la
> etc.), perform your initialization and eventually call
> gforth-engine().

Indeed.  Add an argument for how large the user area should be, because that 
is another page now, and 256/512 bytes (32/64 bits) are sufficient for the 
standard Gforth image.

-- 
Bernd Paysan
"If you want it done right, you have to do it yourself"
net2o id: kQusJzA;7*?t=uy@X}1GWr!+0qqp_Cn176t4(dQ*
https://net2o.de/

Attachment: signature.asc
Description: This is a digitally signed message part.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]