diff --git a/contrib/sdk/sources/newlib/libc/Makefile b/contrib/sdk/sources/newlib/libc/Makefile index 23848f8567..00d73b1203 100644 --- a/contrib/sdk/sources/newlib/libc/Makefile +++ b/contrib/sdk/sources/newlib/libc/Makefile @@ -16,7 +16,8 @@ LIBC_INCLUDES = $(LIBC_TOPDIR)/include NAME:= libc -DEFINES:= -D_IEEE_LIBM -DHAVE_RENAME -DBUILD_LIBC -DPACKAGE_NAME=\"newlib\" +DEFINES:= -U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -U_MSC_VER +DEFINES+= -D_IEEE_LIBM -DHAVE_RENAME -DBUILD_LIBC -DPACKAGE_NAME=\"newlib\" DEFINES+= -DPACKAGE_TARNAME=\"newlib\" -DPACKAGE_VERSION=\"2.4.0\" SEFINES+= -DPACKAGE_STRING=\"newlib\ 2.4.0\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" @@ -46,6 +47,7 @@ CORE_SRCS:= \ argz/buf_findstr.c \ argz/envz_get.c \ crt/console.asm \ + crt/gthr-kos32.c \ crt/thread.S \ crt/setjmp.S \ crt/cpu_features.c \ diff --git a/contrib/sdk/sources/newlib/libc/Tupfile.lua b/contrib/sdk/sources/newlib/libc/Tupfile.lua index 03a3bef1f7..b6ff7aa92c 100644 --- a/contrib/sdk/sources/newlib/libc/Tupfile.lua +++ b/contrib/sdk/sources/newlib/libc/Tupfile.lua @@ -9,7 +9,7 @@ SDK_DIR = "../../.." LIBC_TOPDIR = "." LIBC_INCLUDES = "include" NAME = "libc" -DEFINES = "-D_IEEE_LIBM -DHAVE_RENAME -DBUILD_LIBC" +DEFINES = "-U__WIN32__ -U_Win32 -U_WIN32 -U__MINGW32__ -U_MSC_VER-D_IEEE_LIBM -DHAVE_RENAME -DBUILD_LIBC" INCLUDES = "-Iinclude" TOOLCHAIN_LIBPATH = tup.getconfig("TOOLCHAIN_LIBPATH") diff --git a/contrib/sdk/sources/newlib/libc/crt/emutls.c b/contrib/sdk/sources/newlib/libc/crt/emutls.c deleted file mode 100644 index 3fe0c44f6e..0000000000 --- a/contrib/sdk/sources/newlib/libc/crt/emutls.c +++ /dev/null @@ -1,218 +0,0 @@ -/* TLS emulation. - Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc. - Contributed by Jakub Jelinek . - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -. */ - - -#include -#include -#include -#include -#include - -void *tls_alloc(void); -void __mutex_lock(volatile int *val); - - -static inline void yield(void) -{ - __asm__ __volatile__( - "int $0x40" - ::"a"(68), "b"(1)); -}; - -int __gthread_once (__gthread_once_t *once, void (*func) (void)) -{ - if (once == NULL || func == NULL) - return EINVAL; - - if (! once->done) - { - if(++once->started == 0) - { - (*func) (); - once->done = 1; - } - else - { - /* Another thread is currently executing the code, so wait for it - to finish; yield the CPU in the meantime. If performance - does become an issue, the solution is to use an Event that - we wait on here (and set above), but that implies a place to - create the event before this routine is called. */ - while (! once->done) - yield(); - } - } - return 0; -} - - -#define __GTHREAD_ONCE_INIT {0, -1} - -typedef unsigned int word __attribute__((mode(word))); -typedef unsigned int pointer __attribute__((mode(pointer))); - -struct __emutls_object -{ - word size; - word align; - union { - pointer offset; - void *ptr; - } loc; - void *templ; -}; - -struct __emutls_array -{ - pointer size; - void **data[]; -}; - -void *__emutls_get_address (struct __emutls_object *); -void __emutls_register_common (struct __emutls_object *, word, word, void *); - -static __gthread_mutex_t emutls_mutex; -static __gthread_key_t emutls_key; -static pointer emutls_size; - -static void emutls_destroy (void *ptr) -{ - struct __emutls_array *arr = ptr; - pointer size = arr->size; - pointer i; - - for (i = 0; i < size; ++i) - { - if (arr->data[i]) - free (arr->data[i][-1]); - } - free (ptr); -}; - -static void emutls_init (void) -{ - if (__gthread_key_create (&emutls_key, emutls_destroy) != 0) - abort (); -} - -static void *emutls_alloc (struct __emutls_object *obj) -{ - void *ptr; - void *ret; - - /* We could use here posix_memalign if available and adjust - emutls_destroy accordingly. */ - if (obj->align <= sizeof (void *)) - { - ptr = malloc (obj->size + sizeof (void *)); - if (ptr == NULL) - abort (); - ((void **) ptr)[0] = ptr; - ret = ptr + sizeof (void *); - } - else - { - ptr = malloc (obj->size + sizeof (void *) + obj->align - 1); - if (ptr == NULL) - abort (); - ret = (void *) (((pointer) (ptr + sizeof (void *) + obj->align - 1)) - & ~(pointer)(obj->align - 1)); - ((void **) ret)[-1] = ptr; - } - - if (obj->templ) - memcpy (ret, obj->templ, obj->size); - else - memset (ret, 0, obj->size); - - return ret; -} - -void * __emutls_get_address (struct __emutls_object *obj) -{ - pointer offset = obj->loc.offset; - - if (__builtin_expect (offset == 0, 0)) - { - static __gthread_once_t once = __GTHREAD_ONCE_INIT; - __gthread_once (&once, emutls_init); - __gthread_mutex_lock (&emutls_mutex); - offset = obj->loc.offset; - if (offset == 0) - { - offset = ++emutls_size; - obj->loc.offset = offset; - } - __gthread_mutex_unlock (&emutls_mutex); - } - - struct __emutls_array *arr = __gthread_getspecific (emutls_key); - if (__builtin_expect (arr == NULL, 0)) - { - pointer size = offset + 32; - arr = calloc (size + 1, sizeof (void *)); - if (arr == NULL) - abort (); - arr->size = size; - __gthread_setspecific (emutls_key, (void *) arr); - } - else if (__builtin_expect (offset > arr->size, 0)) - { - pointer orig_size = arr->size; - pointer size = orig_size * 2; - if (offset > size) - size = offset + 32; - arr = realloc (arr, (size + 1) * sizeof (void *)); - if (arr == NULL) - abort (); - arr->size = size; - memset (arr->data + orig_size, 0, - (size - orig_size) * sizeof (void *)); - __gthread_setspecific (emutls_key, (void *) arr); - } - - void *ret = arr->data[offset - 1]; - if (__builtin_expect (ret == NULL, 0)) - { - ret = emutls_alloc (obj); - arr->data[offset - 1] = ret; - } - return ret; -} - - -void __emutls_register_common (struct __emutls_object *obj, - word size, word align, void *templ) -{ - if (obj->size < size) - { - obj->size = size; - obj->templ = NULL; - } - if (obj->align < align) - obj->align = align; - if (templ && size == obj->size) - obj->templ = templ; -} diff --git a/contrib/sdk/sources/newlib/libc/crt/gthr-kos32.c b/contrib/sdk/sources/newlib/libc/crt/gthr-kos32.c new file mode 100644 index 0000000000..ddbed39534 --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/crt/gthr-kos32.c @@ -0,0 +1,258 @@ +/* Implementation of Kos32-specific threads compatibility routines for + libgcc2. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include +#include +#include "gthr-kos32.h" + +#define FUTEX_INIT 0 +#define FUTEX_DESTROY 1 +#define FUTEX_WAIT 2 +#define FUTEX_WAKE 3 + +#define exchange_acquire(ptr, new) \ + __atomic_exchange_4((ptr), (new), __ATOMIC_ACQUIRE) + +#define exchange_release(ptr, new) \ + __atomic_exchange_4((ptr), (new), __ATOMIC_RELEASE) + +int __gthr_kos32_once (__gthread_once_t *once, void (*func) (void)) +{ + if (once == NULL || func == NULL) + return EINVAL; + + if (! once->done) + { + if (__sync_add_and_fetch(&(once->started), 1) == 0) + { + (*func) (); + once->done = 1; + } + else + { + while (! once->done) + yield(); + } + } + return 0; +}; + +int __gthr_kos32_key_create (__gthread_key_t *key, + void (*dtor) (void *) __attribute__((unused))) +{ + int status = 0; + unsigned int tls_index = tls_alloc(); + if (tls_index != 0xFFFFFFFF) + { + *key = tls_index; +#ifdef MINGW32_SUPPORTS_MT_EH + /* Mingw runtime will run the dtors in reverse order for each thread + when the thread exits. */ + status = __mingwthr_key_dtor (*key, dtor); +#endif + } + else + status = -1; + return status; +} + +int __gthr_kos32_key_delete (__gthread_key_t key) +{ + return tls_free(key); +} + +void* __gthr_kos32_getspecific (__gthread_key_t key) +{ + return tls_get(key); +} + +int __gthr_kos32_setspecific (__gthread_key_t key, const void *ptr) +{ + return tls_set(key, CONST_CAST2(void *, const void *, ptr)); +} + +void __gthr_kos32_mutex_init_function (__gthread_mutex_t *mutex) +{ + int handle; + + mutex->lock = 0; + + __asm__ volatile( + "int $0x40\t" + :"=a"(handle) + :"a"(77),"b"(FUTEX_INIT),"c"(mutex)); + mutex->handle = handle; +} + +void __gthr_kos32_mutex_destroy (__gthread_mutex_t *mutex) +{ + int retval; + + __asm__ volatile( + "int $0x40\t" + :"=a"(retval) + :"a"(77),"b"(FUTEX_DESTROY),"c"(mutex->handle)); +} + +int __gthr_kos32_mutex_lock (__gthread_mutex_t *mutex) +{ + int tmp; + + if( __sync_fetch_and_add(&mutex->lock, 1) == 0) + return 0; + + while (exchange_acquire (&mutex->lock, 2) != 0) + { + __asm__ volatile( + "int $0x40\t\n" + :"=a"(tmp) + :"a"(77),"b"(FUTEX_WAIT), + "c"(mutex->handle),"d"(2),"S"(0)); + } + return 0; +} + +int __gthr_kos32_mutex_trylock (__gthread_mutex_t *mutex) +{ + int zero = 0; + + return !__atomic_compare_exchange_4(&mutex->lock, &zero, 1,0,__ATOMIC_ACQUIRE,__ATOMIC_RELAXED); +} + +int __gthr_kos32_mutex_unlock (__gthread_mutex_t *mutex) +{ + int prev; + + prev = exchange_release (&mutex->lock, 0); + + if (prev != 1) + { + __asm__ volatile( + "int $0x40\t" + :"=a"(prev) + :"a"(77),"b"(FUTEX_WAKE), + "c"(mutex->handle),"d"(1)); + }; + return 0; +} + +void __gthr_kos32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex) +{ + int handle; + + mutex->lock = 0; + + __asm__ volatile( + "int $0x40\t" + :"=a"(handle) + :"a"(77),"b"(FUTEX_INIT),"c"(mutex)); + mutex->handle = handle; + + mutex->depth = 0; + mutex->owner = 0; +} + +int __gthr_kos32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex) +{ + int tmp; + + unsigned long me = (unsigned long)tls_get(TLS_KEY_LOW_STACK); + + if( __sync_fetch_and_add(&mutex->lock, 1) == 0) + { + mutex->depth = 1; + mutex->owner = me; + return 0; + } + else if (mutex->owner == me) + { + __sync_fetch_and_sub(&mutex->lock, 1); + ++(mutex->depth); + } + else while (exchange_acquire (&mutex->lock, 2) != 0) + { + __asm__ volatile( + "int $0x40\t\n" + :"=a"(tmp) + :"a"(77),"b"(FUTEX_WAIT), + "c"(mutex->handle),"d"(2),"S"(0)); + mutex->depth = 1; + mutex->owner = me; + }; + + return 0; +} + +int __gthr_kos32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex) +{ + unsigned long me = (unsigned long)tls_get(TLS_KEY_LOW_STACK); + int zero = 0; + + if(__atomic_compare_exchange_4(&mutex->lock, &zero, 1,0,__ATOMIC_ACQUIRE,__ATOMIC_RELAXED)) + { + mutex->depth = 1; + mutex->owner = me; + } + else if (mutex->owner == me) + ++(mutex->depth); + else + return 1; + + return 0; +} + +int __gthr_kos32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex) +{ + --(mutex->depth); + + if (mutex->depth == 0) + { + int prev; + + prev = exchange_release (&mutex->lock, 0); + + if (prev != 1) + { + __asm__ volatile( + "int $0x40\t" + :"=a"(prev) + :"a"(77),"b"(FUTEX_WAKE), + "c"(mutex->handle),"d"(1)); + }; + mutex->owner = 0; + }; + + return 0; +} + +int __gthr_kos32_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex) +{ + int retval; + + __asm__ volatile( + "int $0x40\t" + :"=a"(retval) + :"a"(77),"b"(FUTEX_DESTROY),"c"(mutex->handle)); + + return 0; +} + diff --git a/contrib/sdk/sources/newlib/libc/crt/gthr-kos32.h b/contrib/sdk/sources/newlib/libc/crt/gthr-kos32.h new file mode 100644 index 0000000000..1372b4c72a --- /dev/null +++ b/contrib/sdk/sources/newlib/libc/crt/gthr-kos32.h @@ -0,0 +1,215 @@ +/* Threads compatibility routines for libgcc2 and libobjc. */ +/* Compile this one with gcc. */ + +/* Copyright (C) 1999-2015 Free Software Foundation, Inc. + Contributed by Mumit Khan . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef GCC_GTHR_KOS32_H +#define GCC_GTHR_KOS32_H + +/* Make sure CONST_CAST2 (origin in system.h) is declared. */ +#ifndef CONST_CAST2 +#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq) +#endif + + +#define __GTHREADS 1 + +#include + +#ifndef __UNUSED_PARAM +#define __UNUSED_PARAM(x) x +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long __gthread_key_t; + +typedef struct +{ + int done; + long started; +} __gthread_once_t; + +typedef struct +{ + volatile int lock; + int handle; +} __gthread_mutex_t; + +typedef struct +{ + volatile int lock; + int handle; + long depth; + unsigned long owner; +} __gthread_recursive_mutex_t; + +#define __GTHREAD_ONCE_INIT {0, -1} +#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function + +#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION \ + __gthread_recursive_mutex_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 + if -mthreads option was specified, or 0 otherwise. This is to get around + the lack of weak symbols in PE-COFF. */ +extern int _CRT_MT; +extern int __mingwthr_key_dtor (unsigned long, void (*) (void *)); +#endif /* _WIN32 && !__CYGWIN__ */ + + +static inline int __gthread_active_p (void) +{ +#ifdef MINGW32_SUPPORTS_MT_EH + return _CRT_MT; +#else + return 1; +#endif +} + +extern int __gthr_kos32_once (__gthread_once_t *, void (*) (void)); +extern int __gthr_kos32_key_create (__gthread_key_t *, void (*) (void*)); +extern int __gthr_kos32_key_delete (__gthread_key_t); +extern void * __gthr_kos32_getspecific (__gthread_key_t); +extern int __gthr_kos32_setspecific (__gthread_key_t, const void *); +extern void __gthr_kos32_mutex_init_function (__gthread_mutex_t *); +extern int __gthr_kos32_mutex_lock (__gthread_mutex_t *); +extern int __gthr_kos32_mutex_trylock (__gthread_mutex_t *); +extern int __gthr_kos32_mutex_unlock (__gthread_mutex_t *); +extern void __gthr_kos32_recursive_mutex_init_function (__gthread_recursive_mutex_t *); +extern int __gthr_kos32_recursive_mutex_lock (__gthread_recursive_mutex_t *); +extern int __gthr_kos32_recursive_mutex_trylock (__gthread_recursive_mutex_t *); +extern int __gthr_kos32_recursive_mutex_unlock (__gthread_recursive_mutex_t *); +extern void __gthr_kos32_mutex_destroy (__gthread_mutex_t *); +extern int __gthr_kos32_recursive_mutex_destroy (__gthread_recursive_mutex_t *); + +static inline int __gthread_once (__gthread_once_t *__once, void (*__func) (void)) +{ + if (__gthread_active_p ()) + return __gthr_kos32_once (__once, __func); + else + return -1; +} + +static inline int __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) +{ + return __gthr_kos32_key_create (__key, __dtor); +} + +static inline int __gthread_key_delete (__gthread_key_t __key) +{ + return __gthr_kos32_key_delete (__key); +} + +static inline void* __gthread_getspecific (__gthread_key_t __key) +{ + return __gthr_kos32_getspecific (__key); +} + +static inline int __gthread_setspecific (__gthread_key_t __key, const void *__ptr) +{ + return __gthr_kos32_setspecific (__key, __ptr); +} + +static inline void __gthread_mutex_init_function (__gthread_mutex_t *__mutex) +{ + __gthr_kos32_mutex_init_function(__mutex); +} + +static inline void __gthread_mutex_destroy (__gthread_mutex_t *__mutex) +{ + __gthr_kos32_mutex_destroy (__mutex); +} + +static inline int __gthread_mutex_lock (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthr_kos32_mutex_lock (__mutex); + else + return 0; +} + +static inline int __gthread_mutex_trylock (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthr_kos32_mutex_trylock (__mutex); + else + return 0; +} + +static inline int __gthread_mutex_unlock (__gthread_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthr_kos32_mutex_unlock (__mutex); + else + return 0; +} + +static inline void __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) +{ + __gthr_kos32_recursive_mutex_init_function (__mutex); +} + +static inline int __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthr_kos32_recursive_mutex_lock (__mutex); + else + return 0; +} + +static inline int __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthr_kos32_recursive_mutex_trylock (__mutex); + else + return 0; +} + +static inline int __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) +{ + if (__gthread_active_p ()) + return __gthr_kos32_recursive_mutex_unlock (__mutex); + else + return 0; +} + +static inline int __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex) +{ + return __gthr_kos32_recursive_mutex_destroy (__mutex); +} + + +#ifdef __cplusplus +} +#endif + +#endif /* ! GCC_GTHR_WIN32_H */