From patchwork Thu Aug 28 18:57:40 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thorsten Wilmer X-Patchwork-Id: 384006 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id A74D8140129 for ; Fri, 29 Aug 2014 04:57:56 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:date:message-id:subject:from:to:content-type; q= dns; s=default; b=VtNOdNvOw/ceEWzcHQwlsB5SssrbABpkwqNRsq6QXfbWOU wb5O/P6il6pXESoloKA+KFtBzhYVsadRUXrqUQB3VyNzHvkZGFH0GEascbxixgst +7kQgFEKgNnxdvY6sp1YgcyoST+gwo87hEwgfyp5luMN3URzBLWYplMZIIZ3c= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:date:message-id:subject:from:to:content-type; s= default; bh=TMOvIeOZKJw3jzKsygtd26FnXBA=; b=SOyz/hkS7WU5zu5GJX/S y6wVFsL3/4IeUt3XizbLB1cQ7doLl4oxWFgDga+Ne/8fMLd11NoNxL8pmJB22SMQ xNTiRtJhGrxU5Vde/Jje8itT1q2igLkFDFyRYkmvad+6PN08eHWlMSuLyMfpHxWT 2Eim7Q/J5Rn0I+7g/eJhP8c= Received: (qmail 28090 invoked by alias); 28 Aug 2014 18:57:46 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 28077 invoked by uid 89); 28 Aug 2014 18:57:46 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.6 required=5.0 tests=AWL, BAYES_05, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qa0-f43.google.com Received: from mail-qa0-f43.google.com (HELO mail-qa0-f43.google.com) (209.85.216.43) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Thu, 28 Aug 2014 18:57:43 +0000 Received: by mail-qa0-f43.google.com with SMTP id cm18so1156626qab.30 for ; Thu, 28 Aug 2014 11:57:41 -0700 (PDT) MIME-Version: 1.0 X-Received: by 10.229.62.129 with SMTP id x1mr9807236qch.16.1409252260615; Thu, 28 Aug 2014 11:57:40 -0700 (PDT) Received: by 10.140.100.225 with HTTP; Thu, 28 Aug 2014 11:57:40 -0700 (PDT) Date: Fri, 29 Aug 2014 00:27:40 +0530 Message-ID: Subject: [Patch] fix C++11 thread support for win32 From: Thorsten Wilmer To: gcc-patches@gcc.gnu.org X-IsSubscribed: yes Hi, I stumbled over the problem, that on win32 c++11's Thread support is broken. I found a patch from Tomohiro Kashiwada, who did a great job. Only he didn't pursue to have it integrated since more than two years. I have applied his patch and fixed some compiler warnings and obvious cast/pointer problems, where the win32 api and the pthread api don't match. Also I verified that libstdc++'s configure script detects that thread support can be activated. Please consider the patch below for inclusion. If you see any blocking points, let me know, I'll try to address them as I would like to use my C++11 programs on win32 without hassle and a fresh compiler. The patch is against current git mirror. It compiles without error and the compiled source code survived some example programs for threads and my own complex program, which is using threads, mutex and condition variables. I compiled the complete tool chain from source, this is my gcc configuration: ../gcc/configure --prefix=/usr/local/gcc/git-mingw --with-gmp=/usr/local/gcc/git-mingw --target=x86_64-w64-mingw32 --enable-targets=all --disable-multilib Here the random output of the example program: Z:\>a.exe Thread Thread 2 executing 1 executing Thread Thread 2 executing 1 executing Thread 2 executing Thread 1 executing Thread 2 executing Thread 1 executing Thread Thread 2 executing 1 executing Final value of n is 5 Kind Regards, Thorsten Wilmer From 9591d02da5e6131e4a79259ed952d52dcecb86ac Mon Sep 17 00:00:00 2001 From: Thorsten Wilmer Date: Thu, 28 Aug 2014 23:37:41 +0530 Subject: [PATCH] fix C++11 thread support for win32 Based on Implemented Condition Variable by Tomohiro Kashiwada . Fixed compile warnings and added some error handling. --- libgcc/config/i386/gthr-win32.c | 290 ++++++++++++++++++++++++++++++++++++++++ libgcc/config/i386/gthr-win32.h | 220 ++++++++++++++++++++++++++++-- 2 files changed, 502 insertions(+), 8 deletions(-) #endif /* Windows32 threads specific definitions. The windows32 threading model @@ -65,6 +72,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see needs to use Structured Exception Handling on Windows32. */ #define __GTHREADS 1 +#define __GTHREADS_CXX0X 1 +#define __GTHREAD_HAS_COND 1 #include #ifdef __MINGW32__ @@ -120,7 +129,7 @@ __gthread_objc_thread_detach (void (*func)(void *arg), void *arg) DWORD thread_id = 0; HANDLE win32_handle; - if (!(win32_handle = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) func, + if (!(win32_handle = CreateThread (0, 0, (LPTHREAD_START_ROUTINE) func, arg, 0, &thread_id))) thread_id = 0; @@ -240,7 +249,7 @@ __gthread_objc_thread_get_data (void) int __gthread_objc_mutex_allocate (objc_mutex_t mutex) { - if ((mutex->backend = (void *) CreateMutex (NULL, 0, NULL)) == NULL) + if ((mutex->backend = (void *) CreateMutex (0, 0, 0)) == 0) return -1; else return 0; @@ -358,6 +367,26 @@ typedef struct { void *sema; } __gthread_recursive_mutex_t; +typedef struct { + long counter; + void *pcs; + void *sema; +} __gthread_cond_t; + + +typedef struct { + void *handle; + unsigned id; + void *(*func) (void *); + void *arg; +} __gthread_solid_t; +typedef __gthread_solid_t *__gthread_t; + +typedef struct { + time_t tv_sec; + long tv_nsec; +} __gthread_time_t; + #define __GTHREAD_ONCE_INIT {0, -1} #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function #define __GTHREAD_MUTEX_INIT_DEFAULT {-1, 0} @@ -365,6 +394,8 @@ typedef struct { __gthread_recursive_mutex_init_function #define __GTHREAD_RECURSIVE_MUTEX_INIT_DEFAULT {-1, 0, 0, 0} +#define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function + #if defined (_WIN32) && !defined(__CYGWIN__) #define MINGW32_SUPPORTS_MT_EH 1 /* Mingw runtime >= v0.3 provides a magic variable that is set to nonzero @@ -431,6 +462,31 @@ extern int __gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *); extern void __gthr_win32_mutex_destroy (__gthread_mutex_t *); extern int __gthr_win32_recursive_mutex_destroy (__gthread_recursive_mutex_t *); +extern int __gthr_win32_cond_init (__gthread_cond_t *, void *); +extern int __gthr_win32_cond_destroy (__gthread_cond_t *); +extern int __gthr_win32_cond_broadcast (__gthread_cond_t *); +extern int __gthr_win32_cond_wait (__gthread_cond_t *, __gthread_mutex_t *); +extern int __gthr_win32_cond_wait_recursive (__gthread_cond_t *, + __gthread_recursive_mutex_t *); +extern int __gthr_win32_create (__gthread_t *, void *(*func) (void *), void *); +extern int __gthr_win32_join (__gthread_t, void **); +extern int __gthr_win32_detach (__gthread_t); +extern int __gthr_win32_equal (__gthread_t, __gthread_t); +extern __gthread_t __gthr_win32_self (void); +extern int __gthr_win32_yield (void); +extern int __gthr_win32_mutex_timedlock (__gthread_mutex_t *, + const __gthread_time_t *); +extern int + __gthr_win32_recursive_mutex_timedlock (__gthread_recursive_mutex_t *, + const __gthread_time_t *); +extern int __gthr_win32_cond_signal (__gthread_cond_t *); +extern int __gthr_win32_cond_timedwait (__gthread_cond_t *, + __gthread_mutex_t *, + const __gthread_time_t *); +extern int +__gthr_win32_cond_timedwait_recursive (__gthread_cond_t *, + __gthread_recursive_mutex_t *, + const __gthread_time_t *); static inline int __gthread_once (__gthread_once_t *__once, void (*__func) (void)) @@ -543,6 +599,154 @@ __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex) return __gthr_win32_recursive_mutex_destroy (__mutex); } +static inline int +__gthread_cond_init_function (__gthread_cond_t *__cond) +{ + return __gthr_win32_cond_init (__cond, 0); +} + +static inline int +__gthread_cond_init (__gthread_cond_t *__cond, void *__attr) +{ + return __gthr_win32_cond_init (__cond, __attr); +} + +static inline int +__gthread_cond_destroy (__gthread_cond_t *__cond) +{ + return __gthr_win32_cond_destroy (__cond); +} + +static inline int +__gthread_cond_broadcast (__gthread_cond_t *__cond) +{ + if (__gthread_active_p ()) + return __gthr_win32_cond_broadcast (__cond); + else + return 0; +} + +static inline int +__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthr_win32_cond_wait (__cond, __mutex); + else + return 0; +} + +static inline int +__gthread_cond_wait_recursive (__gthread_cond_t *__cond, + __gthread_recursive_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthr_win32_cond_wait_recursive (__cond, __mutex); + else + return 0; +} + +static inline int +__gthread_create (__gthread_t *__pthr, void *(*__func) (void *), void *__args) +{ + if (__gthread_active_p ()) + return __gthr_win32_create (__pthr, __func, __args); + else + return 0; +} + +static inline int +__gthread_join (__gthread_t __thr, void **__value_ptr) +{ + if (__gthread_active_p ()) + return __gthr_win32_join (__thr, __value_ptr); + else + return 0; +} + +static inline int +__gthread_detach (__gthread_t __thr) +{ + if (__gthread_active_p ()) + return __gthr_win32_detach (__thr); + else + return 0; +} + +static inline int +__gthread_equal (__gthread_t __t1, __gthread_t __t2) +{ + if (__gthread_active_p ()) + return __gthr_win32_equal (__t1, __t2); + else + return 0; +} + +static inline __gthread_t +__gthread_self (void) +{ + return __gthr_win32_self (); +} + +static inline int +__gthread_yield (void) +{ + if (__gthread_active_p ()) + return __gthr_win32_yield (); + else + return 0; +} + +static inline int +__gthread_mutex_timedlock (__gthread_mutex_t *__mutex, + const __gthread_time_t *__abs_timeout) +{ + if (__gthread_active_p ()) + return __gthr_win32_mutex_timedlock (__mutex, __abs_timeout); + else + return 0; +} + +static inline int +__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex, + const __gthread_time_t *__abs_timeout) +{ + if (__gthread_active_p ()) + return __gthr_win32_recursive_mutex_timedlock (__mutex, __abs_timeout); + else + return 0; +} + +static inline int +__gthread_cond_signal (__gthread_cond_t *__cond) +{ + if (__gthread_active_p ()) + return __gthr_win32_cond_signal (__cond); + else + return 0; +} + +static inline int +__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex, + const __gthread_time_t *__abs_timeout) +{ + if (__gthread_active_p ()) + return __gthr_win32_cond_timedwait (__cond, __mutex, __abs_timeout); + else + return 0; +} + +static inline int +__gthread_cond_timedwait_recursive (__gthread_cond_t *__cond, + __gthread_recursive_mutex_t *__mutex, + const __gthread_time_t *__abs_timeout) +{ + if (__gthread_active_p ()) + return __gthr_win32_cond_timedwait_recursive (__cond, __mutex, + __abs_timeout); + else + return 0; +} + #else /* ! __GTHREAD_HIDE_WIN32API */ #include @@ -553,7 +757,7 @@ __gthread_once (__gthread_once_t *__once, void (*__func) (void)) { if (! __gthread_active_p ()) return -1; - else if (__once == NULL || __func == NULL) + else if (__once == 0 || __func == 0) return EINVAL; if (! __once->done) @@ -635,7 +839,7 @@ static inline void __gthread_mutex_init_function (__gthread_mutex_t *__mutex) { __mutex->counter = -1; - __mutex->sema = CreateSemaphoreW (NULL, 0, 65535, NULL); + __mutex->sema = CreateSemaphoreW (0, 0, 65535, 0); } static inline void @@ -686,7 +890,7 @@ __gthread_mutex_unlock (__gthread_mutex_t *__mutex) if (__gthread_active_p ()) { if (InterlockedDecrement (&__mutex->counter) >= 0) - return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1; + return ReleaseSemaphore (__mutex->sema, 1, 0) ? 0 : 1; } return 0; } @@ -697,7 +901,7 @@ __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) __mutex->counter = -1; __mutex->depth = 0; __mutex->owner = 0; - __mutex->sema = CreateSemaphoreW (NULL, 0, 65535, NULL); + __mutex->sema = CreateSemaphore (0, 0, 65535, 0); } static inline int @@ -762,7 +966,7 @@ __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) __mutex->owner = 0; if (InterlockedDecrement (&__mutex->counter) >= 0) - return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1; + return ReleaseSemaphore (__mutex->sema, 1, 0) ? 0 : 1; } } return 0; diff --git a/libgcc/config/i386/gthr-win32.c b/libgcc/config/i386/gthr-win32.c index eec16b3..10769a7 100644 --- a/libgcc/config/i386/gthr-win32.c +++ b/libgcc/config/i386/gthr-win32.c @@ -5,6 +5,8 @@ Contributed by Mumit Khan . Modified and moved to separate file by Danny Smith . + Implemented Condition Variable by Tomohiro Kashiwada + . This file is part of GCC. @@ -28,6 +30,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ #include +#include #ifndef __GTHREAD_HIDE_WIN32API # define __GTHREAD_HIDE_WIN32API 1 #endif @@ -259,9 +262,296 @@ __gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) return 0; } + int __gthr_win32_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex) { CloseHandle ((HANDLE) mutex->sema); return 0; } + + +static DWORD +gthread_calc_time_offset (const __gthread_time_t *abs_time) +{ + FILETIME ft; + LONGLONG ll; + LONGLONG ret; + GetSystemTimeAsFileTime (&ft); + ll = ((LONGLONG)ft.dwHighDateTime << 32) + ft.dwLowDateTime; + ret = (((LONGLONG)abs_time->tv_sec * 10000000 + abs_time->tv_nsec / 100) + - (ll - 116444736000000000)) / 10000; + if (ret < 0) + return 0; + if (ret > 0x7FFFFFFF) + return 0x7FFFFFFF; + return ret; +} + +int +__gthr_win32_cond_init (__gthread_cond_t *cond, + void *attr __attribute__((unused))) +{ + cond->counter = -1; + cond->pcs = malloc (sizeof (CRITICAL_SECTION)); + InitializeCriticalSection ((LPCRITICAL_SECTION)cond->pcs); + cond->sema = CreateSemaphore (NULL, 0, 65535, NULL); + return 0; +} + +int +__gthr_win32_cond_destroy (__gthread_cond_t *cond) +{ + __gthread_cond_broadcast (cond); + free (cond->pcs); + CloseHandle ((HANDLE)cond->sema); + return 0; +} + +int +__gthr_win32_cond_broadcast (__gthread_cond_t *cond) +{ + EnterCriticalSection (cond->pcs); + if (cond->counter >= 0) + ReleaseSemaphore (cond->sema, cond->counter+1, NULL); + cond->counter = -1; + LeaveCriticalSection (cond->pcs); + return 0; +} + +static int +cond_wait_impl (__gthread_cond_t *cond, + __gthread_mutex_t *mutex, DWORD timeout) +{ + EnterCriticalSection (cond->pcs); + ++cond->counter; + LeaveCriticalSection (cond->pcs); + if (SignalObjectAndWait (mutex->sema, cond->sema, timeout, FALSE) + != WAIT_OBJECT_0) + { + EnterCriticalSection (cond->pcs); + --cond->counter; + LeaveCriticalSection (cond->pcs); + } + WaitForSingleObject (mutex->sema, INFINITE); + return 0; +} + +static int +cond_wait_recursive_impl (__gthread_cond_t *cond, + __gthread_recursive_mutex_t *mutex, DWORD timeout) +{ + EnterCriticalSection (cond->pcs); + ++cond->counter; + LeaveCriticalSection (cond->pcs); + if (SignalObjectAndWait (mutex->sema, cond->sema, timeout, FALSE) + != WAIT_OBJECT_0) + { + EnterCriticalSection (cond->pcs); + --cond->counter; + LeaveCriticalSection (cond->pcs); + } + WaitForSingleObject (mutex->sema, INFINITE); + return 0; +} + +int +__gthr_win32_cond_wait (__gthread_cond_t *cond, __gthread_mutex_t *mutex) +{ + return cond_wait_impl (cond, mutex, INFINITE); +} + +int +__gthr_win32_cond_wait_recursive (__gthread_cond_t *cond, + __gthread_recursive_mutex_t *mutex) +{ + return cond_wait_recursive_impl (cond, mutex, INFINITE); +} + +static unsigned +get_thread_id (__gthread_t thr) +{ + if (thr) + return thr->id; + return GetCurrentThreadId (); +} + +static DWORD gthr_gthread_t_get_slot (void) +{ + static DWORD gthread_slot = 0xFFFFFFFF; + if (gthread_slot == 0xFFFFFFFF) + { + DWORD s = TlsAlloc (); + if ((DWORD) __GTHR_W32_InterlockedCompareExchange((long int*)(>hread_slot), s, 0xFFFFFFFF) + != 0xFFFFFFFFu) + { + TlsFree (s); + return gthread_slot; + } + else + { + __gthread_t thr = (__gthread_t)malloc (sizeof (__gthread_solid_t)); + thr->func = NULL; + thr->arg = NULL; + thr->id = GetCurrentThreadId (); + DuplicateHandle(GetCurrentProcess (), GetCurrentThread (), + GetCurrentProcess (), (HANDLE *)&thr->id, + 0, FALSE, DUPLICATE_SAME_ACCESS); + TlsSetValue(gthread_slot, thr); + } + } + return gthread_slot; +} + +static unsigned __stdcall +gthr_entry_stub (void *arg) +{ + __gthread_t p = (__gthread_t)arg; + TlsSetValue (gthr_gthread_t_get_slot (), arg); + /* the return code of the thread function is ignored as we have here anyway only + a unsigned which is not enough to pass a full pointer. + */ + void *ret=(*p->func) (p->arg); + if(ret!=0) + { + DWORD result=*(DWORD*)(ret); + ExitThread(result); + } + else + { + ExitThread(0); + } + + return 0 ; +} + + +int +__gthr_win32_create (__gthread_t *thrp, void *(*func) (void *), void *arg) +{ + gthr_gthread_t_get_slot (); + *thrp = (__gthread_t)malloc (sizeof (__gthread_solid_t)); + (*thrp)->func = func; + (*thrp)->arg = arg; + (*thrp)->handle = (void *)_beginthreadex (NULL, 0, >hr_entry_stub, *thrp, + 0, &(*thrp)->id); + if((*thrp)->handle == 0) + { + return -1; + } + + return 0; +} + +int +__gthr_win32_join (__gthread_t thr, void **pv) +{ + WaitForSingleObject ((HANDLE)thr->handle, INFINITE); + + if (pv) + { + LPDWORD r; + r=(LPDWORD)*pv; + GetExitCodeThread ((HANDLE)thr->handle, r); + } + __gthr_win32_detach (thr); + return 0; +} + +int __gthr_win32_detach (__gthread_t thr) +{ + CloseHandle ((HANDLE)thr->handle); + free (thr); + return 0; +} + +int __gthr_win32_equal (__gthread_t t1, __gthread_t t2) +{ + return get_thread_id (t1) == get_thread_id (t2); +} + +__gthread_t +__gthr_win32_self (void) +{ + return (__gthread_t)TlsGetValue (gthr_gthread_t_get_slot ()); +} + +int +__gthr_win32_yield (void) +{ + Sleep(0); + return 0; +} + +int +__gthr_win32_mutex_timedlock (__gthread_mutex_t *mutex, + const __gthread_time_t *abs_timeout) +{ + if (InterlockedIncrement (&mutex->counter) == 0 || + WaitForSingleObject (mutex->sema, gthread_calc_time_offset (abs_timeout)) + == WAIT_OBJECT_0) + return 0; + else + { + InterlockedDecrement (&mutex->counter); + return 0; + } +} + +int +__gthr_win32_recursive_mutex_timedlock (__gthread_recursive_mutex_t *mutex, + const __gthread_time_t *abs_timeout) +{ + DWORD me = GetCurrentThreadId (); + if (InterlockedIncrement (&mutex->counter) == 0) + { + mutex->depth = 1; + mutex->owner = me; + } + else if (mutex->owner == me) + { + InterlockedDecrement (&mutex->counter); + ++(mutex->depth); + } + else if (WaitForSingleObject (mutex->sema, + gthread_calc_time_offset (abs_timeout)) + == WAIT_OBJECT_0) + { + mutex->depth = 1; + mutex->owner = me; + } + else + { + InterlockedDecrement (&mutex->counter); + } + return 0; +} + +int +__gthr_win32_cond_signal (__gthread_cond_t *cond) +{ + EnterCriticalSection (cond->pcs); + if (cond->counter >= 0) + { + --cond->counter; + ReleaseSemaphore (cond->sema, 1, NULL); + } + LeaveCriticalSection (cond->pcs); + return 0; +} + +int +__gthr_win32_cond_timedwait (__gthread_cond_t *cond, __gthread_mutex_t *mutex, + const __gthread_time_t *abs_timeout) +{ + return cond_wait_impl (cond, mutex, gthread_calc_time_offset (abs_timeout)); +} + +int +__gthr_win32_cond_timedwait_recursive (__gthread_cond_t *cond, + __gthread_recursive_mutex_t *mutex, + const __gthread_time_t *abs_timeout) +{ + return cond_wait_recursive_impl (cond, mutex, + gthread_calc_time_offset (abs_timeout)); +} diff --git a/libgcc/config/i386/gthr-win32.h b/libgcc/config/i386/gthr-win32.h index c295fd5..af1f7cc 100644 --- a/libgcc/config/i386/gthr-win32.h +++ b/libgcc/config/i386/gthr-win32.h @@ -3,6 +3,8 @@ /* Copyright (C) 1999-2014 Free Software Foundation, Inc. Contributed by Mumit Khan . + Implemented Condition Variable by Tomohiro Kashiwada + . This file is part of GCC. @@ -29,8 +31,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define GCC_GTHR_WIN32_H /* Make sure CONST_CAST2 (origin in system.h) is declared. */ +#undef CONST_CAST2 #ifndef CONST_CAST2 -#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq) +#ifdef __cplusplus +#define CONST_CAST2(TOTYPE,FROMTYPE,X) (const_cast (X)) +#else +#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nqtwi;})(X))._nqtwi) +#endif