Synchronising multiple threads

Technical questions regarding the XTC tools and programming with XMOS.
Post Reply
leobodnar
Member
Posts: 12
Joined: Mon May 07, 2018 9:26 am

Synchronising multiple threads

Post by leobodnar »

What are the ways of having multiple threads synchronised?
Say 7 threads are waiting and get released by the 8th at once?
Wiring 8 single ports together will work but is silly.

Essentially - can several threads wait on a shared resource?

Leo


User avatar
CousinItt
Respected Member
Posts: 360
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

Can you be a bit more specific about where these threads reside? Are they running on the same core, the same tile, or anywhere in a network of devices?
leobodnar
Member
Posts: 12
Joined: Mon May 07, 2018 9:26 am

Post by leobodnar »

CousinItt wrote: Thu Oct 15, 2020 10:38 pm Can you be a bit more specific about where these threads reside? Are they running on the same core, the same tile, or anywhere in a network of devices?
Each thread/task is running on its own logic core on the same tile.
Perhaps, using timer event is viable (assuming all timers on the same tile report the same time.)
Leo
User avatar
CousinItt
Respected Member
Posts: 360
Joined: Wed May 31, 2017 6:55 pm

Post by CousinItt »

If the tasks are on the same tile then they share memory. An unsafe pointer can be distributed to the dependent tasks, and they can each wait for the value to change. Would that work for you?

<EDIT/> See also this thread: viewtopic.php?t=3061.
leobodnar
Member
Posts: 12
Joined: Mon May 07, 2018 9:26 am

Post by leobodnar »

Thanks,
Yes, I have ended up using a shared flag in .data section - initially set to zero with all slave tasks waiting for it to be set and the master task the only one writing [1] to it when it's done.
Then I am using locks to sync the hardware resources use, but that's another story.
It all looked very bamboozling until I wrote it in assembly and it's suddenly clean and simple.
Cheers
Leo
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

I wrote a barrier task (I think that's a term for this pattern) for synchronizing my PWM LEDs, to be covered in a blog note [1]. I tested with interface and channels, and also with combinable or not, and was able to get some/one of those running stable. I could publish some of the basic code here later this week. But I will also update the note with the full code. I promise to be back.

[1] My XC softblinking PWM notes Disclaimer no ads, money, gifts, just fun and expenses with my blog notes. This does not contain presently contain the barrier code, I will place it there during this week.
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
akp
XCore Expert
Posts: 578
Joined: Thu Nov 26, 2015 11:47 pm

Post by akp »

If you use the xc_ptr.h with GET_SHARED_GLOBAL() and SET_SHARED_GLOBAL() you can avoid explicit assembly code. But it does the same thing.
leobodnar
Member
Posts: 12
Joined: Mon May 07, 2018 9:26 am

Post by leobodnar »

The gist of it is...

Code: Select all

		// assume this will be called as func(1,...); for master and func(0,...); for slaves

.section .dp.data, "awd", @progbits
init_done:	
		// 1=master thread has initialised the hardware
		.word	0
.text
		...
		// assume that 1st argument for the function call contains 0 for slave threads and 1 for master thread
		bt		r0, master_thread				

		// this is one of the slave threads,
		// wait until master thread configures hardware and sets the init_done flag
wait_init:
		ldw		r11, dp[init_done]
		bf		r11, wait_init
		bu		all_together_now

master_thread:
		// do whatever needs to be done to initialise the hardware
		...
		// release waiting slave threads
		ldc		r11, 1
		stw		r11, dp[init_done]

all_together_now:

User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

Here is my, somewhat branch-off-thread code:

Code: Select all

[[combinable]]
void barrier_do_chan_task (
        chanend             c_barrier[CONFIG_NUM_SOFTBLIKER_LEDS], // Send and receive id_task_t
        out buffered port:1 outP_external_blue_led_high)           // led_on_high_t
{

    bool num_synched = 0;

    id_task_t id_task [CONFIG_NUM_SOFTBLIKER_LEDS];

    for (unsigned ix=0; ix<CONFIG_NUM_SOFTBLIKER_LEDS; ix++) {
        id_task[ix] = CONFIG_NUM_SOFTBLIKER_LEDS; // No such id
    }

    while(1) {
        select  {
            case c_barrier [int iof_client] :> id_task[iof_client]: { // query
                num_synched++;
                debug_print ("%s%u c_barrier num %u\n", (num_synched==1) ? "\n" : "", iof_client, num_synched); // Empty line above if 1
                if (num_synched == CONFIG_NUM_SOFTBLIKER_LEDS) {
                    for (unsigned ix=0; ix<CONFIG_NUM_SOFTBLIKER_LEDS; ix++) {
                        debug_print ("%u ack\n", ix);
                        c_barrier[ix] <: id_task[ix]; // acknowledge, (ie. started and completed)
                        id_task[ix] = CONFIG_NUM_SOFTBLIKER_LEDS; // No such id
                        debug_print ("%u ack'ed\n", ix);
                    }
                    num_synched = 0;
                }
                outP_external_blue_led_high <: (num_synched > 0); // On while barrier is used
            } break;
        }
    }
}
This is a single task that would sit there and wait until all CONFIG_NUM_SOFTBLIKER_LEDS clients have signalled on their c_barrier sending sides. Then they would all be signalled back again. In other words, they would all get the info that all have been stalled until that time. My code is rather littered with the naming for my usage: PWM blinking. But I did make a library for the combined PWM and the barrier. I found it hard to make a completely general barrier library, it was too hard to get my params across. But welcome to do so! My code is donwloadable from [1]. The code is also littered with debug_print, but it's so nice to use. I compile them completely away with a flag.

I assume this may be considered more idiomatic XC than working with shared objects or pointers. Although, perhaps, not as fast. But I do have an xta script in the usage of this.

My barrier is general, but it does not have the flexibility of [2], like being able to withdraw etc.

Observe that each channel is bidirectional, so they better be used correctly to avoid deadlock! Also that I lit a LED while the barrier is in use.

[1] My XC softblinking PWM notes - For newer and updated code contains _Softblinker_PWM and lib_pwm_softblinker. Observe that you need to remove an underscore in the download zip ref.

[2] csp::Barrier Class Reference
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
User avatar
aclassifier
Respected Member
Posts: 483
Joined: Wed Apr 25, 2012 8:52 pm
Contact:

Post by aclassifier »

I have discovered that David May has mentioned barrier synchronisation in one of his papers. It is very interesting! Just search for "barrier" in:

Communicating Processors Past, Present and Future by David May, Bristol University and XMOS, April 2008, at NOCS, Newcastle. See http://people.cs.bris.ac.uk/~dave/nocs.pdf. (From David May’s home page http://people.cs.bris.ac.uk/~dave/)

In fact he mentions this also in other of his papers (from his home page):

Multicore Architecture
XMOS Architecture XC Language
XMOS Architecture XS1 Chips
--
Øyvind Teig
Trondheim (Norway)
https://www.teigfam.net/oyvind/home/
Post Reply