What is a pthread?
Rsadeika
Posts: 3,837
I thought I would give this subject its own space. Is a pthread a separate, simultaneous activity that occurs in a new cog? Is it a separate, simultaneous activity that occurs in the same cog? Is it a combination of the two? Or none of the above.
Ray
Ray
Comments
Undefined reference to _usleep.
When I get some answers to my first post here, then I will try some other things, and I will flesh out the program. In the mean time I have to figure out what is really going on.
Ray
Note that the PropGCC implementation of threads is "cooperative" rather than "preemptive"; if two threads are trying to share a cog, each must call sleep(), pthread_yield(), or some similar blocking pthread call in order to give time to the other. If a thread is busy waiting, for example with waitcnt(), then no other threads can use that cog.
Eric
In the meantime you can use the (undocumented) __napuntil() function, which works like waitcnt() -- it waits until the _CNT variable reaches a particular value, but it does this in a thread-friendly way, giving up time on the cog to other threads.
Eric
Ray
Ray
Pthreads is too big to fit in cog memory, so it won't work in -mcog mode.
The pthread library does work in XMM and XMMC modes, but as I mentioned all the threads have to run on the same cog in that mode. That's a limitation of the way external memory is accessed; only one cog can read from external memory at a time. Someday I hope that restriction will be lifted.
There is a demo in the propgcc/demo/pthread directory. You can make it for any model by specifying MODEL= on the command line, e.g. for XMM mode do: The default is MODEL=lmm.
Eric
The cognew() function requires that the memory it works on be in the hub, so some of the demos above only work in LMM mode. The gas_toggle demo has been adapted to work in XMM and XMMC modes as well; you can look at the start_cog() function in gas_toggle/toggle.c to see how that works.
It depends on what you're doing. cognew() is a simple way to run assembly language code on another cog, but for C code it's a little more complicated (you have to compile the C code with -mcog and use objcopy to convert its symbols). pthreads is simpler for C code and allows for more threads than cogs, but in XMM and XMMC all the threads will run on the same cog.
The toggle demos that jazzed did are a great place to start. There are many ways to achieve the same goal, and which one works best will depend on your application.
Eric
Another advantage is that it allows sharing C named variables with COG threads.
As Eric mentioned, using cognew with C programs requires some special handling.
The demos/toggle/cog_c_toggle/Makefile does this for us.
The cog_c_toggle is pure C without PASM. The pasm_toggle uses C and PASM with BSTC for compile.
Simple steps required for building and loading the cog_c_toggle example without make are:
- propeller-elf-gcc -r -mcog -o toggle_fw.cog -c toggle_fw.c
- propeller-elf-objcopy --localize-text --rename-section .text=toggle_fw.cog toggle_fw.cog
- propeller-elf-gcc -Os -o toggle.elf toggle_fw.cog toggle.c -s
- propeller-load -r toggle.elf
Simple steps for building PASM example demos/toggle/pasm_toggle without make are:- bstc -Ox -c toggle.spin
- propeller-elf-objcopy -I binary -B propeller -O propeller-elf-gcc toggle.dat toggle_firmware.o
- propeller-elf-gcc -Os -o toggle.elf toggle_firmware.o toggle.c -s
- propeller-load -r toggle.elf
In either case above, it will be necessary to put different cog programs into different files for multiple cogs.Hope this helps.
--Steve
Ray
Thanks for keeping at this, Ray -- it's great to have more eyes on the library, and it's certainly possible that you're coming across a bug in it. But I don't think so in this case. I ran exactly what you posted, with the following changes:
usleep(500) replaced by sleep(1) (and similar changes to the other usleep calls)
high(21) replaced by high(15) (for the LED built in to my c3 board)
and it worked in LMM, XMMC, and XMM modes on my C3 board. Source code is at the end of this post. I compiled the XMM mode with
If you use WaitMS() instead of sleep() or __napuntil(), then it probably won't work in XMM or XMMC mode, because the single cog will be stuck on one thread forever. In LMM mode it doesn't matter, because in that mode the threads will have their own cogs and so busy-waiting in WaitMS will not hurt anything.
The full revised code is:
What is in your misc.h library? If I comment out, the compiler complains at me saying "undefined reference to _high" and "..._low". (I figured something would be missing, but I thought I'd give it a try anyway). I also tried "#define _high 1" and "#define _low 0" to no avail.
Additionally, when compiling under Linux, the compiler can't find -lpthread. This is on my build box, I probably dont have the paths set up correctly.
Thanks,
Daniel
That's very strange, my compilation actually was on Linux. Do you have the most recent version of the compiler for Linux? -lpthread was added relatively late (I think in the last release or two).
Eric
About the -lpthread thing - thats probably what it is. Its been a while since I have done hg pull/update on my build box.. It didn't throw the error on the Windows side; I just used the pre-built package.
Thanks for the info .
Ray
Ray
I'm using windows too.
Use sleep for now because the pthread safe function usleep is missing from the library.
We'll need another release to use usleep.
This works for me.
Build with:
propeller-elf-gcc.exe -o a.out -Os raypthread.c -lpthread -s
propeller-load.exe a.out -r -t
Ray
Sorry I missed that part. I also have trouble with the old windows distribution.
I've started a new windows build this morning and will post an update if it works better.
I think Eric has provided a fix for this and usleep.
Hi Ray. Please download the new Windows PropGCC Alpha Distribution.
The program listed above works with it in XMM and XMMC mode (change P21 to P15 for C3 testing).
I tried to summarize the options available into a table to clarify what can be done and what the restrictions are:
Now, let's see if I can explain and summarize this line by line and how much I got right:
1) You can use PThreads in an LMM memory C program to start LMM C code threads, you can create threads up to and beyond the number of physical COGs available (multiple threads running on multiple COGs). If the thread count exceeds the number of COGs available, then the threads without COG affinity must play nice and employ cooperative multi-tasking techniques. COG affinity is possible up to the number of COGs available.
2) COGM C programs can start COGM C code threads via the COGINIT/COGNEW mechanism (sys/threads) up to the number of available COGs. A single code thread per COG, COG affinity is implied by definition.
3) XMM memory model C programs can start XMM memory model code threads via PThreads. All threads will run in a single COG and MUST employ cooperative multi-tasking techniques.
4) XMMC works the same as XMM model programs.
5) LMM memory model C programs can start LMM-C code threads via COGINIT/COGNEW (sys/threads) up to the number of available COGs. A single code thread per COG, COG affinity is implied by definition.
6,7 and 8) These are essentially the same rules for ANY memory model. The difference is the source of the code blob being loaded and executed in the COG. The start mechanism is through COGINIT/COGNEW (sys/thread) with a single code thread per available COG. COG affinity is implied by definition.
Program design will play a big part in selecting the mechanics used and the rules that need to be followed. The Propeller is a hardware architecture hat is limited in some areas but it does have the features to leverage multi-thread and multi-COG programming through C as well if not better than can be done currently with SPIN/PASM. The PThreads implementation opens up some exciting new opportunities.
Please let me know where I'm going astray with any of my thoughts or assumptions. I think this is an important area to document in both terms of how to do it and why to do it and how each method can benefit different applications.
I'll probably start another forum thread once there is a working document and set of programs to discuss.
Thanks!
Some things to note: pthreads must use a thread-safe delay such as usleep() or sleep() - waitcnt can not be used with pthreads. Also __simple_printf is not thread safe, so you can't use -Dprintf=__simple_printf with pthreads programs. LMM C programs can't start LMM threads with COGINIT/COGNEW, they must use the _start_cog_thread function.
LMM C programs can start COG threads with COGINIT/COGNEW. You will note that in SimpleIDE toggle/cog_c_toggle that the file toggle_fw.cogc is a "_NATIVE" C to PASM program file. I used the .cogc extension so that the SimpleIDE build rule machine knows what to do.
Thanks for your effort!
--Steve
Cool!
There will be a section on thread safe coding techniques. Bunches of things to consider and to do and not do.
LMM C starting LMM threads with COGINIT/COGNEW was just laziness on my part in the table to indicate not a PThread thread. _start_cog_thread and all its ugly parameters is what I'm using in my program.
Marching onward!
We could probably make a wrapper or two for that function. STARTCOG ?
We can't really simplify it though.
I'll cut my table out of here with corrections and add it to the doc pile.
Thanks!