Re: Re: Re: Adding a new thread model to GCC
One more question about block-scoped static objects: >From compiled assembly I have learned that GCC uses a 64-bit integer guard to >ensure once-initialization of static objects with block scopes. Code in gcc/libstdc++-v3/libsupc++/guard.cc uses a global mutex to protect multiple threads from racing, which, as described in that file, could potentially cause a deadlock that can be avoided if a condition variable is used. This, however, is unnecessary with mcfgthread. The mcfgthread library uses the once_flag itself as both the mutex and condition variable, eliminating the need of a global mutex and condition variable. Code using mcfgthread might look like this: [code] class foo { ... }; static ::_MCFCRT_OnceFlag flag; static alignas(foo) char obj[sizeof(foo)]; foo *get_obj(){ const auto construct_obj = []{ ::new(static_cast(obj)) foo(); }; const auto destruct_obj = []{ reinterpret_cast(obj)->~foo(); }; // Lock the once flag as if it were a mutex. const auto result = ::_MCFCRT_WaitForOnceFlagForever(&flag); // This never times out, so result can be either _MCFCRT_kOnceResultInitial or _MCFCRT_kOnceResultFinished. if(result == ::_MCFCRT_kOnceResultInitial){ try { // Construct the object in-place. construct_obj(); if(std::atexit(&destruct_obj) != 0){ // Assume we have run out of memory. destruct_obj(); throw std::bad_alloc(); } } catch(...){ // Unlock the once flag, allowing other threads to retry the initialization. // This works like pthread_cond_signal(). ::_MCFCRT_SignalOnceFlagAsAborted(&flag); throw; } // We are done here. Unlock the once flag and other threads will not be blocked any more. // This works like pthread_cond_broadcast(). _MCFCRT_SignalOnceFlagAsFinished(&flag); } return reinterpret_cast(obj); } [/code] Now here is my question: That '__cxxabiv1::__guard' thing seems built-in of GCC. Does it have anything to do with code generation? And where is it involved? -- Best regards, lh_mouse 2016-04-20
Re: SafeStack proposal in GCC
On Wed, 13 Apr 2016, Cristina Georgiana Opriceana wrote: > Hello, > > I bring to your attention SafeStack, part of a bigger research project > - CPI/CPS [1], which offers complete protection against stack-based > control flow hijacks. I am interested in developing SafeStack for GCC > and I would like to ask for your feedback on this proposal. I'm not expert on the relevant parts of GCC, but this seems like a useful feature and your outline design seems sane. -- Joseph S. Myers jos...@codesourcery.com
Re: SafeStack proposal in GCC
On 13/04/16 14:01, Cristina Georgiana Opriceana wrote: > I bring to your attention SafeStack, part of a bigger research project > - CPI/CPS [1], which offers complete protection against stack-based > control flow hijacks. i think it does not provide complete protection. it cannot instrument the c runtime or dsos and attacks can be retried on a forking server which has fixed memory layout, so there is still significant attack surface. (it would be nice if security experts made such claims much more carefully). > In GCC, we propose a design composed of an instrumentation module > (implemented as a GIMPLE pass) and a runtime library. ... > The runtime support will have to deal with unsafe stack allocation - a > hook in the pthread create/destroy functions to create per-thread > stack regions. This runtime support might be reused from the Clang > implementation. the SafeStack runtime in compiler-rt has various issues that should be clearly documented. it seems the runtime * aborts the process on allocation failure. * deallocates the unsafe stack using tsd dtors, but signal handlers may run between dtors and the actual thread exit.. without a mapped unsafe stack. * determines the main stack with broken heuristic (since the rlimit can change at runtime i don't think this is possible to do correctly in general). * interposes pthread_create but not c11 thrd_create so conforming c11 code will crash. (same for non-standard usage of raw clone.) * sigaltstack and swapcontext are broken too. i think the runtime issues are more likely to cause problems than the compiler parts: it has to be reliable and abi stable since safestack is advertised for production use. (i think gcc should raise the bar for runtime code quality higher than that, but there is precedent for much worse runtimes in gcc so this should not block the safestack porting work, however consider these issues when communicating about it to upstream or to potential users.)
Why does gcc generate const local array on stack?
Hi, I came across the following issue. int foo (int N) { const int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; return a[N]; } Compile with x86 O2 foo: .LFB0: .cfi_startproc movslq %edi, %rdi movl $0, -56(%rsp) movl $1, -52(%rsp) movl $2, -48(%rsp) movl $3, -44(%rsp) movl $4, -40(%rsp) movl $5, -36(%rsp) movl $6, -32(%rsp) movl $7, -28(%rsp) movl $8, -24(%rsp) movl $9, -20(%rsp) movl -56(%rsp,%rdi,4), %eax ret The array is placed on stack and GCC has to generate a sequence of instructions to initialize the array every time the function is called. On the contrary, LLVM moves the array to global data and doesn't need initialization within the function. If I add static to the array, GCC behaves the same as LLVM, just as expected. Is there some subtle C standard issue or some switch I didn't turned on? I understand if this function is recursive and pointer of the array is involved, GCC would have to maintain the array on stack and hence the initialization. But here the code is very simple. I don't understand the logic of generated code, or maybe missing optimization opportunity? Thanks, Bingfeng Mei
Re: SafeStack proposal in GCC
On Wed, Apr 20, 2016 at 4:54 PM, Szabolcs Nagy wrote: > On 13/04/16 14:01, Cristina Georgiana Opriceana wrote: >> I bring to your attention SafeStack, part of a bigger research project >> - CPI/CPS [1], which offers complete protection against stack-based >> control flow hijacks. > > i think it does not provide complete protection. > > it cannot instrument the c runtime or dsos and attacks > can be retried on a forking server which has fixed memory > layout, so there is still significant attack surface. > > (it would be nice if security experts made such claims > much more carefully). OK, the point is well taken, every actual implementation of such techniques is bound to have limitations like the ones you mention. The protection can only be complete in an academic sense: assuming the perfect implementation that follows the CPI formal model, has perfect safe region isolation, etc. In practice, we're just trying to make the attacker's job harder. > >> In GCC, we propose a design composed of an instrumentation module >> (implemented as a GIMPLE pass) and a runtime library. > ... >> The runtime support will have to deal with unsafe stack allocation - a >> hook in the pthread create/destroy functions to create per-thread >> stack regions. This runtime support might be reused from the Clang >> implementation. > > the SafeStack runtime in compiler-rt has various issues > that should be clearly documented. Thanks a lot for pointing it out, getting such feedback is one of the reasons we want to upstream this in the first place. The other reasons include getting more people to use and to improve the code by fixing such issues. > > it seems the runtime > > * aborts the process on allocation failure. > > * deallocates the unsafe stack using tsd dtors, but > signal handlers may run between dtors and the actual > thread exit.. without a mapped unsafe stack. I think the only correct way to handle this is to put the unsafe stack allocation/deallocation code into libc. We implemented it for FreeBSD libc in a way that imposes no overhead for apps that don't use safestack, perhaps something similar could be possible in glibc. We'd welcome any better suggestions on this! > > * determines the main stack with broken heuristic > (since the rlimit can change at runtime i don't think > this is possible to do correctly in general). > > * interposes pthread_create but not c11 thrd_create > so conforming c11 code will crash. (same for non-standard > usage of raw clone.) > > * sigaltstack and swapcontext are broken too. We have prototype that supports swapcontext that we're happy to release, but it clearly requires more work before being ready to merge upstream. > > i think the runtime issues are more likely to cause > problems than the compiler parts: it has to be reliable > and abi stable since safestack is advertised for > production use. > > (i think gcc should raise the bar for runtime code > quality higher than that, but there is precedent > for much worse runtimes in gcc so this should not > block the safestack porting work, however consider > these issues when communicating about it to upstream > or to potential users.) > - Vova
Re: Why does gcc generate const local array on stack?
I tend to say clang is wrong here. Quoting the standard: ISO/IEC WG14 Draft N1570 (Programming languages — C): [quote] 6.2.2 Linkages of identifiers 6 The following identifiers have no linkage: an identifier declared to be anything other than an object or a function; an identifier declared to be a function parameter; a block scope identifier for an object declared without the storage-class specifier extern. 6.2.4 Storage durations of objects 6 An object whose identifier is declared with no linkage and without the storage-class specifier static has automatic storage duration, as do some compound literals. ... 7 For such an object that does have a variable length array type, its lifetime extends from the declaration of the object until execution of the program leaves the scope of the declaration.35) If the scope is entered recursively, a new instance of the object is created each time. The initial value of the object is indeterminate. [/quote] Your identifier 'a' has no linkage. Your object designated by 'a' does not have a storage-class specifier. So it has automatic storage duration and 6.2.4/7 applies: 'If the scope is entered recursively, a new instance of the object is created each time.' Interesting enough, ISO C doesn't say whether distinct objects should have distinct addresses. It is worth noting that this is explicitly forbidden in ISO C++ because distinct complete objects shall have distinct addresses: ISO/IEC WG21 N4582 (Working Draft, Standard for Programming Language C++) : [quote] 1.9 Program execution [intro.execution] 7 An instance of each object with automatic storage duration (3.7.3) is associated with each entry into its block. Such an object exists and retains its last-stored value during the execution of the block and while the block is suspended (by a call of a function or receipt of a signal). 1.8 The C++ object model [intro.object] 6 Unless an object is a bit-field or a base class subobject of zero size, the address of that object is the address of the first byte it occupies. Two objects that are not bit-fields may have the same address if one is a subobject of the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they shall have distinct addresses.4 [/quote] -- Best regards, lh_mouse 2016-04-20 - 发件人:Bingfeng Mei 发送日期:2016-04-20 23:38 收件人:gcc 抄送: 主题:Why does gcc generate const local array on stack? Hi, I came across the following issue. int foo (int N) { const int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; return a[N]; } Compile with x86 O2 foo: .LFB0: .cfi_startproc movslq %edi, %rdi movl $0, -56(%rsp) movl $1, -52(%rsp) movl $2, -48(%rsp) movl $3, -44(%rsp) movl $4, -40(%rsp) movl $5, -36(%rsp) movl $6, -32(%rsp) movl $7, -28(%rsp) movl $8, -24(%rsp) movl $9, -20(%rsp) movl -56(%rsp,%rdi,4), %eax ret The array is placed on stack and GCC has to generate a sequence of instructions to initialize the array every time the function is called. On the contrary, LLVM moves the array to global data and doesn't need initialization within the function. If I add static to the array, GCC behaves the same as LLVM, just as expected. Is there some subtle C standard issue or some switch I didn't turned on? I understand if this function is recursive and pointer of the array is involved, GCC would have to maintain the array on stack and hence the initialization. But here the code is very simple. I don't understand the logic of generated code, or maybe missing optimization opportunity? Thanks, Bingfeng Mei
Re: Preventing preemption of 'protected' symbols in GNU ld 2.26 [aka should we revert the fix for 65248]
H.J. Lu wrote: On Tue, Apr 19, 2016 at 7:06 AM, Michael Matz wrote: Hi, On Tue, 19 Apr 2016, Richard Biener wrote: So with all this it sounds that current protected visibility is just broken and we should forgo with it, making it equal to default visibility? Like how? You mean in GCC regarding protected as default visibility? No, that's just throwing out the baby with the water. We should make protected do what it was intended to do and accept that not all invariants that are true for default visible symbols are also true for protected symbols, possibly by ... At least I couldn't decipher a solution that solves all of the issues with protected visibility apart from trying to error at link-time (or runtime?) for the cases that are tricky (impossible?) to solve. Protected visibility is a useful feature. But as it stands today, it is pretty much useless on x86 as seen in ld and ld.so. We have known this defect for a long time, almost from day 1. To make it truly useful, we need to clearly spell out how and when it can be used. We should enforce its limitation in compiler, ld and ld.so so that there is no surprise, either for correctness or performance, at run-time. my prefference would be if you (re)add it: do so such that there is no portability issue with next or previous gcc version (or other cc if possible), and that it be left as optional with a quick note that it is, and insure both on and off both build w/o fail in doing so. picky? thank you, have a nice day!
Re: Why does gcc generate const local array on stack?
On 20 April 2016 at 18:31, lh_mouse wrote: > I tend to say clang is wrong here. If you can't detect the difference then it is a valid transformation. > Your identifier 'a' has no linkage. Your object designated by 'a' does not > have a storage-class specifier. > So it has automatic storage duration and 6.2.4/7 applies: 'If the scope is > entered recursively, a new instance of the object is created each time.' How do you tell the difference between a const array that is recreated each time and one that isn't? > Interesting enough, ISO C doesn't say whether distinct objects should have > distinct addresses. > It is worth noting that this is explicitly forbidden in ISO C++ because > distinct complete objects shall have distinct addresses: If the object's address doesn't escape from the function then I can't think of a way to tell the difference.
gcc-4.9-20160420 is now available
Snapshot gcc-4.9-20160420 is now available on ftp://gcc.gnu.org/pub/gcc/snapshots/4.9-20160420/ and on various mirrors, see http://gcc.gnu.org/mirrors.html for details. This snapshot has been generated from the GCC 4.9 SVN branch with the following options: svn://gcc.gnu.org/svn/gcc/branches/gcc-4_9-branch revision 235297 You'll find: gcc-4.9-20160420.tar.bz2 Complete GCC MD5=8126fccd044733719231dfd5ddeaf985 SHA1=4da5f7fe73a10c784b2850d87b876f5f2011d262 Diffs from 4.9-20160413 are available in the diffs/ subdirectory. When a particular snapshot is ready for public consumption the LATEST-4.9 link is updated and a message is sent to the gcc list. Please do not use a snapshot before it has been announced that way.
Re: Does gcc cilk plus support include offloading to graphics hardware?
Thank you Ilya, I now understand that gcc has full support for only the _language_ extensions of cilk plus. Perhaps the release notes might be updated to note this. Intel market #pragma offload(gfx) as a cilk plus feature. For example slides 12-15 here: https://meetingcpp.com/tl_files/mcpp/2015/talks/Intel%20Graphics%20Technology%20for%20general%20purpose%20computing.pdf Thanks again. On 20 April 2016 at 19:31, Ilya Verbin wrote: > 2016-04-20 4:01 GMT+03:00 Hal Ashburner : >> Release notes say: >> "Full support for Cilk Plus has been added to the GCC compiler. Cilk >> Plus is an extension to the C and C++ languages to support data and >> task parallelism." >> >> gcc-5.2 (centos-7, devtoolset-4) says: >> >> g++ -std=c++14 -Wall -O3 -march=native -fcilkplus vec_add.cpp -o vec_add >> vec_add.cpp:6:0: warning: ignoring #pragma offload target [-Wunknown-pragmas] >> #pragma offload target(gfx) pin(out, in1, in2 : length(n)) > > "#pragma offload" is not a part of Cilk Plus [1], and it is not > supported by GCC. > However, GCC supports similar "#pragma omp target" for offloading to > Intel Xeon Phi and other GPUs (Intel Graphics is not supported). > > [1] > www.cilkplus.org/sites/default/files/open_specifications/Intel_Cilk_plus_lang_spec_1.2.htm > > -- Ilya
Looking for some help with GCC 6 and bad code generation
I would like someone to look at this and tell me this is an already fixed bug. Or that recent GCC patches may have fixed it. :-) Or it would also be great to get some advice on building a reproducer without needing to include many megabytes of proprietary code plus Boost. I've been using Fedora 24 Alpha and of course I've somehow managed to write some C++ code even more confusing for GCC than Firefox. Heh. The problem is a crash when std::string tries to free memory from a temporary std::string that was bound to a const reference. And it only crashes when I pass -O2 or -O3 and the -fprofile-generate flags. $ gcc -v Using built-in specs. COLLECT_GCC=/usr/bin/gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/6.0.0/lto-wrapper Target: x86_64-redhat-linux Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --disable-libgcj --with-isl --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux Thread model: posix gcc version 6.0.0 20160406 (Red Hat 6.0.0-0.20) (GCC) I collected my findings so far into the attachment. Thanks for reading! -- Knowledge is Power -- Power Corrupts Study Hard -- Be Evil I am working at reducing this to a test case but it is slow going. It seems quite sensitive to how much exists in the headers and templates. The cxxtest code snippit that I am showing in the assembly code below is: static const char* udbname = "urldb-import"; static const char* tname = "tmpmapfile"; class TestURLDatabase_1_Delete : public CxxTest::TestSuite { public: void setUp() { remove(udbname); } void testDelete1() { eSoft::URLDatabaseReaderWriter_1 dbw(udbname); dbw.insert_compress_word("esoft", 1); dbw.insert_url("esoft.com", 0x0AAAU); TS_ASSERT_EQUALS( dbw.lookup("esoft.com"), 0x0AAAU ); dbw.remove_url("esoft.com"); TS_ASSERT_EQUALS( dbw.lookup("esoft.com"), 0U ); } [... rest of tests snipped ...] The constructor call looks like: URLDatabaseReaderWriter_1(const std::string &fname, const std::string &id = URLDatabaseReader_1::identifier()) So it ends up generating two temporary std::strings. Assembly code showing the problem I am having with GCC 6.0 and the C++11 ABI std::string. For some reason, in this function, a temporary std::string allocated for a conversion from a const char* to const std::string& is being deleted twice. Once right after the constructor function that is using the temporary string, and again at function exit, probably to cover the case if the constructor throws. The second delete thinks it is using allocated storage instead of local. These are sections of objdump -dCr output. Without -fprofile-generate. Note that at 0x99 %rbx is reloaded from %rax (the result of identifier() I think) and it is then used at 0xb3 to determine if std::string is using local storage or allocated storage. This seems to work and both temporary strings are properly destroyed. = Disassembly of section .text._ZN24TestURLDatabase_1_Delete11testDelete1Ev: : 0: 41 54 push %r12 2: 55 push %rbp 3: 53 push %rbx 4: 48 81 ec 30 02 00 00sub$0x230,%rsp b: 64 48 8b 04 25 28 00mov%fs:0x28,%rax 12: 00 00 14: 48 89 84 24 28 02 00mov%rax,0x228(%rsp) 1b: 00 1c: 31 c0 xor%eax,%eax 1e: e8 00 00 00 00 callq 23 1f: R_X86_64_PLT32 eSoft::URLDatabaseReader_1::identifier[abi:cxx11]()-0x4 23: 49 89 c4mov%rax,%r12 26: 48 89 e3mov%rsp,%rbx 29: 48 8d 44 24 10 lea0x10(%rsp),%rax 2e: 48 89 04 24 mov%rax,(%rsp) 32: 48 8d 15 00 00 00 00lea0x0(%rip),%rdx# 39 35: R_X86_64_PC32 .LC0+0x8 39: 48 8d 35 00 00 00 00lea0x0(%rip),%rsi# 40 3c: R_X86_64_PC32 .LC0-0x4 40: 48 89 e7mov%rsp,%rdi 43: e8 00 00 00 00 callq 48 44: R_X86_64_PC32 .text._ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPcEEvT_S7_St20forward_iterator_tag.isra.57-0x4 48: 48 8d 6c 24 20 lea0x20(%rsp),%rbp 4d: 4c 89 e2
Re: Looking for some help with GCC 6 and bad code generation
On Thu, Apr 21, 2016 at 9:11 AM, Zan Lynx wrote: > I would like someone to look at this and tell me this is an already > fixed bug. Or that recent GCC patches may have fixed it. :-) > > Or it would also be great to get some advice on building a reproducer > without needing to include many megabytes of proprietary code plus Boost. > > I've been using Fedora 24 Alpha and of course I've somehow managed to > write some C++ code even more confusing for GCC than Firefox. Heh. > > The problem is a crash when std::string tries to free memory from a > temporary std::string that was bound to a const reference. > > And it only crashes when I pass -O2 or -O3 and the -fprofile-generate flags. What is the return type of URLDatabaseReader_1::identifier() ? Also does -fsanitize=undefined say anything about your code? Thanks, Andrew > > $ gcc -v > Using built-in specs. > COLLECT_GCC=/usr/bin/gcc > COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/6.0.0/lto-wrapper > Target: x86_64-redhat-linux > Configured with: ../configure --enable-bootstrap > --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr > --mandir=/usr/share/man --infodir=/usr/share/info > --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared > --enable-threads=posix --enable-checking=release --enable-multilib > --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions > --enable-gnu-unique-object --enable-linker-build-id > --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array > --disable-libgcj --with-isl --enable-libmpx > --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 > --build=x86_64-redhat-linux > Thread model: posix > gcc version 6.0.0 20160406 (Red Hat 6.0.0-0.20) (GCC) > > I collected my findings so far into the attachment. > > Thanks for reading! > > -- > Knowledge is Power -- Power Corrupts > Study Hard -- Be Evil
Re: Looking for some help with GCC 6 and bad code generation
On 4/20/2016 7:18 PM, Andrew Pinski wrote: On Thu, Apr 21, 2016 at 9:11 AM, Zan Lynx wrote: I would like someone to look at this and tell me this is an already fixed bug. Or that recent GCC patches may have fixed it. :-) Or it would also be great to get some advice on building a reproducer without needing to include many megabytes of proprietary code plus Boost. I've been using Fedora 24 Alpha and of course I've somehow managed to write some C++ code even more confusing for GCC than Firefox. Heh. The problem is a crash when std::string tries to free memory from a temporary std::string that was bound to a const reference. And it only crashes when I pass -O2 or -O3 and the -fprofile-generate flags. What is the return type of URLDatabaseReader_1::identifier() ? Also does -fsanitize=undefined say anything about your code? Thanks, Andrew const std::string& URLDatabaseReader_1::identifier() { static const std::string id("esct"); return id; } And I'll give sanitize a try. -- Knowledge is Power -- Power Corrupts Study Hard -- Be Evil
Re: Re: Why does gcc generate const local array on stack?
See this example: http://coliru.stacked-crooked.com/a/048b4aa5046da11b In this example the function is called recursively. During each call a pointer to that local areay is appended to a static array of pointers. Should a new instance of that local array of const int be created every time, abort() will never be called. Since calling a library function is observable behavior, clang's optimization has effectively changed that program's behavior. Hence I think it is wrong. [code] #include static const int *ptrs[2]; static unsigned recur; void foo(){ const int a[] = {0,1,2,3,4,5,6,7,8,9}; ptrs[recur] = a; if(recur == 0){ ++recur; foo(); } if(ptrs[0] == ptrs[1]){ abort(); } } int main(){ foo(); } [/code] -- Best regards, lh_mouse 2016-04-21 - 发件人:Jonathan Wakely 发送日期:2016-04-21 01:51 收件人:lh_mouse 抄送:Bingfeng Mei,gcc 主题:Re: Why does gcc generate const local array on stack? On 20 April 2016 at 18:31, lh_mouse wrote: > I tend to say clang is wrong here. If you can't detect the difference then it is a valid transformation. > Your identifier 'a' has no linkage. Your object designated by 'a' does not > have a storage-class specifier. > So it has automatic storage duration and 6.2.4/7 applies: 'If the scope is > entered recursively, a new instance of the object is created each time.' How do you tell the difference between a const array that is recreated each time and one that isn't? > Interesting enough, ISO C doesn't say whether distinct objects should have > distinct addresses. > It is worth noting that this is explicitly forbidden in ISO C++ because > distinct complete objects shall have distinct addresses: If the object's address doesn't escape from the function then I can't think of a way to tell the difference.
Re: Does gcc cilk plus support include offloading to graphics hardware?
Another cilk plus question: Is op_ostream also considered to be outside of cilk plus? https://www.cilkplus.org/docs/doxygen/include-dir/group___reducers_ostream.html I am trying to compile the basic "Cilk Plus Tutorial Sources" code as supplied at http://cilkplus.org/download reducer-ostream-demo.cpp, reducer-string-demo.cpp and reducer-wstring-demo.cpp I am unable to get to compile. Thank you kindly Makefile: FLAGS=-std=c++14 -Wall -O3 -march=native CILK_FLAGS=-fcilkplus SOURCES=$(shell ls *.cpp) BINS=$(SOURCES:.cpp=) all:$(BINS) %:%.cpp g++ $(FLAGS) $(CILK_FLAGS) $< -o $@