[Vm-dev] Re: VMMaker-oscog issues on RISC OS

Eliot Miranda eliot.miranda at gmail.com
Thu Apr 11 01:05:27 UTC 2013


Hi Tim,

On Wed, Apr 10, 2013 at 12:43 PM, tim Rowledge <tim at rowledge.org> wrote:

>
> I have a whole 8 methods that I changed to make generating sources appear
> to work on RISC OS, so I'll attempt to submit them later.
>
> Next question; what sort of changes were made to platform code to work
> with the new core? I've noted the mention of the heartbeat ticker, which is
> actually something that may seriously benefit RISC OS and is probably
> something that ought to have been put in the plain VM years ago.
>

The main changes (on the stack vm) are
- a heartbeat.  preferrably this is a thread in a spin-loop, blocking on a
delay, and forcing a poll when it unblocks.  see
http://www.squeakvm.org/svn/squeak/branches/Cog/platforms/unix/vm/sqUnixHeartbeat.c&
http://www.squeakvm.org/svn/squeak/branches/Cog/platforms/win32/vm/sqWin32Heartbeat.c.
 but for this to work the heartbeat thread must have a higher priority than
the VM thread and on linux only the superuser can create real-time threads
that have settable priorities, so.... there-on one has to use an interval
timer, which sucks as it a) interrupts system calls (SA_RESTART is
essential but third-party libraries may be phased by the interval timer)
and b) it's a pain to debug through cuz gdb will stop in the signal handler
until one says "handle 14 ignore", or some such.

- a 64-bit microsecond clock as the basis of time, see the heartbeat files.

- a thread-safe external semaphore registry, see
http://www.squeakvm.org/svn/squeak/branches/Cog/platforms/Cross/vm/sqExternalSemaphores.c

- some atomic access primitives used to implement both the 64-bit
microsecond clock and the external semaphore registry in a lock-free form.
 see
http://www.squeakvm.org/svn/squeak/branches/Cog/platforms/Cross/vm/{sqAtomicOps.h,sqMemoryFence.h}

There's also some Qwaq/teleplace/Term left-overs in the form of a ticker
thread for running multi-media processing in parallel with the VM.  See
sqTicker.c, but I wouldn't worry about that.

There's also some experimental stuff to do with support for a
multi-threaded VM along the lines of e.g. the S# or Python VMs where any
number of threads can share the VM, but only one is actually running the VM
at any one time, and hand-over between threads is carefully mediated.  See
various COGMTVM defines in the VM.


Oh and I've been trying to make sense of the global struct related changes.
> Umm…. a bit confused. Help.
>

Ah.... well, one of my directions in modifying Slang for Cog/Qwaq was to
defer decisions until compile time, getting Slang to generate source which
could determine
- whether a plugin was internal or external
- whether a plugin was included
- whether to use the global struct or flat variables
could be chosen when compiling the VM, not when generating the source.  It
makes the generated C source cross-platform, cuts down on duplication, and
makes it much easier to run experiments to measure if the global struct is
faster or not.

So... to defer the choice of global struct to compile time we...

a) wrap all references to variable which might be in the global struct in
the GIV macro (Global Interpreter Variable), see
CCodeGeneratorGlobalStructure>>#returnPrefixFromVariable:, so in the source
you see e.g.

sqInt
interpret(void)
{   DECL_MAYBE_SQ_GLOBAL_STRUCT
    register sqInt currentBytecode CB_REG;
    register char* localFP FP_REG;
    register char* localIP IP_REG;
...

    if (GIV(stackLimit) == 0) {
        /* begin initStackPagesAndInterpret */

b) define GIV optionally, and output the variables that could be in the
struct in a block with a suitable prefix.  It looks like:

/*** Variables ***/
#if SQ_USE_GLOBAL_STRUCT
# define _iss /* define in-struct static as void */
static struct foo {
#else
# define _iss static
#endif
_iss char * stackPointer;
...
_iss sqInt theUnknownShort;
#undef _iss
#if SQ_USE_GLOBAL_STRUCT
 } fum;
# define DECL_MAYBE_SQ_GLOBAL_STRUCT register struct foo * foo = &fum;
# define DECL_MAYBE_VOLATILE_SQ_GLOBAL_STRUCT volatile register struct foo
* foo = &fum;
# define GIV(interpreterInstVar) (foo->interpreterInstVar)
#else
# define DECL_MAYBE_SQ_GLOBAL_STRUCT /* oh, no mr bill! */
# define DECL_MAYBE_VOLATILE_SQ_GLOBAL_STRUCT /* oh no, mr bill! */
# define GIV(interpreterInstVar) interpreterInstVar
#endif
#if SQ_USE_GLOBAL_STRUCT
static struct foo * foo = &fum;
#endif

which is effectively either

static struct foo {
    char * stackPointer;
    ....
    char * stackPointer;
} fum;

#define GIV(v) (foo->v)

or

static char * stackPointer;
...
static sqInt theUnknownShort;
#define GIV(v) v

c) define an optional macro for declaring a local reference to foo in
functions that need it, so you see

sqInt
interpret(void)
{   DECL_MAYBE_SQ_GLOBAL_STRUCT

and there's either

# define DECL_MAYBE_SQ_GLOBAL_STRUCT register struct foo * foo = &fum;
# define DECL_MAYBE_VOLATILE_SQ_GLOBAL_STRUCT volatile register struct foo
* foo = &fum;

or

# define DECL_MAYBE_SQ_GLOBAL_STRUCT /* oh, no mr bill! */
# define DECL_MAYBE_VOLATILE_SQ_GLOBAL_STRUCT /* oh no, mr bill! */


Then in your makefile you can do -DUSE_GLOBAL_STRUCT=1 if it floats your
boat.  This is a great idea on PPC but doesn't work on x86.  I'd be
interested to know which is better on ARM.

Make sense?  If not, uncork a Bowmore and read at leisure...
-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20130410/d796a8ea/attachment.htm


More information about the Vm-dev mailing list