propgcc and pthreads - strange lockup behavior
bgp
Posts: 34
I've been trying some things with propgcc as part of making a relatively simple device that has a speaker, some buttons, and also accepts commands through the serial console.
In order to run these at the same time, I believe I need to do this in different (p)threads. I imagine would want something like:
* A thread to be reading from the console, waiting for commands and sending back output.
* A thread that is waiting to be told to beep and when it should runs freqout() or whatever
* A thread that is scanning the pins for the buttons and setting variables based on what it finds.
* Perhaps the main program execution is doing the routing and looking for these events and doing stuff with them.
It is also possible that some of these could be combined (like the last I know for example could easily be). But some are not so easy - like the freqout() call.
Long story short, in my test program I seem to easily get strange problems where things lock up. Example code:
In that code, the assignment of lastPinValue seems to lock things up (all output halts - for all intents and purposes is dead/sleeping).
Even if the assignment of lastPinValue were not thread-safe, I would not think this would lock the program up.
Am building this with SimpleIDE using the CMM memory model.
Are there some rules of the road regarding how threads should be talking to each other?
In order to run these at the same time, I believe I need to do this in different (p)threads. I imagine would want something like:
* A thread to be reading from the console, waiting for commands and sending back output.
* A thread that is waiting to be told to beep and when it should runs freqout() or whatever
* A thread that is scanning the pins for the buttons and setting variables based on what it finds.
* Perhaps the main program execution is doing the routing and looking for these events and doing stuff with them.
It is also possible that some of these could be combined (like the last I know for example could easily be). But some are not so easy - like the freqout() call.
Long story short, in my test program I seem to easily get strange problems where things lock up. Example code:
// includes, etc. elided int pinValue(int pin) { uint32_t mask = 1 << pin; return (INA & mask) ? 1 : 0; } int lastPinValue = 0; void *watchPins(void *arg) { while(1) { __napuntil(1000); lastPinValue = pinValue(13); } } int main() // Main function { DIRA &= ~(1 << 13); printf("Hello, "); pthread_t t; pthread_create(&t, NULL, watchPins, (void *)&pinMutex); printf("World!\n"); while (1) { printf("v: %d\n", lastPinValue); __napuntil(1000); } }
In that code, the assignment of lastPinValue seems to lock things up (all output halts - for all intents and purposes is dead/sleeping).
Even if the assignment of lastPinValue were not thread-safe, I would not think this would lock the program up.
Am building this with SimpleIDE using the CMM memory model.
Are there some rules of the road regarding how threads should be talking to each other?
Comments
Assuming you want to pause for one second:
The pthreads tools are available as a supplement for situations that require more tasks than can be run on available cogs.
There are many rules to follow for pthreads to work correctly. I highly recommend hobbyists avoiding them entirely if possible.
@jazzed - gotcha, makes sense to me. Is there a simple "cognew"-type way of just calling a function in a new cog? If there is some example code that you could point me to that does something like that, that would be awesome. So far I haven't found such a thing.
Best, Brad
http://learn.parallax.com/multicore-approaches
It is part of the Parallax Propeller C learn tutorials.
One thing that should be considered is that printing to the uart from multiple cogs or threads can be difficult with pthreads or multicore methods. There is one simple solution described in the multicore tutorial.
(I also noticed this goes into quite a bit on this topic: https://code.google.com/p/propgcc/wiki/PropGccInDepth will read up more on that too.)
That post is great - I'll definitely be referencing it again later.
With that said though, your program doesn't use more than 8 threads, so you shouldn't have any problems using waitcnt.
The following was taken from the Simple libraries (I think... it's been too long) and tweaked to use the libraries in PropWare. It should give you a solid idea how to use cog_run().
Original source
Cool and thanks!
Adjusting things to use cog_run() and sharing data with a volatile global variable worked like a charm and was very simple to use.