Bug creation and email sending has been disabled, file new bugs at gcc.gnu.org/bugzilla
Bug 16 - Programs that use std.parallelism.taskPool hang
Summary: Programs that use std.parallelism.taskPool hang
Status: RESOLVED WONTFIX
Alias: None
Product: GDC
Classification: Unclassified
Component: gdc (show other bugs)
Version: development
Hardware: x86_64 Linux
: --- normal
Assignee: Iain Buclaw
URL:
Depends on:
Blocks:
 
Reported: 2012-10-18 20:08 CEST by Artem Tarasov
Modified: 2012-12-16 09:25 CET (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Artem Tarasov 2012-10-18 20:08:37 CEST
I've compiled GDC trunk with latest GCC.

Then I compiled the following code with GDC:

import std.parallelism;
void main() { taskPool; }

Most times, the produced executable just hangs. However, on every 5th run or so, it finishes execution immediately, as expected.

Output of gdc -v:

Using built-in specs.
COLLECT_GCC=gdc
COLLECT_LTO_WRAPPER=/export/local/users/artem/opt/gdc48/bin/../libexec/gcc/x86_64-unknown-linux-gnu/4.8.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc-4.8-20121014/configure --enable-languages=d --enable-checking=release --prefix=/home/artem/opt/gdc48 --enable-multilib
Thread model: posix
gcc version 4.8.0 20121014 (experimental) (GCC)


Glibc version: 2.11.3-3
Comment 1 jerro.public 2012-12-16 04:47:21 CET
I'm having a problem with this bug too, but for me the test case in the report only hangs in rare cases. This hangs every time for me (on x86_64 debian wheezy with commit f07f442 of GDC built with GCC 4.8-20121209):

import std.stdio, std.parallelism;

void main()
{
    writeln(taskPool.reduce!"a+b"([0, 1, 2, 3]));
}

The reason for this is that gdc generates code that doesn't call atomicReadUbyte(status) on every iteration of the loop in std.parallelism.TaskPool.workLoop as the source code does, but calls it once before the loop begins and then uses a stored value inside the loop.
Comment 2 Johannes Pfau 2012-12-16 09:14:38 CET
Great. Remember the "we don't need volatile in D, it's dangerous" statements? This problem is caused by not having volatile...

workLoop repeatedly calls atomicReadUbyte(status). status is a member of TaskPool with type ubyte. It's not marked as shared or volatile, but it's used as a shared variable. atomicReadUbyte also doesn't mark its parameter as shared/volatile.

The GCC backend only sees a repeated access to a thread-local variable. It can't know that the variable can be changed by different threads and obviously optimizes the repeated function call away. It's the textbook example of volatile.

The solution is probably not that obvious. There have been discussions whether shared/__gshared should imply volatile, but as long as there is no official statement in this regard, there's not much we can do.

Anyway, it's a bug in std.parallelism, not in gdc so I'll file a bug report on the phobos bugzilla.
Comment 3 Johannes Pfau 2012-12-16 09:25:45 CET
http://d.puremagic.com/issues/show_bug.cgi?id=9163