tag:blogger.com,1999:blog-9184145065528610199.post3546695223512716441..comments2023-05-28T14:25:30.121+02:00Comments on Mr Foo: Atomic setting on ARMtuftyhttp://www.blogger.com/profile/00602829823862264815noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-9184145065528610199.post-74010475968862099812015-03-06T18:25:56.286+01:002015-03-06T18:25:56.286+01:00Found a better way: the entire thing may be writte...Found a better way: the entire thing may be written as<br /><br /> return __sync_add_and_fetch( memory, 1);<br /><br />This is a compiler builtin (supported on gcc and clang, at least) which on ARM will be the same "ldrex add 1 strex until !=0" construct. And it's portable; on x86 it's done with a locked 'xaddl' instruction. <br /><br />See https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.htmldeskwarriorhttps://www.blogger.com/profile/08932272810276042857noreply@blogger.comtag:blogger.com,1999:blog-9184145065528610199.post-75831235086228352162015-03-04T02:23:12.433+01:002015-03-04T02:23:12.433+01:00There are two reasons the exclusivity could fail: ...There are two reasons the exclusivity could fail: (1) another core (or bus agent) could write the location between the ldrex/strex. This is detected by the hardware monitor, since it knows which core is issuing each access. (2) A interrupt could occur between the ldrex/strex, and the same core could then modify the location, either in an ISR or another thread, before the strex can be done in the original thread. That can't be detected by the monitor. So, clrex is used to reset all the outstanding exclusive accesses whenever a context switch occurs. What this means is - if an interrupt occurs between your ldrex and strex, then the strex will always fail, even though it maybe didn't need to. It's no big deal since the event is (a) quite rare and (b) not a lot of extra work anyway. <br /><br />So, it should be completely reliable if used as described here. You don't need to do any 'clrex' in application code since the OS scheduler does that. (If you are writing a low-level ISR then maybe you might need it there, I don't know)deskwarriorhttps://www.blogger.com/profile/08932272810276042857noreply@blogger.comtag:blogger.com,1999:blog-9184145065528610199.post-65288527043991271632015-03-04T01:55:18.474+01:002015-03-04T01:55:18.474+01:00One could also remove the label, cmp, bne, and wra...One could also remove the label, cmp, bne, and wrap the asm in "do { ... }while( temp2 != 0);" so the compiler will use whatever branch is best on the specified machine. Also, I'd make it 'uint32_t volatile *mem' , since any variable used across threads (and which you might pass the address-of to this function) should be 'volatile' (it won't affect how this asm is generated, but it would save you having to 'cast away' volatile when invoking it).deskwarriorhttps://www.blogger.com/profile/08932272810276042857noreply@blogger.comtag:blogger.com,1999:blog-9184145065528610199.post-87808459711297228142015-03-04T01:47:30.476+01:002015-03-04T01:47:30.476+01:00There are two reasons the exclusivity could fail: ...There are two reasons the exclusivity could fail: (1) another core (or bus agent) could write the location between the ldrex/strex. This is detected by the hardware monitor, since it knows which core is issuing each access. (2) A interrupt could occur between the ldrex/strex, and the same core could then modify the location, either in an ISR or another thread, before the strex can be done in the original thread. That can't be detected by the monitor. So, clrex is used to reset all the outstanding exclusive accesses whenever a context switch occurs. What this means is - if an interrupt occurs between your ldrex and strex, then the strex will always fail, even though it maybe didn't need to. It's no big deal since the event is (a) quite rare and (b) not a lot of extra work anyway. <br /><br />So, it should be completely reliable if used as described here. You don't need to do any 'clrex' in application code since the OS scheduler does that. (If you are writing a low-level ISR then maybe you might need it there, I don't know)deskwarriorhttps://www.blogger.com/profile/08932272810276042857noreply@blogger.comtag:blogger.com,1999:blog-9184145065528610199.post-6112582754059931092014-05-05T16:07:22.479+02:002014-05-05T16:07:22.479+02:00Konz
The code compiles fine. The reason for not ...Konz<br /><br />The code compiles fine. The reason for not using cbnz, by the way, is that it's specific to the Thumb instruction set.tuftyhttps://www.blogger.com/profile/00602829823862264815noreply@blogger.comtag:blogger.com,1999:blog-9184145065528610199.post-40920620639001384772013-11-21T16:45:12.348+01:002013-11-21T16:45:12.348+01:00The code would be easier to read if you replaced \...The code would be easier to read if you replaced \t with spaces or real tabs. Also, you can reduce the number of double-quotes by continuing the line with a final backslash. At the assembly level, you should look at cbnz, this replaces your last two lines. Finally, I don't think you actually compiled this code: the extra set of square brackets around the memory operands are wrong.Konzhttps://www.blogger.com/profile/06061640618369768590noreply@blogger.comtag:blogger.com,1999:blog-9184145065528610199.post-70290618987890511982013-05-27T15:39:04.896+02:002013-05-27T15:39:04.896+02:00I agree with Claus, this post makes it seem comple...I agree with Claus, this post makes it seem complex. And buggy - when you say ldrex/strex covers 99.99% of cases in this super-simple example, what happens with the remaining .01%? How do they fail, and how does clrex fix the problem? And if ldrex/strex sometimes fails when the case is this simple, does it fail more often or more horribly with more complicated cases?Felicity Pilchardhttps://www.blogger.com/profile/11674742547506549132noreply@blogger.comtag:blogger.com,1999:blog-9184145065528610199.post-2153147200427920762012-07-18T13:55:58.430+02:002012-07-18T13:55:58.430+02:00Hmm, it sounds so complex with the clrex command. ...Hmm, it sounds so complex with the clrex command. What do you mean you clear it in the task schedule, if i use the atomic_add for semaphores, do the task schedule check all semaphore and clear them? sounds a bit of work then to do? or didnt i get it?`:-)CyCl0nehttps://www.blogger.com/profile/00970358219385574675noreply@blogger.com