Shop Learn
Catalina - ANSI C for the Propeller 1 & 2 — Parallax Forums

Catalina - ANSI C for the Propeller 1 & 2

RossHRossH Posts: 4,787
edited 2021-12-19 08:28 in C/C++

I guess I should start a new thread for Catalina, instead of continuing the separate ones for the P1 and P2. I will add new updates here.

Catalina is an open source ANSI C compiler. It support the Propeller 1 and Propeller 2.

Catalina is available here.

The current version is 4.9.5 on both Windows and Linux.

The most recent update is that Catalina now supports Lua 5.4.3. For more details, see the notes on release 4.9.5 in the post below.

Comments

  • RossHRossH Posts: 4,787
    edited 2021-12-19 10:33

    I am releasing Catalina 4.9.5. The main thing this release adds is enhanced Lua support and a couple of bug fixes. See the README extract below.

    Lua is lots of fun, and well suited to the Propeller (especially the Propeller 2). For those unfamiliar with it, here is a description of Lua from lua.org:

    Lua is a powerful, efficient, lightweight, embeddable scripting language. It supports procedural programming, object-oriented programming, functional programming, data-driven programming, and data description.

    Lua combines simple procedural syntax with powerful data description constructs based on associative arrays and extensible semantics. Lua is dynamically typed, runs by interpreting bytecode with a register-based virtual machine, and has automatic memory management with incremental garbage collection, making it ideal for configuration, scripting, and rapid prototyping.

    In addition to adding Lua 5.4.3 (the latest version) I have upgraded both Catalina and Catalyst to use Lua 5.1.5, because this version adds the ability to not only run an interactive Lua interpreter and a Lua compiler, but also to execute pre-compiled Lua programs using less memory, which enables the execution of larger Lua programs on the Propeller.

    Here is the relevant section of the README.TXT file.

    RELEASE 4.9.5
    
    New Functionality
    -----------------
    
    1. Updated Lua to version 5.1.5 in both payload (where it is embedded for
       scripting) and Catalyst (where it is used as a stand-alone demo program). 
       Version 5.1.5 is the last release of Lua 5.1. On a Propeller 1 it must 
       be compiled in LARGE mode. On a Propeller 2 it can be compiled in either
       NATIVE or COMPACT mode.
    
       Catalyst will continue to incorporate Lua 5.1 because it is small 
       enough to be useful on a micro controller like the Propeller even
       when compiled in NATIVE mode (for speed). Also, Lua 5.1.5 incorporates 
       a new option to execute compiled Lua programs using a Lua execution 
       engine that does not load the Lua parser (luax). This saves even more 
       Hub RAM when all the Lua code to be executed is pre-compiled using the 
       Lua compiler (luac).
    
       For example, to execute the "life.lua" demo program, you can now either
       do:
    
          lua life.lua
    
       or
    
          luac -o life.out life.lua
          luax life.out
    
       Lua version 5.4.3 is now also included as a Catalyst demo, but is not 
       compiled by default. Version 5.4.3 is the current release of Lua 5.4.
       On the Propeller 2 it should be compiled with the COMPACT option, or 
       it may be too large to be much use. For example:
    
          build_all P2_EVAL SIMPLE VT100 COMPACT
    
       On the Propeller 2, the code sizes of Lua 5.1 (without the Lua parser), 
       Lua 5.1 (with the Lua parser) and Lua 5.4 are:
    
                                COMPACT   NATIVE  
          Lua 5.1 (no parser)     138k     250k   
          Lua 5.1 (with parser)   166k     297k   
          Lua 5.4 (with parser)   227k     412k   
    
       Hence Lua 5.1 is quite usable in both NATIVE and COMPACT modes, and with 
       or without loading the parser, whereas Lua 5.4 is really only usable in 
       COMPACT mode. This is because Lua 5.4 itself takes so much Hub RAM that 
       there is not much left to run anything except small Lua programs (the 
       above sizes are the code sizes only - there is also stack and heap space 
       required to actually execute a Lua program). Note that there is currently
       no option to execute Lua 5.4 programs without loading the Lua parser.
       This option may be added in a later Catalina release.
    
       Note also that on memory constrained systems such as a Propeller, the Lua 
       garbage collector sometimes requires a "tweak" to ensure it runs often 
       enough to stop Lua programs running out of memory. The "life.lua" demo 
       program is an example - it does many string concatenations per generation, 
       and if the garbage collection does not run often enough, the program can 
       run out of memory. To prevent this, the following line has been added to 
       the program:
    
          collectgarbage("setstepmul", 500)
    
       Refer to the Lua documentation for more details.
    
    2. Updated MAX_SYMBOLS in p2asm to be 20,000 (was 10,000) - this is 
       required to allow Lua 5.4.3 to be compiled with optimization enabled.
    
    3. Added decoding of Catalina symbols MHZ_300 and OPTIMIZE. This allows
       these options to be specified on the command line of the build_all 
       scripts, or via CATALINA_DEFINE:
    
          MHZ_300 - set the default Propeller 2 clock to 300Mhz. Note that 
                    this may not work on all Propeller 2 platforms. USE THIS 
                    OPTION WITH CAUTION, BECAUSE IT MAY NOT BE IMMEDIATELY 
                    APPARENT THAT A PROGRAM IS NOT EXECUTING CORRECTLY!
    
          OPTIMIZE - set the optimizer level to 5.
    
      For example, you can now say:
    
          build_all P2_EVAL MHZ_300 OPTIMIZE
    
       or
    
          set CATALINA_DEFINE=P2_EVAL MHZ_300 OPTIMIZE
          build_all
    
       These symbols are not intended to be used on the command line, but they 
       can be used via the -C option. For example:
    
          catalina hello_world.c -p2 -lci -C MHZ_300 -C OPTIMIZE
    
       would be the same as:
    
          catalina hello_world.c -p2 -lci -f300Mhz -O5
    
    
    Other Changes
    -------------
    
    1. Reformatted some Catalyst text files (e.g. Catalyst.txt) to be Unix 
       format instead of DOS. This makes them easier to view in the Catalyst
       text editor (vi).
    
    2. Fixed a bug in the Catalina Optimizer when optimizing COMPACT programs.
       This may have resulted in programs that would not execute correctly. 
       Affected only Propeller 2 COMPACT programs.
    
    3. Fixed a bug when compiling Catalyst - it would not compile for the
       Propeller 2 if the file sio_array.h was not present in the core folder, 
       even though that file is only required when compiling for the Propeller 1.
    
    

    Both Windows and Linux versions are now available.

    Ross.

  • RossHRossH Posts: 4,787
    edited 2021-12-20 03:57

    I have had a question about integrating C with Lua. This is very easy to do, and there is a minimalist example (min.c) that is included with Lua-5.1.5 in Catalina 4.9.5. However, this example is not so easy to execute using the payload terminal emulator because when you run the program, payload terminates before it prints the output the program produces.

    The min.c program reads stdin and expects the input to be terminated with an EOT (i.e. Ctrl-D) before it produces output to stdout and/or stderr. But Ctrl-D is also the signal to payload to terminate, so you never see the output. To fix this, I have added the ability for payload to send an EOT to the application without terminating. Just press Ctrl-D once to send EOT. To terminate payload you now have to enter TWO CONSECUTIVE Ctrl-D characters.

    Copy the new payload executable over the existing payload.exe in your Catalina\bin directory. The amended source (payload.c) is also included, and will also be included in the next release of Catalina.

    The program min.c is in the Lua-5.1.5\etc folder, but the easiest way to compile it is to copy it to the Lua src folder, then build the Lua library and then compile the min program. For example, you could use commands like:

    cd catalyst\demos\lua-5.1.5\src
    copy ..\etc\min.c .
    set CATALINA_DEFINE=P2_EVAL
    make -f Makefile.Catalina clean liblua
    catalina -p2 -lcx -lmc -llua min.c
    

    To load and run the program, use the new payload in interactive mode:

    payload -i -b230400 min.bin

    Then in the payload window, type the following:

    a=1.1
    b=2.2
    print("a+b=",a+b)
    

    Make sure to press ENTER after the final line. Then press Ctrl-D. You should see output like:

    a+b= 3.300000191

    Press Ctrl-D again to exit payload. The min.c program interprets any Lua statements entered via stdin, but it loads no Lua libraries - the "print" function you just executed is not the normal Lua print function - it is the C function in min.c. This minimalist example shows how easy it is to call Lua from C, and also C from Lua!

    Here is the entire min.c program:

    /*
    * min.c -- a minimal Lua interpreter
    * loads stdin only with minimal error handling.
    * no interaction, and no standard library, only a "print" function.
    */
    
    #include <stdio.h>
    
    #include "lua.h"
    #include "lauxlib.h"
    
    static int print(lua_State *L)
    {
     int n=lua_gettop(L);
     int i;
     for (i=1; i<=n; i++)
     {
      if (i>1) printf("\t");
      if (lua_isstring(L,i))
       printf("%s",lua_tostring(L,i));
      else if (lua_isnil(L,i))
       printf("%s","nil");
      else if (lua_isboolean(L,i))
       printf("%s",lua_toboolean(L,i) ? "true" : "false");
      else
       printf("%s:%p",luaL_typename(L,i),lua_topointer(L,i));
     }
     printf("\n");
     return 0;
    }
    
    int main(void)
    {
     lua_State *L=lua_open();
     lua_register(L,"print",print);
     if (luaL_dofile(L,NULL)!=0) fprintf(stderr,"%s\n",lua_tostring(L,-1));
     lua_close(L);
     return 0;
    }
    
    

    You can perhaps see why I find Lua so interesting!

  • RossHRossH Posts: 4,787

    I have just issued a small patch for Catalina - release 4.9.6. It is available on SourceForge. Please note that this is NOT a full release. It must be installed over an existing installation of Catalina 4.9.5. It includes all new sources and Windows binaries, but for Linux you will need to recompile Catalina from source after you install the patch.

    The main purpose of release 4.9.6 is to tidy up a few outstanding issues before the next full release of Catalina, which may be a while away because it will introduce some significant changes. For example, the next full release will include a thread-safe version of malloc, and multithreading support for Lua.

    Here is an extract from the README.TXT:

    RELEASE 4.9.6
    
    New Functionality
    -----------------
    
    1. Updated the payload loader to allow EOT (Ctrl-D) to be passed to the
       application program in interactive mode without also closing the terminal 
       emulator. Now pressing Ctrl-D ONCE passes an EOT to the application but
       does not terminate payload. To terminate payload you must now enter TWO 
       SUCCESSIVE Ctrl-D characters.
    
    2. Updated the minimalist Lua demo program (min.c) so that it would compile
       under both Lua 5.1.5 and Lua 5.4.3 (which changed the names of some Lua
       library functions).
    
    3. Updated the Lua 5.1.5 and 5.4.3 Makefiles to include pattern templates.
       This simplifies the compilation of Lua programs like min.c - you can
       now use just the Catalina Makefile to build Lua programs. For example, to 
       build the minimalist demo:
          make -f Makefile.Catalina clean min.bin 
    
    4. Added the Lua execution engine (luax) that executes only compiled Lua 
       programs to Lua-5.4.3. This saves Hub RAM by not loading the Lua parser
       if all the Lua programs to be executed are pre-compiled.
    
    5. Added "clean_all" scripts to the Catalyst demo folders, to make it easier
       to remove compiled versions of all the Catalyst programs.
    
    6. Added "clean_all" scripts to the Catalina source folders, to make it easier
       to remove compiled versions of all the Catalina programs.
    
    7. Removed the -C NATIVE from the Catalyst build_all and Makefiles, and some 
       of the -O5 options on individual demo programs. This means that you can now 
       specify OPTIMIZE on the command line if you want Catalyst programs to be
       optimized, and on the Propeller 2 you can now choose to compile all the
       demo programs as COMPACT (instead of NATIVE). Note that this applies to 
       the Propeller 2 only. Do not specify a memory model on the Propeller 1 - 
       the core programs must always compiled as COMPACT on the Propeller 1 
       because otherwise they would be too large for a Propeller 1 without XMM 
       RAM, and the other programs must usually be compiled in LARGE mode.
    
    Other Changes
    -------------
    
    1. Fixed some errors in Dumbo Basic that stopped it compiling in COMPACT
       mode. Affected the Propeller 2 only.
    
    2. Release 4.9.5 fixed one bug in the COMPACT mode optimizer, but introduced
       another, which has been fixed in this release. Affected the Propeller 2 
       only (and the only program known to be affected was the vi text editor, 
       which would not compile in COMPACT mode).
    
  • RossHRossH Posts: 4,787
    edited 2022-01-18 01:26

    Just a quick progress report. I have just finished making Catalina's memory management functions (malloc, calloc, realloc, free etc) thread-safe, which also makes them safe to execute from multiple cogs and also from multiple memory models.

    As a test I thought I'd try executing multiple parallel Lua interpreters. Turns out to be quite trivial.

    Here is an example program which executes four Lua interpreters, each one running on a separate cog. Currently the Lua interpreters are pretty much independent, and can only communicate via C shared functions and global variables (such as is demonstrated by the "print" function in this example):

    /*
     * multi_cog.c -- a minimal multi-cog Lua interpreter.
     *
     *    executes Lua interpreters on multiple cogs.
     *
     *    no user interaction, no standard Lua library, only a "print" function.
     *
     */
    
    /*
     * include Catalina definitions:
     */
    #include <catalina_cog.h>
    //#include <catalina_threads.h>
    
    /*
     * include Lua definitions:
     */
    #include "lua.h"
    #include "lauxlib.h"
    
    /*
     * define a stack size for the Lua interpreters (the 
     * exact value depends on the Lua code to be executed):
     */
    #define STACK_SIZE 1000 // longs
    
    /*
     * define a global flag to synchronize starting the Lua interpreters
     * (so we can easily see that they do execute in parallel):
     */
    static int start;
    
    /*
     * define a global lock to protect memory functions:
     */
    static int memory_lock;
    
    /*
     * define a global lock to protect our HMI functions 
     * (so the output is not garbled):
     */
    static int hmi_lock;
    
    /*
     * define a C function for Lua to call (just as an example):
     */
    static int print(lua_State *L) {
       int n=lua_gettop(L);
       int i;
       ACQUIRE(hmi_lock);
       for (i=1; i<=n; i++) {
          if (i>1) printf("\t");
          if (lua_isstring(L,i))
             printf("%s",lua_tostring(L,i));
          else if (lua_isnil(L,i))
             printf("%s","nil");
          else if (lua_isboolean(L,i))
             printf("%s",lua_toboolean(L,i) ? "true" : "false");
          else
             printf("%s:%p",luaL_typename(L,i),lua_topointer(L,i));
       }
       printf("\n");
       RELEASE(hmi_lock);
       return 0;
    }
    
    /*
     * define a function that can be started on a cog to
     * execute a lua interpreter on a string (the string 
     * can contain any arbirary lua code):
     */
    void lua_on_a_cog(char *code) {
       int error;
       lua_State *L;
    
       L=luaL_newstate();
       lua_register(L,"print",print);
       while (!start) { }; // wait for start signal
       error = luaL_loadstring(L, code) || lua_pcall(L, 0, 0, 0);
       if (error) {
          ACQUIRE(hmi_lock);
          printf("%s\n", lua_tostring(L, -1));
          RELEASE(hmi_lock);
          lua_pop(L, 1); // pop error message from the stack
       }
       lua_close(L);
       while(1);
    }
    
    /*
     * one cog will execute this Lua code:
     */
    void lua_interpreter_1(void) {
       lua_on_a_cog("for a = 1, 10 do print(\"a= \"..a) end");
    }
    
    /*
     * one cog will execute this Lua code:
     */
    void lua_interpreter_2(void) {
       lua_on_a_cog("for b = 10, 1, -1 do print(\"b= \"..b) end");
    }
    
    /*
     * one cog will execute this Lua code:
     */
    void lua_interpreter_3(void) {
       lua_on_a_cog("for c = 20, 30 do print(\"c= \"..c) end");
    }
    
    /*
     * one cog will execute this Lua code:
     */
    void lua_interpreter_4(void) {
       lua_on_a_cog("for d = 30, 20, -1 do print(\"d= \"..d) end");
    }
    /*
     * the main function just starts the cog functions:
     */
    void main(void) {
    
       // allocate stack space for each Lua interpreter:
       unsigned long lua_stack_1[STACK_SIZE];
       unsigned long lua_stack_2[STACK_SIZE];
       unsigned long lua_stack_3[STACK_SIZE];
       unsigned long lua_stack_4[STACK_SIZE];
    
       // even though we do not use threading, multi-kernel programs
       // must assign a memory lock to protect the memory management
       // functions from multi-cog access:
       memory_lock = _locknew();
       _memory_set_lock(memory_lock);
    
       // because multiple cogs may access the services provided by plugins,
       // we must assign one or more locks to protect the services during 
       // multi-cog access. In previous versions of Catalina, this had to be
       // done by specifying -C PROTECT_PLUGINS during compilation, which is
       // still supported. In that case the following function does nothing:
       _set_service_lock(-1);
    
       // allocate a lock to protect HMI functions:
       hmi_lock = _locknew();
    
       // start multiple cogs, each one executing a Lua interpreter
       // (they won't start executing their Lua code until we tell them):
       _coginit_C(&lua_interpreter_1, &lua_stack_1[STACK_SIZE]);
       _coginit_C(&lua_interpreter_2, &lua_stack_2[STACK_SIZE]);
       _coginit_C(&lua_interpreter_3, &lua_stack_3[STACK_SIZE]);
       _coginit_C(&lua_interpreter_4, &lua_stack_4[STACK_SIZE]);
    
       // start all the Lua interpreters:
       start = 1;
    
       // just let the cogs do their thing:
       while (1);
    }
    
    

    Here is the actual output produced when the above program is run (on a Propeller 2). It is pretty much what you would expect if all the Lua interpreters are in fact executing in parallel:

    d= 30
    a= 1
    c= 20
    d= 29
    b= 10
    a= 2
    c= 21
    d= 28
    a= 3
    b= 9
    c= 22
    a= 4
    d= 27
    b= 8
    c= 23
    a= 5
    b= 7
    d= 26
    a= 6
    b= 6
    c= 24
    a= 7
    b= 5
    c= 25
    a= 8
    d= 25
    c= 26
    b= 4
    d= 24
    a= 9
    b= 3
    c= 27
    d= 23
    a= 10
    b= 2
    c= 28
    d= 22
    b= 1
    c= 29
    d= 21
    c= 30
    d= 20
    
    

    Of course, this program requires Catalina 5.0, which is not released yet!

    The next step is to add multi-threading support to Lua (i.e. in addition to just multi-cog and multi-model support). With Catalina's multi-threading, this should be trivial, and should allow the execution of dozens of concurrent Lua interpreters, not bounded by the number of available cogs (as the example above is!).

    However, I am not sure yet that this will be particularly useful. Ideally I would prefer to be able to run individual Lua functions as threads - i.e. to offer a much finer granularity of threading than just instances of the Lua interpreter.

    Time will tell.

  • I don't suppose there is any chance for a Mac release?

  • RossHRossH Posts: 4,787

    Hi David

    I never did Mac releases, but I used to use a virtual Mac to make sure Catalina would compile and basically run. So the Linux version of Catalina used to be able to be compiled on a Mac, but we are going back quite a few years, and I doubt very much that it would do so now.

    Ross.

  • @RossH said:
    Hi David

    I never did Mac releases, but I used to use a virtual Mac to make sure Catalina would compile and basically run. So the Linux version of Catalina used to be able to be compiled on a Mac, but we are going back quite a few years, and I doubt very much that it would do so now.

    Ross.

    You're probably right that it won't compile out of the box if you haven't done anything to make that happen. I remember trying a while back and there were some problems that I didn't have time to resolve.

  • RossHRossH Posts: 4,787
    edited 2022-01-14 00:00

    As expected, the multi-threaded version proved to be trivial, but worth doing to verify (before I dig deeper into making Lua multi-threaded) that once the memory management functions are made thread-safe, so is Lua.

    Here is a very similar program to the multi-cog version above, but this one is not limited by the available cogs - it executes 20 Lua interpreters in separate threads:

    /*
     * multi_thread.c -- a minimal multi-threaded Lua interpreter.
     *
     *    executes Lua interpreters on multiple threads.
     *
     *    no user interaction, no standard Lua library, only a "print" function.
     *
     */
    
    /*
     * include Catalina definitions:
     */
    #include <catalina_cog.h>
    #include <catalina_threads.h>
    #include <thread_utilities.h>
    
    /*
     * include Lua definitions:
     */
    #include "lua.h"
    #include "lauxlib.h"
    
    /*
     * define how many Lua interpreters (i.e. threads) we want:
     */
    #define NUM_THREADS 20
    /*
     * define a stack size for the Lua interpreters (the 
     * exact value depends on the Lua code to be executed):
     */
    #define STACK_SIZE (MIN_THREAD_STACK_SIZE + 1000) // longs
    
    /*
     * define the number of thread locks we need (we only need one
     * to protect our HMI functions):
     */
    #define NUM_LOCKS 1
    
    /*
     * a pool of thread locks - note that the pool must be 5 bytes larger than
     * the actual number of locks required (MIN_THREAD_POOL_SIZE = 5):
     */
    static char pool[MIN_THREAD_POOL_SIZE + NUM_LOCKS]; 
    
    /*
     * a lock allocated from the pool - required to protect our HMI functions:
     */
    static int hmi_lock;
    
    /*
     * a global flag to synchronize starting the Lua interpreters
     * (so we can easily see that they do execute in parallel):
     */
    static int start;
    
    /*
     * a global lock to protect kernels and memory functions:
     */
    static int kernel_lock;
    
    /*
     * a C function for Lua to call (just as an example):
     */
    static int print(lua_State *L) {
       int n=lua_gettop(L);
       int i;
       for (i=1; i<=n; i++) {
          if (i>1) _thread_printf(pool, hmi_lock, "\t");
          if (lua_isstring(L,i))
             _thread_printf(pool, hmi_lock, "%s",lua_tostring(L,i));
          else if (lua_isnil(L,i))
             _thread_printf(pool, hmi_lock, "%s","nil");
          else if (lua_isboolean(L,i))
             _thread_printf(pool, hmi_lock, "%s",lua_toboolean(L,i) ? "true" : "false");
          else
             _thread_printf(pool, hmi_lock, "%s:%p",luaL_typename(L,i),lua_topointer(L,i));
       }
       _thread_printf(pool, hmi_lock, "\n");
       _thread_yield();
       return 0;
    }
    
    /*
     * a Lua interpreter that can be executed as a thread - it will 
     * execute whatever Lua code passed to it in code[0]:
     */
    int lua_thread(int me, char *code[]) {
       int error;
       lua_State *L;
    
       L=luaL_newstate();
       lua_register(L,"print",print);
       while (!start) { }; // wait for start signal
       error = luaL_loadstring(L, code[0]) || lua_pcall(L, 0, 0, 0);
       if (error) {
          _thread_printf(pool, hmi_lock, "%s\n", lua_tostring(L, -1));
          lua_pop(L, 1); // pop error message from the stack
       }
       lua_close(L);
       return error;
    }
    
    /*
     * the main function just starts the thread functions:
     */
    void main(void) {
    
        int i;
    
       // the lua code to be executed - one string will be executed 
       // by each Lua interpreter running as a separate thread:
       char *code[] = {
         "for a = 1, 10 do print(\"a= \"..a) end", 
         "for b = 11, 20 do print(\"b= \"..b) end", 
         "for c = 21, 30 do print(\"c= \"..c) end", 
         "for d = 31, 40 do print(\"d= \"..d) end", 
         "for e = 41, 50 do print(\"e= \"..e) end", 
         "for f = 51, 60 do print(\"f= \"..f) end", 
         "for g = 61, 70 do print(\"g= \"..g) end", 
         "for h = 71, 80 do print(\"h= \"..h) end", 
         "for i = 81, 90 do print(\"i= \"..i) end", 
         "for j = 91, 100 do print(\"j= \"..j) end", 
         "for k = 101, 110 do print(\"k= \"..k) end", 
         "for l = 111, 120 do print(\"l= \"..l) end", 
         "for m = 121, 130 do print(\"m= \"..m) end", 
         "for n = 131, 140 do print(\"n= \"..n) end", 
         "for o = 141, 150 do print(\"o= \"..o) end", 
         "for p = 151, 160 do print(\"p= \"..p) end", 
         "for q = 161, 170 do print(\"q= \"..q) end", 
         "for r = 171, 180 do print(\"r= \"..r) end", 
         "for s = 181, 190 do print(\"s= \"..s) end", 
         "for t = 191, 200 do print(\"t= \"..t) end", 
       };
    
       // allocate stack space for each Lua interpreter:
       unsigned long stack[STACK_SIZE * NUM_THREADS];
    
       // assign a lock to protect kernels 
       // (and memory management functions):
       kernel_lock = _locknew();
       _thread_set_lock(kernel_lock);
    
       // initialize a pool of thread locks (we need only 1 lock)
       _thread_init_lock_pool (pool, NUM_LOCKS, _locknew());
    
       // assign a thread lock to avoid HMI plugin contention:
       hmi_lock = _thread_locknew(pool);
    
       // start multiple threads, each one executing a Lua interpreter
       // (they won't start executing their Lua code until we tell them):
       for (i = 0; i < NUM_THREADS; i++) {
          _thread_start(&lua_thread, &stack[STACK_SIZE*(i+1)], i, &code[i]);
       }
    
       // start all the Lua interpreters:
       start = 1;
    
       // just let the threads do their thing:
       while (1) {
         _thread_yield();
       };
    }
    
    

    The output is exactly what you would expect. Here are just the last few lines:

    t= 198
    s= 188
    r= 178
    q= 168
    p= 158
    o= 148
    n= 138
    m= 128
    l= 118
    k= 108
    j= 98
    i= 88
    h= 78
    g= 68
    f= 58
    e= 48
    d= 38
    c= 28
    b= 18
    a= 8
    t= 199
    s= 189
    r= 179
    q= 169
    p= 159
    o= 149
    n= 139
    m= 129
    l= 119
    k= 109
    j= 99
    i= 89
    h= 79
    g= 69
    f= 59
    e= 49
    d= 39
    c= 29
    b= 19
    a= 9
    t= 200
    s= 190
    r= 180
    q= 170
    p= 160
    o= 150
    n= 140
    m= 130
    l= 120
    k= 110
    j= 100
    i= 90
    h= 80
    g= 70
    f= 60
    e= 50
    d= 40
    c= 30
    b= 20
    a= 10
    
    

    Now comes the hard part ... :(

Sign In or Register to comment.