How to use the same memory in multi threads?

Technical questions regarding the XTC tools and programming with XMOS.
porsche
Member
Posts: 15
Joined: Fri Nov 11, 2011 9:57 am

How to use the same memory in multi threads?

Post by porsche »

hi all:
In a core, how to use the same memory location in the multiple threads in a core?
Have any one done the ways?
I hope the memory pool is used for data & control processing.
How to set the compiler to ignore these pool memory range?
Or there has the lib to manipulate these memory pool?
Thank you!


User avatar
XMatt
XCore Addict
Posts: 147
Joined: Tue Feb 23, 2010 6:55 pm

Post by XMatt »

From C code you can access the memory however you like, so calling some C code to do the memory access from the threads will be the easiest option.
porsche
Member
Posts: 15
Joined: Fri Nov 11, 2011 9:57 am

Post by porsche »

Hi Hacker:
I think over the access of the same memory between threads in a core.
How to implement?
Through channel tell the threads where the shared memory location?
Or directly assign the memory address but how?
Can you give an example?

By the way if the access of the same memory between 2 threads in different cores,
is there impossible, right?
Heater
Respected Member
Posts: 296
Joined: Thu Dec 10, 2009 10:33 pm

Post by Heater »

porche,

Two threads in XC cannot share the same memory.
Each of those threads could call a C function to access a shared memory region.
The address of the shared pool being only know to the C code.

So create a C module. In there define your shared memory area, an array or struct or whatever. Also define access functions in C that can be called from your XC code.

Be ready to deal with race conditions and corruption as your XC threads make simultaneous updates to that data area.

No threads on different cores cannot share RAM. Each core has it's own RAM space.
User avatar
Berni
Respected Member
Posts: 363
Joined: Thu Dec 10, 2009 10:17 pm

Post by Berni »

The easiest is to move your code in to a .c file and then you can do with memory whatever you like just as in C, the downside of using C is that all the hardware is not available to you(Pins,timers etc) but it would be possible to make wrappers for those in XC if timing is not critical.
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

Berni wrote:The easiest is to move your code in to a .c file and then you can do with memory whatever you like just as in C, the downside of using C is that all the hardware is not available to you(Pins,timers etc) but it would be possible to make wrappers for those in XC if timing is not critical.
You can access the hardware resources directly from C just fine;
since C does not have language constructs for that, you use compiler
builtins or inline assembler statements.

What XC brings to the table is a set of simple rules that make it
possible to reason about how the program works when running
on multiple threads (or cores). Sometimes in an XC program you
want to break those rules, because they are too limiting (for example
some shared buffer thing), but then you have to enforce correctness
yourself. This is useful for components that are mostly "stand-alone",
have a small "surface"; on the other hand, wrapping tiny pieces of XC
in a C interface gives you none of the good things of XC, but does
give you all its downsides (and you get some lovely call overhead
"for free" ;-P )
porsche
Member
Posts: 15
Joined: Fri Nov 11, 2011 9:57 am

Post by porsche »

Hi Segher:

Indeed the sharing buffers is a hot point. Use channel to pass the big buffers to other threads is not as good as to pass the reference.

Think about a scenario, one thread has one large size data and other threads want to read this large size data to process.

But how to pass the reference in .xc to another .xc (or .c) in different threads? Can you give a sample code for me to research ?
User avatar
Berni
Respected Member
Posts: 363
Joined: Thu Dec 10, 2009 10:17 pm

Post by Berni »

Well i dont think i remember doing shared variables, but by how much this is used there could be something to make it ignore this(There is a #pragma unsafe arrays but from what i read all that does is remove boundary checking to speed stuff up)

Well one way i could see it possible to share a variable over a channel is if you used (unsigned int)%your_var; to get an address of the variable that you can pass over a channel as a normal integer. On the other side you again feed that back to a C file where you go distant_var = (*unsigned int)addr; (distant_var has to be a pointer). But do remember that you must do this between threads on the same core since if its not all it does is read junk without any warning.
User avatar
lilltroll
XCore Expert
Posts: 956
Joined: Fri Dec 11, 2009 3:53 am
Location: Sweden, Eskilstuna

Post by lilltroll »

If you need acess to channels and ports, it might be easier to create a pointer with asm in xc.

first

Code: Select all

static char data[256]
This example is for hispeed RS232 working with packages of data ,including crc32. In this example I have a circular buffer called data with size char[]

The receiving thread works as usual with xc. When a package has been received, the thread sends a control token plus the starting index of the package in the buffer as a uint32 on a streaming channel.

The supervising thread manipulating the data uses a select

Code: Select all

			case sinct_byref(c_RX,command):
			c_RX:>start;
			asm("add %0,%1,%2" : "=r"(ptr) : "r"(data) , "r"(start));

I now have information on where to go next based on the control token (command), and I also have a pointer (prt) to the memory where I can start to read.
Depending on how I wish to interpret the data in the buffer, I can use the instructions ld8u, ld16s or ldw to access the array.

An example would be that the data holds 3 signed shorts

Code: Select all

	asm("ld16s %0,%1[%2]": "=r"(short1)		: "r"(ptr) , "r"(0) ); //load word with sign extension
	asm("ld16s %0,%1[%2]": "=r"(short2)	: "r"(ptr) , "r"(1) );
	asm("ld16s %0,%1[%2]": "=r"(short3)		: "r"(ptr) , "r"(2) );
PS1, using short or longs instead of chars, you should not use add to calculate the offset, instead use ldaw for words etc. DS.
PS2, ld16s and ldw must be align in memory. An address to ld16s must be even, and an address to ldw must be an multiple of 4. DS.
PS3. If you for an example need to avoid that the RX thread stalls, due to that the master thread is busy, you could send only a control token over the channel. An control token is only 8 bits, and the channel buffer is 64 bits. That way I could receive 8 packages of data, without stalling the receiving thread even if the master thread is occupied with other operations. (I would need to create a new vector that holds the buffer-index's.) DS.
User avatar
segher
XCore Expert
Posts: 844
Joined: Sun Jul 11, 2010 1:31 am

Post by segher »

porsche wrote:Indeed the sharing buffers is a hot point. Use channel to pass the big buffers to other threads is not as good as to pass the reference.
That is correct: if you have to delay sending the data on (maybe because
the receiver is busy -- try to avoid that, stream everything, go with the
flow!), or if more than two threads on the same core as your sender have
to receive the same data and you would rather spend more time in the
receivers and less in the sender (usually advantageous because of how
the thread scheduling interacts with the receive code), or if *both* the
sender and the receiver need the data in memory for other reasons (for
example, if they both need to do some transform on it that requires random
access to the data); in such cases, it is better to pass the data around
in memory.

In all other cases, it is faster to pass the data over a (streaming)
channel. This also has the rather big advantage that your code components
become more decoupled; also, you can then move some components to another
core to get a snugger fit.

But sometimes, you really want to have a shared buffer, for good reasons
(which doesn't happen so often) or bad reasons ("it's what we're used to").
But how to pass the reference in .xc to another .xc (or .c) in different threads? Can you give a sample code for me to research ?
You cannot do it in pure XC (you can do some tricks with inline assembler).
If you go via C, it is easy: every (global) variable is shared between all
threads. Well, "easy": you now have to solve the data hazards and other
ordering stuff yourself.

I don't have any example code in either C or XC, sorry.