__sync_add_and_fetch in objc block for global variable on ARM

Hello community,

I faced with bug in multithread environment in objective C code which using dispatch_async and block,
__sync_add_and_fetch increments global variable. But in case of many..many threads> 5, after every
__sync_add_and_fetch got damaged

...
int32_t count = 0;

...

int
main(int argc, char *argv)
{
for (i = 1; i < 32; ++i) {
...
char* name;
asprintf(&name, "test.overcommit.%d", i);

    dispatch\_queue\_t queue = dispatch\_queue\_create\(name, NULL\);
    free\(name\);
    dispatch\_set\_target\_queue\(queue, dispatch\_get\_global\_queue\(0,
                dispatch\_get\_global\_queue\(DISPATCH\_QUEUE\_PRIORITY\_LOW, 0\)\)\);

    /\* async queue \*/
    dispatch\_async\(queue, ^\{
       \_\_sync\_add\_and\_fetch\(&amp;count, 1\); //&lt;&lt; Here count is corrupted in case of number of threads&gt; \~5
       printf\(&quot;count addr %p, value %d\\n&quot;, &amp;count, count\);
       fflush\(stdout\);
    \}\);

}
...
dispatch_main();
}

in case of count is local variable in scope of main function and has __block attribute, all is fine.

I'm using
clang version 3.3 (tags/RELEASE_33/final)
Target: armv7l-unknown-linux-gnueabi
Thread model: posix
libBlockRuntime 0.3
libdispatch for linux 1.2
CPU is ARMv7,
in disas I see dmb ish instruction, but I don't know is it enough.

I understand, my clang is out of date. Moving to new version could be painful )
Maybe somebody knows, was that bug fixed?

BR,
Alexey

in disas I see dmb ish instruction, but I don't know is it enough.

There should be 2 dmb instructions: one before the ldrex/strex loop
and one after. But I wouldn't expect dropping one to actually cause a
problem in the code you posted.

In what way is "count" corrupted, and how do you observe it? What
assembly is actually produced for the block?

I understand, my clang is out of date. Moving to new version could be painful )
Maybe somebody knows, was that bug fixed?

That area's certainly improved, but I'm not aware of any bugs on that
scale ("can't dispatch 32 threads to atomically increment a single
variable and print it") in clang 3.3 so I think something else is
probably going on.

A self-contained, minimal example we can examine would be useful.

Cheers.

Tim.

Hi Tim

disp_async_min.m (1.74 KB)

Hi Tim, thank you for response and sorry my fault,

count name in example is too general, my objc runtime is using it for handling auto release pool
occupancy.

compiler is fine :wink:

Ah! That would certainly do it. Glad you managed to sort the issue.

Tim.