Currently I have a control task on tile 0 that communicates with a number of tasks on tiles 2 and 3. This consumes a lot of chanends. I was thinking of having a broker/manager process on tile 2 and 3 that consumed the control information and stored it in shared memory.
Are word reads and writes atomic on XS2 or do I need to use locks?
Store atomicity Topic is solved
-
- Active Member
- Posts: 38
- Joined: Sat Jul 08, 2023 5:15 am
-
Verified
- XCore Legend
- Posts: 1158
- Joined: Thu Dec 10, 2009 9:20 pm
- Location: Bristol, UK
Word reads/writes are atomic, there are single word (32bit) load and store instructions.
You could read/write a couple of words atomically by targeting the double word (64bit) access instructions.
You could read/write a couple of words atomically by targeting the double word (64bit) access instructions.
Technical Director @ XMOS. Opinions expressed are my own
-
- Active Member
- Posts: 38
- Joined: Sat Jul 08, 2023 5:15 am
Thanks Ross!
Interestingly I am getting ET_LOAD_STORE when I try to write. Here's a simplified version of the code:
long_long_array_to_xc_ptr() is the same as the other variants, I wanted 64-bit alignment so I can potentially read 64-bit words as you described above.
I wasn't sure if SET/GET_SHARED_GLOBAL() are necessary or indeed whether I could just declare the global variables in C rather than XC. I tried many permutations all which raised ET_LOAD_STORE.
Interestingly I am getting ET_LOAD_STORE when I try to write. Here's a simplified version of the code:
Code: Select all
// 64-bit word stores 16-bit LR gains as well as various flags
static uint64_t __control[NUM_MIXER_OUTPUTS];
xc_ptr gControl;
void
init(void) {
SET_SHARED_GLOBAL(gControl, long_long_array_to_xc_ptr(& __control[0]));
}
xc_ptr getBasePointer(void)
{
xc_ptr basePointer;
GET_SHARED_GLOBAL(basePointer, gControl);
return basePointer;
}
static inline void
setGain(xc_ptr basePointer, uint8_t outputChannel, uint16_t lgain, uint16_t rgain)
{
uint32_t lrgain = (lgain ≪ 16) | rgain;
// *2 because accessing 32-bit offset
write_long_via_xc_ptr_indexed(lrgain, (size_t)(2 * outputChannel), basePointer);
}
void
runTask()
{
...
setGain(getBasePointer(), 0, 0, 0);
...
}
I wasn't sure if SET/GET_SHARED_GLOBAL() are necessary or indeed whether I could just declare the global variables in C rather than XC. I tried many permutations all which raised ET_LOAD_STORE.
Last edited by lukehatpadl on Mon Oct 07, 2024 7:27 am, edited 1 time in total.
-
- Active Member
- Posts: 38
- Joined: Sat Jul 08, 2023 5:15 am
Possibly related question: does each tile get its own copy of global variables? I presume so.
Followup question: is there a preprocessor macro I can use to determine the current tile at compile time? Could be useful for adding some safety checks.
Followup question: is there a preprocessor macro I can use to determine the current tile at compile time? Could be useful for adding some safety checks.
-
Verified
- XCore Legend
- Posts: 1158
- Joined: Thu Dec 10, 2009 9:20 pm
- Location: Bristol, UK
SET/GET_SHARED_GLOBAL macros in the USB Audio codebase hark back to the days with xc didn't have any support for pointers - so inline asm was used.
These days you're better off using an "unsafe" pointers:
These days you're better off using an "unsafe" pointers:
Code: Select all
#include <print.h>
long long var;
int main()
{
unsafe
{
long long * unsafe ptr = &var;
*ptr = 100LL;
printllongln(*ptr);
}
}
Technical Director @ XMOS. Opinions expressed are my own
-
Verified
- XCore Legend
- Posts: 1158
- Joined: Thu Dec 10, 2009 9:20 pm
- Location: Bristol, UK
Each tile will have its own independent version of each global.
Not aware of anything in the preprocessor, but you could use
Not aware of anything in the preprocessor, but you could use
Code: Select all
unsigned get_local_tile_id(void);
Technical Director @ XMOS. Opinions expressed are my own
-
- Active Member
- Posts: 38
- Joined: Sat Jul 08, 2023 5:15 am
Thanks! This is more elegant, although I still needed to use the macros for initialising the global to avoid the parallel usage error.
Compiles:
Code: Select all
SET_SHARED_GLOBAL(gOutputMixerControl,
long_long_array_to_xc_ptr(&__gOutputMixerControl[0]));
Code: Select all
unsafe {
gOutputMixerControl = long_long_array_to_xc_ptr(&__gOutputMixerControl[0]);
}
-
- Active Member
- Posts: 38
- Joined: Sat Jul 08, 2023 5:15 am
FWIW, I resolved the ET_LOAD_STORE exception issue by just migrating the code that wrote to the array to C. When I have a moment I'll compare the assembly output to see exactly what's going on. I'm still using the xc_ptr.h helpers on the read side.