Function to be used in a cog - rules
John Kauffman
Posts: 653
Please confirm, for C language, the rules for a function that will run in a cog. Thanks.
A function to run in a cog must have return of void.
A function to run in a cog must be an infinite loop - or - contain a cog_end(cog).
Above true or should be stated alternately?
Any other basic rules?
Thanks.
A function to run in a cog must have return of void.
A function to run in a cog must be an infinite loop - or - contain a cog_end(cog).
Above true or should be stated alternately?
Any other basic rules?
Thanks.
Comments
There are a couple ways to run code in a new cog. If using lmm or cmm models, you could start a new lmm/cmm kernel in the next available cog by using the cogstart function.
From any memory model, you can use the Propeller's native cognew to start a new cog running pure PASM (or PASM compiled from C... aka, cogc).
So first, it would likely be helpful if you specify what type of cog you want to start.
It very much depends on exactly what you're trying to do. The simplest way to start C code in another cog is to use the cogstart function, and that does indeed take as a parameter a pointer to a function returning void (to be precise the argument has type void (*func)(void *arg). That function does not have to loop forever -- if it exits the cog it was running on stops automatically. The function will be run in the same memory model you are currently in (LMM or CMM).
Other ways to run C code in another cog are:
(1) with the pthread library function pthread_start (very similar to cogstart)
(2) with OpenMP pragmas (probably not available in simpleIDE)
(3) by compiling the C code with -mcog and linking it specially ("COGC mode"). This is different from the other ways because the C code is running directly on the COG, so it is very fast but must fit in the COG memory
What are you trying to accomplish in the other cog?
Current checklist:
proper function declaration/protoype
forward declaration
matching number arguments in call with number of parameters in declaration
* special rules for functions to be used in cogs:
*- function is infinite loop (later add option of cog_end)
*- function return is void
Vars visible across cogs need to be volatile
etc.
Thanks.
I would think cogstart would be the simplest - by far.
And for this case, you definitely want an infinite loop and return value of void... but I never liked it when my professors would say something is "required" when it isn't truly. Strongly suggested, yes. Required by your grading rubric... probably lol. But not required by the compiler.
Right, cog_start is also on there.
Sometimes I start with "required" then after initial success introduce exceptions.
Joke on grading well received - necessary but a drag.
Just checking to make sure you've seen or know about Andy's Multicore Approaches tutorials. They go through a lot of what you're asking about here.
If you've already gone through them – great! If not, I definitely recommend them.
Not sure I know what you mean. If you actually want to write code that will be loaded into COG and run entirely in COG, then you need to know about, dare I say it, _NAKED functions and _COGMEM variable declarations.
Do have a look in the demos that come with prop-gcc. Should be in /opt/parallax/demos.
Or on line in the source code repository. For example: https://github.com/parallaxinc/propgcc/blob/master/demos/toggle/cog_c_toggle/toggle_fw.c
I seem to recall that SimpleIDE has some convention about naming such sources as *,cogc rather than *.c. Is that still true?
C is nice, but why does it have to overcomplicate everything?
Flexibility and optimization. That of course has it's drawbacks, and arguing which is better has been done a thousand times already. But the answer to your question is quite simple.
The Propeller architecture does not support C at all well. Hence the contortions required to get it to work.
I'm not sure what you mean. Do you mean modifications to the C language itself to make it somehow Propeller friendly? In that case it is not C any more and nobody would be interested in using it.
GCC is quite happy targeting small devices. Like AVR, the Arduino uses GCC.
Seems the Problem is that the Prop can only run native code in it's 2K COG spaces. But it has 32 bit instructions so not much compiler generated code can be made to fit.
After that we get into the world of code in HUB and LMM. Big code and slow.
I'm actually quite happy with that because writing assembler for the Prop is so easy. That's where the fast bits go. The rest of the app can amble along in C.
All in all I'm very impressed with how well the prop-gcc guys have gotten GCC to work with the Propeller.
PropGCC came along, and suddenly almost everyone but Parallax itself decides that Spin, which I consider to be a nearly perfect language for the Prop, is to shunned in favor of C. Not just people new to the Propeller scene are using PropGCC (it's a great entry point for them) - many people who have been using the Propeller with Spin and PASM for years seem to be switching to C for a reason completely unknown to me. If Spin was designed specifically for the Propeller, and C is such a bad fit for the propeller and not much faster and around the same code size, why would anyone prefer C over Spin?
You say that Spin is designed for the Propeller but that C isn't a good fit. I'd like to suggest that Spin isn't a very good fit either. Spin is dog slow and has to run on top of a bytecode VM. The truth is, the Propeller isn't designed for high-level languages of any sort. It's great for PASM though. In fact, PropBASIC might be the language best suited for writing programs that run entirely in a COG.
Thanks for suggestions re my question. That should guide students making their first custom functions to run in a cog.
One small thing on default cog use with C written in SIDE and the default of CMM Main RAM compact. I see conflicting information. Is this the normal pattern that occurs by default in the simplest case?
main() in cog 0
simpletools.h in cog #1
(if math library) in cog #2
user-created functions start in cog #3 (#2 if no math library)
Thanks.
Also as far as I can tell simpletools.h will only add defines and code that will be used from your program. In COG 0 (Unless it actually starts a serial driver or whatever which could be in any other COG)
Same for the maths functions. They are just code that is called and run on your COG0
Same for user created functions.
When do other COGs get used then? I hope the answer to that is only when your program asks for code to be run from other COGs. Either explicitly or implicitly by using some driver from a library. This should be in the documentation for the driver.
What COGs get used? We do not know. In general when code is started in a COG the next free COG is used, whatever it is.
Do we need to know what COG is used for what? Not usually.
To conclude, this is accurate for students starting cogs for the first time?
Cog #0 holds main() and any user-defined functions in the main file. Since the #include brings additional functions into main() before it loads, simpletools is also in cog#0. Additional cogs are used only if started by a command. Sometimes that is explicit by int *cog = cog(...). Sometimes a new cog is started implicitly by a high-level function like the servo commands. Exactly which cog is used beyond #0 is not important to us at this level.
In general no matter if using C or Spin one should use gognew rather than coginit. That way the Propeller sorts out where things end up and you don't have to keep track of which COG is doing what.