[cfe-dev] [PATCH] Libc++ Windows fixes

Ruben Van Boxem vanboxem.ruben at gmail.com
Sun Nov 27 06:28:40 PST 2011


Hi,

I've been cracking at it again, and came up with the attached patch to
let libc++ play nice with MSVC (or is it the other way around?).

I created a new __config macro: _LIBCPP_HAS_BROKEN_DECLTYPE, which is
defined for MSVC, and disables any functionality dependent on the
functionality broken in MSVC 10 (and probably 11). This is all the
__is_constructible stuff, and unfortunately this leads to other places
this macro pops up.

The good news: I've gotten through <type_traits>, adding the _MSC_VER
checks alongside the already existing Clang and GCC checks. Perhaps a
better way to handle this would be two new config macros:
_LIBCPP_HAS_NOTHROW_INTRINSICS and _LIBCPP_HAS_TRIVIAL_INTRINSICS (not
*_TYPE_TRAITS, as that's confusing, the type_traits stuff will always
be present). I can fix that if that sounds sensible. The
__is_standard_layout and __is_trivial are really just MSVC's __is_pod,
I don't know how conformant this will be untill I am able to run the
tests.

The bad news: I've run into another language incompatibility, namely
MSVC not allowing template function default template-arguments. I've
looked in C++03 and my C++11 FDIS, and there's indeed a difference,
and it is allowed in C++11 as far as I can see. But of course MSVC
doesn't allow it. I believe I can disable the error (which seems to be
a warning emitted by default as an error:
http://msdn.microsoft.com/en-us/library/190h9wbh(v=VS.100).aspx), but
I'm not sure if it'll have the wanted behavior (the default argument
will be ignored).

Comments and commits are welcome!

Ruben
-------------- next part --------------
Index: include/pthread_compat.h
===================================================================
--- include/pthread_compat.h	(revision 0)
+++ include/pthread_compat.h	(revision 0)
@@ -0,0 +1,76 @@
+/*
+   Copyright (c) 2011 mingw-w64 project
+
+   Permission is hereby granted, free of charge, to any person obtaining a
+   copy of this software and associated documentation files (the "Software"),
+   to deal in the Software without restriction, including without limitation
+   the rights to use, copy, modify, merge, publish, distribute, sublicense,
+   and/or sell copies of the Software, and to permit persons to whom the
+   Software is furnished to do so, subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in
+   all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+ * Parts of this library are derived by:
+ *
+ * Posix Threads library for Microsoft Windows
+ *
+ * Use at own risk, there is no implied warranty to this code.
+ * It uses undocumented features of Microsoft Windows that can change
+ * at any time in the future.
+ *
+ * (C) 2010 Lockless Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *
+ *  * Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *  * Neither the name of Lockless Inc. nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AN
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WIN_PTHREADS_PTHREAD_COMPAT_H
+#define WIN_PTHREADS_PTHREAD_COMPAT_H
+
+#ifdef _MSC_VER
+
+#include "pthread_time.h"
+
+typedef __int64 pid_t;
+typedef int clockid_t;
+
+#define inline __inline
+#define __attribute__(X) __declspec X
+#define __section__(X) allocate(X)
+
+#endif
+
+#endif
Index: include/pthread.h
===================================================================
--- include/pthread.h	(revision 4641)
+++ include/pthread.h	(working copy)
@@ -69,6 +69,8 @@
 
 #include <sys/timeb.h>
 
+#include "pthread_compat.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -301,7 +303,7 @@
 pthread_t WINPTHREAD_API pthread_self(void);
 int       WINPTHREAD_API pthread_get_concurrency(int *val);
 int       WINPTHREAD_API pthread_set_concurrency(int val);
-int       WINPTHREAD_API pthread_exit(void *res);
+void      WINPTHREAD_API pthread_exit(void *res);
 void      WINPTHREAD_API _pthread_invoke_cancel(void);
 void      WINPTHREAD_API pthread_testcancel(void);
 int       WINPTHREAD_API pthread_cancel(pthread_t t);
Index: src/misc.h
===================================================================
--- src/misc.h	(revision 4641)
+++ src/misc.h	(working copy)
@@ -23,6 +23,8 @@
 #ifndef WIN_PTHREADS_MISC_H
 #define WIN_PTHREADS_MISC_H
 
+#include "pthread_compat.h"
+
 #ifndef assert
 
 #ifndef ASSERT_TRACE
Index: src/mutex.c
===================================================================
--- src/mutex.c	(revision 4641)
+++ src/mutex.c	(working copy)
@@ -249,6 +249,7 @@
 {
     unsigned long long t, ct;
     int r;
+    mutex_t *_m;
 
     if (!ts) return pthread_mutex_lock(m);
     r = mutex_ref(m);
@@ -258,7 +259,7 @@
     r=_mutex_trylock(m);
     if (r != EBUSY) return mutex_unref(m,r);
     
-    mutex_t *_m = (mutex_t *)*m;
+    _m = (mutex_t *)*m;
     if (_m->type != PTHREAD_MUTEX_NORMAL && COND_LOCKED(_m) && COND_OWNER(_m))
       return mutex_unref(m,EDEADLK);
     ct = _pthread_time_in_ms();
@@ -269,11 +270,12 @@
 }
 
 int pthread_mutex_unlock(pthread_mutex_t *m)
-{
+{    
+    mutex_t *_m;
     int r = mutex_ref_unlock(m);
     if(r) return r;
 
-    mutex_t *_m = (mutex_t *)*m;
+    _m = (mutex_t *)*m;
     if (_m->type == PTHREAD_MUTEX_NORMAL)
     {
         if (!COND_LOCKED(_m))
@@ -383,13 +385,14 @@
 
 int pthread_mutex_destroy(pthread_mutex_t *m)
 {
+    mutex_t *_m;
     pthread_mutex_t mDestroy;
     int r = mutex_ref_destroy(m,&mDestroy);
     if(r) return r;
     if(!mDestroy) return 0; /* destroyed a (still) static initialized mutex */
 
     /* now the mutex is invalid, and no one can touch it */
-    mutex_t *_m = (mutex_t *)mDestroy;
+    _m = (mutex_t *)mDestroy;
 
 
     CloseHandle(_m->h);
Index: src/thread.c
===================================================================
--- src/thread.c	(revision 4641)
+++ src/thread.c	(working copy)
@@ -322,6 +322,8 @@
 __dyn_tls_pthread (HANDLE hDllHandle, DWORD dwReason, LPVOID lpreserved)
 {
   _pthread_v *t = NULL;
+  spin_t new_spin_keys = {0, LIFE_SPINLOCK, 1};
+
   if (dwReason == DLL_PROCESS_DETACH)
     {
       free_pthread_mem ();
@@ -342,7 +344,7 @@
 	      t->h = NULL;
 	    }
 	  pthread_mutex_destroy (&t->p_clock);
-	  t->spin_keys = (spin_t) {0,LIFE_SPINLOCK, 1};
+	  t->spin_keys = new_spin_keys;
 	  push_pthread_mem (t);
 	  t = NULL;
 	  TlsSetValue (_pthread_tls, t);
@@ -365,7 +367,7 @@
 	      TlsSetValue (_pthread_tls, t);
 	    }
 	  pthread_mutex_destroy(&t->p_clock);
-	  t->spin_keys = (spin_t) {0,LIFE_SPINLOCK, 1};
+	  t->spin_keys = new_spin_keys;
 	}
       else if (t)
 	{
@@ -373,14 +375,20 @@
 	    CloseHandle (t->evStart);
 	  t->evStart = NULL;
 	  pthread_mutex_destroy (&t->p_clock);
-	  t->spin_keys = (spin_t) {0,LIFE_SPINLOCK,1};
+	  t->spin_keys = new_spin_keys;
 	}
     }
   return TRUE;
 }
 
 /* TLS-runtime section variable.  */
-PIMAGE_TLS_CALLBACK __xl_f __attribute__ ((section (".CRT$XLF"))) = (PIMAGE_TLS_CALLBACK) __dyn_tls_pthread;
+#ifdef _MSC_VER
+#pragma section(".CRT$XLF", shared)
+#endif
+PIMAGE_TLS_CALLBACK __attribute__ ((__section__ (".CRT$XLF"))) __xl_f  = (PIMAGE_TLS_CALLBACK) __dyn_tls_pthread;
+#ifdef _MSC_VER
+#pragma data_seg()
+#endif
 
 #ifdef WINPTHREAD_DBG
 static int print_state = 0;
@@ -858,6 +866,7 @@
 __pthread_self_lite (void)
 {
   _pthread_v *t;
+  spin_t new_spin_keys = {0,LIFE_SPINLOCK,1};
 
   _pthread_once_raw (&_pthread_tls_once, pthread_tls_init);
 
@@ -875,7 +884,7 @@
   t->tid = GetCurrentThreadId();
   t->evStart = CreateEvent (NULL, 1, 0, NULL);
   t->p_clock = PTHREAD_MUTEX_INITIALIZER;
-  t->spin_keys = (spin_t) {0,LIFE_SPINLOCK,1};
+  t->spin_keys = new_spin_keys;
   t->sched_pol = SCHED_OTHER;
   t->h = NULL; //GetCurrentThread();
   if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &t->h, 0, FALSE, DUPLICATE_SAME_ACCESS))
@@ -939,16 +948,13 @@
   return 0;
 }
 
-int
+void
 pthread_exit (void *res)
 {
   _pthread_v *t = NULL;
   unsigned rslt = (unsigned) ((intptr_t) res);
   struct _pthread_v *id = __pthread_self_lite ();
 
-  if (!id)
-    return EINVAL;
-
   id->ret_arg = res;
 
   _pthread_cleanup_dest (id->x);
@@ -994,9 +1000,9 @@
 void
 _pthread_invoke_cancel (void)
 {
+  _pthread_cleanup *pcup;
   struct _pthread_v *se = __pthread_self_lite ();
   se->in_cancel = 1;
-  _pthread_cleanup *pcup;
   _pthread_setnobreak (1);
   InterlockedDecrement(&_pthread_cancelling);
 
@@ -1410,6 +1416,7 @@
   int redo = 0;
   struct _pthread_v *tv;
   size_t ssize = 0;
+  spin_t new_spin_keys = {0,LIFE_SPINLOCK,1};
 
   if ((tv = pop_pthread_mem ()) == NULL)
     return EAGAIN;
@@ -1434,7 +1441,7 @@
   while (++redo <= 4);
 
   tv->p_clock = PTHREAD_MUTEX_INITIALIZER;
-  tv->spin_keys = (spin_t) {0,LIFE_SPINLOCK,1};
+  tv->spin_keys = new_spin_keys;
   tv->valid = LIFE_THREAD;
   tv->sched.sched_priority = THREAD_PRIORITY_NORMAL;
   tv->sched_pol = SCHED_OTHER;
@@ -1472,7 +1479,7 @@
       if (tv->evStart)
 	CloseHandle (tv->evStart);
       pthread_mutex_destroy (&tv->p_clock);
-      tv->spin_keys = (spin_t) {0,LIFE_SPINLOCK,1};
+      tv->spin_keys = new_spin_keys;
       tv->evStart = NULL;
       if (th)
         memset(th,0, sizeof (pthread_t));
@@ -1513,6 +1520,7 @@
 {
   DWORD dwFlags;
   struct _pthread_v *tv = __pth_gpointer_locked (t);
+  spin_t new_spin_keys = {0,LIFE_SPINLOCK,1};
 
   if (!tv || tv->h == NULL || !GetHandleInformation(tv->h, &dwFlags))
     return ESRCH;
@@ -1533,7 +1541,7 @@
   if (res)
     *res = tv->ret_arg;
   pthread_mutex_destroy (&tv->p_clock);
-  tv->spin_keys = (spin_t) {0,LIFE_SPINLOCK,1};
+  tv->spin_keys = new_spin_keys;
   push_pthread_mem (tv);
 
   return 0;
@@ -1544,6 +1552,7 @@
 {
   DWORD dwFlags;
   struct _pthread_v *tv;
+  spin_t new_spin_keys = {0,LIFE_SPINLOCK,1};
 
   pthread_mutex_lock (&mtx_pthr_locked);
   tv = __pth_gpointer_locked (t);
@@ -1582,7 +1591,7 @@
   if (res)
     *res = tv->ret_arg;
   pthread_mutex_destroy (&tv->p_clock);
-  tv->spin_keys = (spin_t) {0,LIFE_SPINLOCK,1};
+  tv->spin_keys = new_spin_keys;
 
   push_pthread_mem (tv);
 
@@ -1598,6 +1607,7 @@
   DWORD dwFlags;
   struct _pthread_v *tv = __pth_gpointer_locked (t);
   HANDLE dw;
+  spin_t new_spin_keys = {0,LIFE_SPINLOCK,1};
 
   pthread_mutex_lock (&mtx_pthr_locked);
   if (!tv || tv->h == NULL || !GetHandleInformation(tv->h, &dwFlags))
@@ -1624,7 +1634,7 @@
 	    CloseHandle (tv->evStart);
 	  tv->evStart = NULL;
 	  pthread_mutex_destroy (&tv->p_clock);
-	  tv->spin_keys = (spin_t) {0,LIFE_SPINLOCK,1};
+	  tv->spin_keys = new_spin_keys;
 	  push_pthread_mem (tv);
 	}
     }
Index: src/cond.c
===================================================================
--- src/cond.c	(revision 4641)
+++ src/cond.c	(working copy)
@@ -36,6 +36,8 @@
 #include "misc.h"
 #include "winpthread_internal.h"
 
+#include "pthread_compat.h"
+
 int __pthread_shallcancel (void);
 
 static int do_sema_b_wait (HANDLE sema, int nointerrupt, DWORD timeout,CRITICAL_SECTION *cs, LONG *val);
Index: src/sem.c
===================================================================
--- src/sem.c	(revision 4641)
+++ src/sem.c	(working copy)
@@ -214,7 +214,7 @@
   int cur_v, ret = 0;
   DWORD dwr;
   HANDLE semh;
-  _sem_t *sv;;
+  _sem_t *sv;
   struct sSemTimedWait arg;
 
   if (!t)
@@ -327,7 +327,7 @@
 int
 sem_getvalue (sem_t *sem, int *sval)
 {
-  _sem_t *sv;;
+  _sem_t *sv;
   int r;
 
   if (!sval)
Index: src/barrier.c
===================================================================
--- src/barrier.c	(revision 4641)
+++ src/barrier.c	(working copy)
@@ -90,12 +90,13 @@
 int pthread_barrier_destroy(pthread_barrier_t *b_)
 {
     pthread_barrier_t bDestroy;
+    barrier_t *b;
     int r = barrier_ref_destroy(b_,&bDestroy);
     
     if (r)
       return r;
 
-    barrier_t *b = (barrier_t *)bDestroy;
+    b = (barrier_t *)bDestroy;
     
     pthread_mutex_lock(&b->m);
 
@@ -174,11 +175,12 @@
 {
   long sel;
   int r, e, rslt;
+  barrier_t *b;
 
   r = barrier_ref(b_);
   if(r) return r;
 
-  barrier_t *b = (barrier_t *)*b_;
+  b = (barrier_t *)*b_;
 
   if ((r = pthread_mutex_lock(&b->m))) return  barrier_unref(b_,EINVAL);
   sel = b->sel;
Index: src/clock.c
===================================================================
--- src/clock.c	(revision 4641)
+++ src/clock.c	(working copy)
@@ -9,6 +9,8 @@
 #include <time.h>
 #include <windows.h>
 
+#include "pthread.h"
+
 #define POW10_7                 10000000
 #define POW10_9                 1000000000
 


More information about the cfe-dev mailing list