Test and Set atomic operation

Go To Last Post
27 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is there a test and set atomic operation on any XMEGA processor? 

 

This would normally be an instruction in the processor instruction set. This is needed to implement a semaphore or mutext or similar functions.

I have looked at the XMEGA-C manual that lists all the assembly language instructions but I did not see it, although maybe it's done is some other way.

(I happen to be using the XMEGA384C3 but I saw somewhere that all XMEGA processors are software compatible.)

 

 

 

 

This topic has a solution.
Last Edited: Wed. Jul 26, 2017 - 05:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Look in the AVR-LibC documentation.

 

I think that you will find that it mostly just involves a cli and and sei.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Tue. Jul 25, 2017 - 03:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is it LAS instruction?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kabasan wrote:
Is it LAS instruction?
Yup, those were the new instructions added to Xmega for exactly this process

 

Previously (tiny/mega) one just need to have interrupts disabled for a couple of opcodes while doing it using more opcodes.

Last Edited: Tue. Jul 25, 2017 - 03:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Any word on if/when GCC will support them? At the moment I'm using macros and it's hard to see how the compiler could really integrate them for atomic operations, but I'm often wrong about that kind of thing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't really set a test here?

Rd is loaded after the operation!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not understanding how the LAS, LAC or LAT can be used, in the case of the
sei() or cli() they can protect my own test-and-set as follow....

 

cli()
if(!x){ x = 1; <critical code> }
sei()

 

if the lock is available it takes it, if not available it does nothing.

 

But the LAS(which I guess is a form of LDI) does not perform the operation conditionally.
I'm confused.

I can't find the documentation for LAS, LAC and LAT either I'm relying on your post.

Last Edited: Tue. Jul 25, 2017 - 04:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
Rd is loaded after the operation!

No, the picture in #3 is a little bit misleading. Actually it is:

temp <- Rd

Rd <- (Z)

(Z) <- temp v (Z)

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dan_meg wrote:
But the LAS(which I guess is a form of LDI) does not perform the operation conditionally. I'm confused.
After the operation the register contains the old content of the memory location. So you know which bits were already set.

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No, the picture in #3 is a little bit misleading.

 

No it's not misleading it WRONG! 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
No it's not misleading it WRONG!
I would not go that far.

Don't give the lines a time relation (one after the other). It is one instruction, so both lines happen simultaneously. Instead you can attach a "new" to the left column and an "old" to the right.

new (Z) = old Rd v old (Z)

new Rd = old (Z)

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:

No, the picture in #3 is a little bit misleading.

 

No it's not misleading it WRONG! 

I'm not an Xmega person, so find this thread interesting.

 

Y'all have to educate us tyros on what is wrong and/or misleading.  I don't know the source of the picture in #3, but it seems to follow the Instruction Set document.

[how do these instructions relate to OP's "test-and-set" desire?]

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:
[how do these instructions relate to OP's "test-and-set" desire?]
This instruction is a "set and give the opportunity to test afterwards". It serves the same purpose as "test-and-set".

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok I wrote my first ever xmega program:

    ldi r16,0x0f
    ldi r30,0x00
    ldi r31,0x20
    st z,r16
start:
    inc r16
    las z,r16
    rjmp start

And ran it in the simulator at the end we have this:

r16==0x0f (what I wrote in line 4)

and memory 0x2000 is 0x1f (as expected)

 

So sternst is correct and the documentation is WRONG !

 

But stille there is no test!

Last Edited: Tue. Jul 25, 2017 - 09:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
So sternst is correct and the documentation is WRONG !
Nope, it is not wrong. You are putting a chronology into the two parts of the instruction, which actually does not exist.

sparrow2 wrote:
But stille there is no test!
You have to do the test yourself afterwards.

Stefan Ernst

Last Edited: Tue. Jul 25, 2017 - 09:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
So sternst is correct and the documentation is WRONG !

I understand what you are getting at. ;)  It makes my head hurt trying to think of how to make the one-line instruction description.  The comma apparently means "at the same time". ;)  Like a prisoner exchange, walking towards each other over the bridge.

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Tue. Jul 25, 2017 - 09:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok in one line I get it, but I would use something double arrows. (I just looked at swap and there they do the same, never looked at it, because that one I know how works :) )

But the #3 that don't make any sense when you write it in two lines.

 

 

Add this is how 8086 XCHG is described :

 

operand1 < - > operand2

That is way better but perhaps not perfect. 

 

and for  z80      EX  DE,HL  

have this :

DE ↔ HL

I didn't know the normal font had  "↔"  

Last Edited: Tue. Jul 25, 2017 - 10:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

    Lets say you have three tasks (taks0, task1 and task2) and each is using the same resource, be it a peripheral, memory area. When task0 is in control of that resource it sets bit zero at memory location 0x2000 for example. When task1 is in control of the resource, it sets bit 1 and so on. You want to use this resource in a non blocking way.

    Now lets say that now task2 is in control and bit2 is set. Main is jumping to task0. Task0 wants to use the resource and perform LAS 0x2000, 1. It just tries to take over at this point. Then it tests back the old value which happen now to be 4 (task2 in control). The resource is not available, so it performs a LAC 0x2000, 1. Now it goes to task1. If the result would have been 0, then task0 would go ahead and use that resource. No cli, sei involved.

    This probably can be done in a different way. It is just an example about how you set a bit and perform the task if test OK or do not perform the task and clear back your bit if test not OK.

 

    George.

Last Edited: Tue. Jul 25, 2017 - 11:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It seems like these instructions were mostly designed for the XMEGA's peripherals where you often clear flags by writing 1 to them. It's a nice atomic way of clearing the flags and capturing the state in an atomic operation so that you don't miss flags being re-set between read and write instructions.

 

Of course hardly anything bothers to actually use them for most peripherals. USB seems to be the main area where they are important.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

> Any word on if/when GCC will support them?

 

GCC could support then as target-specific built-in.  The problem will be for devices which don't support read-modify-write because open-coding replacements might be tricky to implement.

 

Up to now noone has interest in such thing (and hence noone added such support).

avrfreaks does not support Opera. Profile inactive.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Has anyone seen them used outside of the XMEGA USB memory mapped endpoints?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The whole idea of the "test and set" operation traditionally was that it would be done atomically, that is the key that allows it to be used for a semaphore or mutex. 

 

This scenario with the test afterwards is not atomic and opens it up to another task or interrupt coming in before the test and so apparently fails to be useful as a semaphore in a multi task environment. 

It fails because if the first task tested after a second task snuck in, it would not know who now owns the semaphore since more than one bit is set.

(it might be possible to use this in a simple foreground/background multi threaded situation I suppose)

 

But if someone is actually using this for a semaphore than please share your code or please let us know what function implements it.

 

 

 

 

Last Edited: Wed. Jul 26, 2017 - 04:23 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Assume a resource controlled by 1-bit. (e.g. bit 0 of address 0x2000):

    ldi r16,0x01 ;r16 = bit to test and set
    ldi r30,0x00
    ldi r31,0x20  ;r31:r30 = address to test
    las z,r16     ; get the bit and also set it

After the LAS, r16 contains previous contents of 0x2000.

At this point if the LSBit of r16 contains 0, the resource was not in use and may be used. (and the bit is now 1, indicating resource busy for this process)

If the LSBit of r16 contains 1, the resource was in use and should not be used by this routine.

 

Edit: better demonstration example...

start:
    nop
    nop
wait_for_resource:
    ldi r16,0x01  ;r16 = bit to test and set
    ldi r30,0x00
    ldi r31,0x20  ;r31:r30 = address to test
    las z,r16     ; get the bit and also set it
    sbrc r16, 0   ; test bit 0, skip if bit clear 
    jmp wait_for_resource
got_resource:
    nop
    nop
    jmp start

 

David (aka frog_jr)

Last Edited: Wed. Jul 26, 2017 - 05:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I like Frog_jr's answer, I see now that it works!  Sorry for the confusion. 

 

Thank you all for the great discussion!

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dan_meg wrote:
This scenario with the test afterwards is not atomic and opens it up to another task or interrupt coming in before the test and so apparently fails to be useful as a semaphore in a multi task environment.
Not true. The data for the test was gathered within the atomic instruction, and the test is a different one than in "test-and-set". The instruction is a 'set' without a 'test', so basically a "try to get the resource without looking whether it is free". The test afterwards then is "did I get the resource or not?".

Stefan Ernst

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes Sternst you are correct, maybe the "test-and-set" should now be called "read-and-set", which happens as an atomic operation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

maybe the "test-and-set" should now be called "read-and-set",

Uh...

 

LAS = load-and-set

LAC = load-and-clear

LAT = load-and-toggle

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]