Blocking channels - Shared Variables

Technical questions regarding the XTC tools and programming with XMOS.
User avatar
JasonWhiteman
Active Member
Posts: 63
Joined: Mon Jul 15, 2013 11:39 pm

Blocking channels - Shared Variables

Post by JasonWhiteman »

XCore experts,

This one should be relatively simple. I ran into issues with thread blocking using channel I/O, so I switched to a global variable with a single function producer/consumer use and second function consumer-only use.

Reading the variable usage, I thought I was fine. However, I receive a "violation of parallel usage rules" error. The compiler flags the 1st instance of the variable used in each function.

int shared_variable; // global def

func1()
{
if (shared_variable == 1) foo=5;
}

func2()
{
shared_variable = 1;
}

Further notes: func1() is par'd in main as a thread on core 0. func2() is par'd in main as a thread on core 0.

I originally was using channel communication to handle passing information from func1 to func2. This was abandoned due to the blocking nature of channel usage. My func1() consumer actually contains a slow-clock generator (looped circular counter). I wasn't seeing my counter progress due to the wait on incoming channel data.

My next fix is to try the select/case "trick". However, fix or no fix - I would like to better understand the rule violation.

I did a search and looked through a couple pages of results before posting. Hopefully it wasn't answered on checked_page +1.

Regards,
Jason Whiteman


TjBordelon
Active Member
Posts: 39
Joined: Mon Jul 29, 2013 4:41 pm

Post by TjBordelon »

I believe shared memory is discouraged because of the mindset of the architects. Everything is supposed to communicate with channels so code can be on any core.

But technically there is absolutely nothing wrong with what you are trying to do. The language just prevents it. So long as the operation is "atomic" and can't be partially updated this is entirely valid.

There are tricks others point out if you search the forums, but the basic idea is to cheat using C. Create yourself a few C functions that pass data through a global..

Code: Select all

----[ foo.c ]----

int shared_variable; // global def

int GetSharedVariable() { return shared_variable;}
void SetSharedVariable( int v) { shared_variable = v;}

----[ meanwhile_back_at_the_farm.xc ]----

int GetSharedVariable();
void SetSharedVariable( int v);  // Poor man's prototypes

func1()
{
if (GetSharedVariable() == 1) foo=5;
}

func2()
{
SetSharedVariable() = 1;
}

You can even get fancier in asm using locks and set a bunch of state that needs to be "atomic" aka updated at once.

Again, nothing wrong with doing this. I believe it makes more sense in many cases where cores are running on the same tile, and you know that to be the case. You can obviously get into trouble with this (as you can with pointers) but we're grown-ups :)