diff mbox

[newlib] Allow locking routine to be retargeted

Message ID 34e2c2ad-be0f-44ed-201e-a6f294814f4e@foss.arm.com
State Superseded
Headers show

Commit Message

Thomas Preudhomme Dec. 13, 2016, 5:18 p.m. UTC
Hi,

At the moment when targeting bare-metal targets or systems without definition 
for the locking primitives newlib, uses dummy empty macros. This has the 
advantage of reduced size and faster implementation but does not allow the 
application to retarget the locking routines. Retargeting is useful for a single 
toolchain to support multiple systems since then it's only at build time that 
you know which system you are targeting.

This patch adds a new configure option --enable-newlib-retargetable-locking to 
use dummy empty weakly defined functions instead of dummy empty macros. The 
default is to keep the current behavior to not have any size or speed impact on 
targets not interested in this feature.

Testing: I've built a simple test program that calls malloc and free with all 
the locking function defined in the same file. Running into a debugger with 
breakpoints on the function shows that they are indeed called. Newlib testsuite 
(the 30 tests that run wich check-target-newlib from GCC) also comes back clean.

Is this ok for master branch?

Best regards,

Thomas

Comments

Freddie Chopin Dec. 13, 2016, 8:12 p.m. UTC | #1
Great!

I've already managed to compile the toolchain for ARM, now I'm trying
to implement all these "retargeting" functions and required lock
objects. We'll see how it works (;

BTW - maybe it would be better to leave the functions undefined and
provide the stubs only in libnosys.a? This would be consistent with
other newlib stubs (like _sbrk_r(), _read_r() and so on)?

Regards,
FCh
Freddie Chopin Dec. 13, 2016, 9:10 p.m. UTC | #2
OK.

Issue 1 - contents of lock.h should be surrounded with:

#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
}
#endif

Regards,
FCh
Freddie Chopin Dec. 13, 2016, 9:40 p.m. UTC | #3
Apart from the issue with missing extern "C" for C++, everything seems
to work fine in my limited test with four required global locks and
some uses of stdio functions.

Regards,
FCh
Thomas Preudhomme Dec. 14, 2016, 11:54 a.m. UTC | #4
On 13/12/16 20:12, Freddie Chopin wrote:
> Great!

>

> I've already managed to compile the toolchain for ARM, now I'm trying

> to implement all these "retargeting" functions and required lock

> objects. We'll see how it works (;

>

> BTW - maybe it would be better to leave the functions undefined and

> provide the stubs only in libnosys.a? This would be consistent with

> other newlib stubs (like _sbrk_r(), _read_r() and so on)?


I need to look into how does that work when not using libnosys.a. I'll also add 
the extern C as per your suggestion.

Thanks,

Thomas
Freddie Chopin Dec. 14, 2016, 12:38 p.m. UTC | #5
On Wed, 2016-12-14 at 11:54 +0000, Thomas Preudhomme wrote:
> On 13/12/16 20:12, Freddie Chopin wrote:

> > Great!

> > 

> > I've already managed to compile the toolchain for ARM, now I'm

> > trying

> > to implement all these "retargeting" functions and required lock

> > objects. We'll see how it works (;

> > 

> > BTW - maybe it would be better to leave the functions undefined and

> > provide the stubs only in libnosys.a? This would be consistent with

> > other newlib stubs (like _sbrk_r(), _read_r() and so on)?

> 

> I need to look into how does that work when not using libnosys


It's worth trying. I think that as long as the project doesn't use any
code which requires locking, there will be no problem at all.

When the user _DOES_ use some code which requires them, he'll get the
linking errors (withou libnosys.a). But given the fact that the two
most "popular" locks which will be used are atexit and malloc, the
situation is not so bad:
1. atexit usually uses malloc anyway,
2. malloc requires you to provide _sbrk_r() - if you don't you'll get a
linking error,
3. the fact that the functions are provided as weak symbols probably
doesn't change much - the user would get linking errors anyway, because
the storage for locks is not provided.

With item 3 in mind, I guess that if you provide weak functions, some
dummy storage should also be provided as a weak symbol - either in
lock.c or in libnosys.a.

Regards,
FCh
Sebastian Huber Dec. 14, 2016, 2:21 p.m. UTC | #6
On 13/12/16 18:18, Thomas Preudhomme wrote:
> +#else

> +

> +typedef void * _LOCK_T;

> +#define _LOCK_RECURSIVE_T _LOCK_T

> +

> +#define __LOCK_INIT(class,lock) extern struct_lock _lock_  ## lock; \

> +	class_LOCK_T lock = &_lock_  ## lock

> +#define __LOCK_INIT_RECURSIVE(class,lock) __LOCK_INIT(class,lock)


I would use:

struct _lock;
typedef struct _lock *_LOCK_T;

This makes debugging a bit easier.

-- 
Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone   : +49 89 189 47 41-16
Fax     : +49 89 189 47 41-09
E-Mail  : sebastian.huber@embedded-brains.de
PGP     : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
Thomas Preudhomme Dec. 14, 2016, 2:36 p.m. UTC | #7
On 14/12/16 14:21, Sebastian Huber wrote:
>

>

> On 13/12/16 18:18, Thomas Preudhomme wrote:

>> +#else

>> +

>> +typedef void * _LOCK_T;

>> +#define _LOCK_RECURSIVE_T _LOCK_T

>> +

>> +#define __LOCK_INIT(class,lock) extern struct_lock _lock_  ## lock; \

>> +    class_LOCK_T lock = &_lock_  ## lock

>> +#define __LOCK_INIT_RECURSIVE(class,lock) __LOCK_INIT(class,lock)

>

> I would use:

>

> struct _lock;

> typedef struct _lock *_LOCK_T;

>

> This makes debugging a bit easier.


But then if your lock is just an integer you have to use a structure with a 
single field, right?

Why is struct _lock easier to debug by the way?

Best regards,

Thomas
Thomas Preudhomme Dec. 14, 2016, 2:52 p.m. UTC | #8
On 14/12/16 14:36, Thomas Preudhomme wrote:
>

>

> On 14/12/16 14:21, Sebastian Huber wrote:

>>

>>

>> On 13/12/16 18:18, Thomas Preudhomme wrote:

>>> +#else

>>> +

>>> +typedef void * _LOCK_T;

>>> +#define _LOCK_RECURSIVE_T _LOCK_T

>>> +

>>> +#define __LOCK_INIT(class,lock) extern struct_lock _lock_  ## lock; \

>>> +    class_LOCK_T lock = &_lock_  ## lock

>>> +#define __LOCK_INIT_RECURSIVE(class,lock) __LOCK_INIT(class,lock)

>>

>> I would use:

>>

>> struct _lock;

>> typedef struct _lock *_LOCK_T;

>>

>> This makes debugging a bit easier.

>

> But then if your lock is just an integer you have to use a structure with a

> single field, right?


I'm thinking that the lock also needs to be weakly defined so that there is no 
link failure on single threaded environment.

Best regards,

Thomas
Freddie Chopin Dec. 14, 2016, 3:26 p.m. UTC | #9
On Wed, 2016-12-14 at 14:36 +0000, Thomas Preudhomme wrote:
> Why is struct _lock easier to debug by the way?


I think the reason is that in user code - which does the "retargeting"
- _lock can be defined to be whatever is needed, so in the debugger you
see the contents of the struct. If you use void*, then you have to do
manual casting in debugger to see these contents.

I think this will also help to keep the retargeting code valid - now
the compiler can check whether you use correct types - either _lock or
it's address, while with void* the compiler will happily accept almost
anything.

Regards,
FCh
Freddie Chopin Jan. 9, 2017, 6:49 p.m. UTC | #10
Thomas - do you still plan to work on this change?

Regards,
FCh
Thomas Preudhomme Jan. 10, 2017, 4:50 p.m. UTC | #11
Yes absolutely. I didn't progress during holidays for obvious reasons but I've 
implemented the changes you requested and am about to start testing.

Best regards,

Thomas

On 09/01/17 18:49, Freddie Chopin wrote:
> Thomas - do you still plan to work on this change?

>

> Regards,

> FCh

>
Freddie Chopin Jan. 10, 2017, 5:06 p.m. UTC | #12
On Tue, 2017-01-10 at 16:50 +0000, Thomas Preudhomme wrote:
> Yes absolutely.


Great!

> I didn't progress during holidays for obvious reasons


Yeah, I had so many plans for this period and did almost nothing (;

> but I've 

> implemented the changes you requested and am about to start testing.


You can share the patch earlier if you want/can, I could test some of
the features too (;

Regards,
FCh
Thomas Preudhomme Jan. 11, 2017, 1:09 p.m. UTC | #13
Hi Freddie,

On 14/12/16 12:38, Freddie Chopin wrote:
> On Wed, 2016-12-14 at 11:54 +0000, Thomas Preudhomme wrote:

>> On 13/12/16 20:12, Freddie Chopin wrote:

>>> Great!

>>>

>>> I've already managed to compile the toolchain for ARM, now I'm

>>> trying

>>> to implement all these "retargeting" functions and required lock

>>> objects. We'll see how it works (;

>>>

>>> BTW - maybe it would be better to leave the functions undefined and

>>> provide the stubs only in libnosys.a? This would be consistent with

>>> other newlib stubs (like _sbrk_r(), _read_r() and so on)?

>>

>> I need to look into how does that work when not using libnosys

>

> It's worth trying. I think that as long as the project doesn't use any

> code which requires locking, there will be no problem at all.

>

> When the user _DOES_ use some code which requires them, he'll get the

> linking errors (withou libnosys.a). But given the fact that the two

> most "popular" locks which will be used are atexit and malloc, the

> situation is not so bad:

> 1. atexit usually uses malloc anyway,

> 2. malloc requires you to provide _sbrk_r() - if you don't you'll get a

> linking error,

> 3. the fact that the functions are provided as weak symbols probably

> doesn't change much - the user would get linking errors anyway, because

> the storage for locks is not provided.

>

> With item 3 in mind, I guess that if you provide weak functions, some

> dummy storage should also be provided as a weak symbol - either in

> lock.c or in libnosys.a.


I looked into putting lock.c in libnosys.a but then the applications fail to 
link when using rdimon for semihosting. I think I'll go for the weak lock and 
dummy functions always linked in (provided newlib was built with the right 
configure option).

Best regards,

Thomas
diff mbox

Patch

diff --git a/newlib/configure b/newlib/configure
index 30e1d57664302248af9087b0051290e2aff4b382..42b1e13feeda8a5b7ad3cf365393bd4640da4c8c 100755
--- a/newlib/configure
+++ b/newlib/configure
@@ -798,6 +798,7 @@  enable_newlib_nano_malloc
 enable_newlib_unbuf_stream_opt
 enable_lite_exit
 enable_newlib_nano_formatted_io
+enable_newlib_retargetable_locking
 enable_multilib
 enable_target_optspace
 enable_malloc_debugging
@@ -1469,6 +1470,7 @@  Optional Features:
   --disable-newlib-unbuf-stream-opt    disable unbuffered stream optimization in streamio
   --enable-lite-exit	enable light weight exit
   --enable-newlib-nano-formatted-io    Use nano version formatted IO
+  --enable-newlib-retargetable-locking    Allow locking routines to be retargeted at link time
   --enable-multilib         build many library versions (default)
   --enable-target-optspace  optimize for space
   --enable-malloc-debugging indicate malloc debugging requested
@@ -2470,6 +2472,18 @@  else
 fi
 
 
+# Check whether --enable-newlib-retargetable-locking was given.
+if test "${enable_newlib_retargetable_locking+set}" = set; then :
+  enableval=$enable_newlib_retargetable_locking; case "${enableval}" in
+   yes) newlib_retargetable_locking=yes ;;
+   no)  newlib_retargetable_locking=no ;;
+   *) as_fn_error $? "bad value ${enableval} for newlib-retargetable-locking" "$LINENO" 5 ;;
+ esac
+else
+  newlib_retargetable_locking=no
+fi
+
+
 
 # Make sure we can run config.sub.
 $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
@@ -11776,7 +11790,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11779 "configure"
+#line 11793 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11882,7 +11896,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11885 "configure"
+#line 11899 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12421,6 +12435,13 @@  _ACEOF
 
 fi
 
+if test "${newlib_retargetable_locking}" = "yes"; then
+cat >>confdefs.h <<_ACEOF
+#define _RETARGETABLE_LOCKING 1
+_ACEOF
+
+fi
+
 
 if test "x${iconv_encodings}" != "x" \
    || test "x${iconv_to_encodings}" != "x" \
diff --git a/newlib/configure.in b/newlib/configure.in
index 01c6367a99cdf6f74a5ad15c8a4eb4a45f206e9d..70cffa76a966f8d9cd1c8888156002e76ea13dc2 100644
--- a/newlib/configure.in
+++ b/newlib/configure.in
@@ -218,6 +218,17 @@  AC_ARG_ENABLE(newlib_nano_formatted_io,
    *) AC_MSG_ERROR(bad value ${enableval} for newlib-nano-formatted-io) ;;
  esac],[newlib_nano_formatted_io=no])
 
+dnl Support --enable-retargetable-locking
+dnl This option is also read in libc/configure.in.  It is repeated
+dnl here so that it shows up in the help text.
+AC_ARG_ENABLE(newlib-retargetable-locking,
+[  --enable-newlib-retargetable-locking    Allow locking routines to be retargeted at link time],
+[case "${enableval}" in
+   yes) newlib_retargetable_locking=yes ;;
+   no)  newlib_retargetable_locking=no ;;
+   *) AC_MSG_ERROR(bad value ${enableval} for newlib-retargetable-locking) ;;
+ esac],[newlib_retargetable_locking=no])
+
 NEWLIB_CONFIGURE(.)
 
 dnl We have to enable libtool after NEWLIB_CONFIGURE because if we try and
@@ -442,6 +453,10 @@  if test "${newlib_nano_formatted_io}" = "yes"; then
 AC_DEFINE_UNQUOTED(_NANO_FORMATTED_IO)
 fi
 
+if test "${newlib_retargetable_locking}" = "yes"; then
+AC_DEFINE_UNQUOTED(_RETARGETABLE_LOCKING)
+fi
+
 dnl
 dnl Parse --enable-newlib-iconv-encodings option argument
 dnl
diff --git a/newlib/libc/configure b/newlib/libc/configure
index 5dccc852b8cd90d697a90f113ec17982741ecc3a..35077b81550aa999026ff67a7428fec6509a26ce 100755
--- a/newlib/libc/configure
+++ b/newlib/libc/configure
@@ -751,6 +751,8 @@  build
 newlib_basedir
 MAY_SUPPLY_SYSCALLS_FALSE
 MAY_SUPPLY_SYSCALLS_TRUE
+NEWLIB_RETARGETABLE_LOCKING_FALSE
+NEWLIB_RETARGETABLE_LOCKING_TRUE
 NEWLIB_NANO_FORMATTED_IO_FALSE
 NEWLIB_NANO_FORMATTED_IO_TRUE
 target_alias
@@ -797,6 +799,7 @@  enable_option_checking
 enable_newlib_io_pos_args
 enable_newlib_nano_malloc
 enable_newlib_nano_formatted_io
+enable_newlib_retargetable_locking
 enable_multilib
 enable_target_optspace
 enable_malloc_debugging
@@ -1448,6 +1451,7 @@  Optional Features:
   --enable-newlib-io-pos-args enable printf-family positional arg support
   --enable-newlib-nano-malloc    Use small-footprint nano-malloc implementation
   --enable-newlib-nano-formatted-io    Use small-footprint nano-formatted-IO implementation
+  --enable-newlib-retargetable-locking    Allow locking routines to be retargeted at link time
   --enable-multilib         build many library versions (default)
   --enable-target-optspace  optimize for space
   --enable-malloc-debugging indicate malloc debugging requested
@@ -2252,6 +2256,26 @@  else
 fi
 
 
+# Check whether --enable-newlib-retargetable-locking was given.
+if test "${enable_newlib_retargetable_locking+set}" = set; then :
+  enableval=$enable_newlib_retargetable_locking; case "${enableval}" in
+   yes) newlib_retargetable_locking=yes ;;
+   no)  newlib_retargetable_lock=no ;;
+   *) as_fn_error $? "bad value ${enableval} for newlib-retargetable-locking" "$LINENO" 5 ;;
+ esac
+else
+  newlib_retargetable_locking=no
+fi
+
+ if test x$newlib_retargetable_locking = xyes; then
+  NEWLIB_RETARGETABLE_LOCKING_TRUE=
+  NEWLIB_RETARGETABLE_LOCKING_FALSE='#'
+else
+  NEWLIB_RETARGETABLE_LOCKING_TRUE='#'
+  NEWLIB_RETARGETABLE_LOCKING_FALSE=
+fi
+
+
 
 # Make sure we can run config.sub.
 $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
@@ -11525,7 +11549,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11528 "configure"
+#line 11552 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11631,7 +11655,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11634 "configure"
+#line 11658 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12248,6 +12272,10 @@  if test -z "${NEWLIB_NANO_FORMATTED_IO_TRUE}" && test -z "${NEWLIB_NANO_FORMATTE
   as_fn_error $? "conditional \"NEWLIB_NANO_FORMATTED_IO\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${NEWLIB_RETARGETABLE_LOCKING_TRUE}" && test -z "${NEWLIB_RETARGETABLE_LOCKING_FALSE}"; then
+  as_fn_error $? "conditional \"NEWLIB_RETARGETABLE_LOCKING\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${MAY_SUPPLY_SYSCALLS_TRUE}" && test -z "${MAY_SUPPLY_SYSCALLS_FALSE}"; then
   as_fn_error $? "conditional \"MAY_SUPPLY_SYSCALLS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/newlib/libc/configure.in b/newlib/libc/configure.in
index 0a7bb8815be44fb1e92f753fa2c8df2a31b95f94..ac25a3933c4a4794f3cfe291e0275d0ed001b96a 100644
--- a/newlib/libc/configure.in
+++ b/newlib/libc/configure.in
@@ -36,6 +36,16 @@  AC_ARG_ENABLE(newlib_nano_formatted_io,
  esac],[newlib_nano_formatted_io=no])
 AM_CONDITIONAL(NEWLIB_NANO_FORMATTED_IO, test x$newlib_nano_formatted_io = xyes)
 
+dnl Support --enable-retargetable-locking used by libc/sys
+AC_ARG_ENABLE(newlib-retargetable-locking,
+[  --enable-newlib-retargetable-locking    Allow locking routines to be retargeted at link time],
+[case "${enableval}" in
+   yes) newlib_retargetable_locking=yes ;;
+   no)  newlib_retargetable_lock=no ;;
+   *) AC_MSG_ERROR(bad value ${enableval} for newlib-retargetable-locking) ;;
+ esac],[newlib_retargetable_locking=no])
+AM_CONDITIONAL(NEWLIB_RETARGETABLE_LOCKING, test x$newlib_retargetable_locking = xyes)
+
 NEWLIB_CONFIGURE(..)
 
 AM_CONDITIONAL(NEWLIB_NANO_MALLOC, test x$newlib_nano_malloc = xyes)
diff --git a/newlib/libc/include/sys/lock.h b/newlib/libc/include/sys/lock.h
index 9075e35c9179968031010432515e3a845ff6ca8d..e5bdcd001ea348bac6a77d45eeb1b48f7ef2a69a 100644
--- a/newlib/libc/include/sys/lock.h
+++ b/newlib/libc/include/sys/lock.h
@@ -3,10 +3,13 @@ 
 
 /* dummy lock routines for single-threaded aps */
 
+#include <newlib.h>
+#include <_ansi.h>
+
+#ifndef _RETARGETABLE_LOCKING
+
 typedef int _LOCK_T;
 typedef int _LOCK_RECURSIVE_T;
- 
-#include <_ansi.h>
 
 #define __LOCK_INIT(class,lock) static int lock = 0;
 #define __LOCK_INIT_RECURSIVE(class,lock) static int lock = 0;
@@ -21,4 +24,37 @@  typedef int _LOCK_RECURSIVE_T;
 #define __lock_release(lock) (_CAST_VOID 0)
 #define __lock_release_recursive(lock) (_CAST_VOID 0)
 
+#else
+
+typedef void * _LOCK_T;
+#define _LOCK_RECURSIVE_T _LOCK_T
+
+#define __LOCK_INIT(class,lock) extern struct _lock _lock_ ## lock; \
+	class _LOCK_T lock = &_lock_ ## lock
+#define __LOCK_INIT_RECURSIVE(class,lock) __LOCK_INIT(class,lock)
+
+extern void __retarget_lock_init(_LOCK_T *lock);
+#define __lock_init(lock) __retarget_lock_init(&lock)
+extern void __retarget_lock_init_recursive(_LOCK_T *lock);
+#define __lock_init_recursive(lock) __retarget_lock_init_recursive(&lock)
+extern void __retarget_lock_close(_LOCK_T lock);
+#define __lock_close(lock) __retarget_lock_close(lock)
+extern void __retarget_lock_close_recursive(_LOCK_T lock);
+#define __lock_close_recursive(lock) __retarget_lock_close_recursive(lock)
+extern void __retarget_lock_acquire(_LOCK_T lock);
+#define __lock_acquire(lock) __retarget_lock_acquire(lock)
+extern void __retarget_lock_acquire_recursive(_LOCK_T lock);
+#define __lock_acquire_recursive(lock) __retarget_lock_acquire_recursive(lock)
+extern int __retarget_lock_try_acquire(_LOCK_T lock);
+#define __lock_try_acquire(lock) __retarget_lock_try_acquire(lock)
+extern int __retarget_lock_try_acquire_recursive(_LOCK_T lock);
+#define __lock_try_acquire_recursive(lock) \
+  __retarget_lock_try_acquire_recursive(lock)
+extern void __retarget_lock_release(_LOCK_T lock);
+#define __lock_release(lock) __retarget_lock_release(lock)
+extern void __retarget_lock_release_recursive(_LOCK_T lock);
+#define __lock_release_recursive(lock) __retarget_lock_release_recursive(lock)
+
+#endif /* _RETARGETABLE_LOCKING */
+
 #endif /* __SYS_LOCK_H__ */
diff --git a/newlib/libc/stdlib/Makefile.am b/newlib/libc/stdlib/Makefile.am
index 2d45d1029ace8087b57657cbc11feabf76f4206e..76ed8480c28ebfb68e2f48432c0359b11f1522a8 100644
--- a/newlib/libc/stdlib/Makefile.am
+++ b/newlib/libc/stdlib/Makefile.am
@@ -74,6 +74,11 @@  GENERAL_SOURCES += \
 	wcstold.c
 endif # HAVE_LONG_DOUBLE
 
+if NEWLIB_RETARGETABLE_LOCKING
+GENERAL_SOURCES += \
+	lock.c
+endif
+
 if NEWLIB_NANO_MALLOC
 MALIGNR=nano-malignr
 MALLOPTR=nano-malloptr
diff --git a/newlib/libc/stdlib/Makefile.in b/newlib/libc/stdlib/Makefile.in
index 466ab6d1e02ea919f6c8ceed792024955bef1a66..3295e981c87bac3b21a6b72dda148f892fe018d6 100644
--- a/newlib/libc/stdlib/Makefile.in
+++ b/newlib/libc/stdlib/Makefile.in
@@ -57,6 +57,9 @@  host_triplet = @host@
 @HAVE_LONG_DOUBLE_TRUE@	strtold.c \
 @HAVE_LONG_DOUBLE_TRUE@	wcstold.c
 
+@NEWLIB_RETARGETABLE_LOCKING_TRUE@am__append_2 = \
+@NEWLIB_RETARGETABLE_LOCKING_TRUE@	lock.c
+
 DIST_COMMON = $(srcdir)/../../Makefile.shared $(srcdir)/Makefile.in \
 	$(srcdir)/Makefile.am
 subdir = stdlib
@@ -81,7 +84,9 @@  lib_a_AR = $(AR) $(ARFLAGS)
 @ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@	$(ELIX_2_OBJS)
 @HAVE_LONG_DOUBLE_TRUE@am__objects_1 = lib_a-strtold.$(OBJEXT) \
 @HAVE_LONG_DOUBLE_TRUE@	lib_a-wcstold.$(OBJEXT)
-am__objects_2 = lib_a-__adjust.$(OBJEXT) lib_a-__atexit.$(OBJEXT) \
+@NEWLIB_RETARGETABLE_LOCKING_TRUE@am__objects_2 =  \
+@NEWLIB_RETARGETABLE_LOCKING_TRUE@	lib_a-lock.$(OBJEXT)
+am__objects_3 = lib_a-__adjust.$(OBJEXT) lib_a-__atexit.$(OBJEXT) \
 	lib_a-__call_atexit.$(OBJEXT) lib_a-__exp10.$(OBJEXT) \
 	lib_a-__ten_mu.$(OBJEXT) lib_a-_Exit.$(OBJEXT) \
 	lib_a-abort.$(OBJEXT) lib_a-abs.$(OBJEXT) \
@@ -112,8 +117,8 @@  am__objects_2 = lib_a-__adjust.$(OBJEXT) lib_a-__atexit.$(OBJEXT) \
 	lib_a-wcstol.$(OBJEXT) lib_a-wcstoul.$(OBJEXT) \
 	lib_a-wcstombs.$(OBJEXT) lib_a-wcstombs_r.$(OBJEXT) \
 	lib_a-wctomb.$(OBJEXT) lib_a-wctomb_r.$(OBJEXT) \
-	$(am__objects_1)
-am__objects_3 = lib_a-arc4random.$(OBJEXT) \
+	$(am__objects_1) $(am__objects_2)
+am__objects_4 = lib_a-arc4random.$(OBJEXT) \
 	lib_a-arc4random_uniform.$(OBJEXT) lib_a-cxa_atexit.$(OBJEXT) \
 	lib_a-cxa_finalize.$(OBJEXT) lib_a-drand48.$(OBJEXT) \
 	lib_a-ecvtbuf.$(OBJEXT) lib_a-efgcvt.$(OBJEXT) \
@@ -128,7 +133,7 @@  am__objects_3 = lib_a-arc4random.$(OBJEXT) \
 	lib_a-wcstoll_r.$(OBJEXT) lib_a-wcstoull.$(OBJEXT) \
 	lib_a-wcstoull_r.$(OBJEXT) lib_a-atoll.$(OBJEXT) \
 	lib_a-llabs.$(OBJEXT) lib_a-lldiv.$(OBJEXT)
-am__objects_4 = lib_a-a64l.$(OBJEXT) lib_a-btowc.$(OBJEXT) \
+am__objects_5 = lib_a-a64l.$(OBJEXT) lib_a-btowc.$(OBJEXT) \
 	lib_a-getopt.$(OBJEXT) lib_a-getsubopt.$(OBJEXT) \
 	lib_a-l64a.$(OBJEXT) lib_a-malign.$(OBJEXT) \
 	lib_a-mbrlen.$(OBJEXT) lib_a-mbrtowc.$(OBJEXT) \
@@ -137,22 +142,23 @@  am__objects_4 = lib_a-a64l.$(OBJEXT) lib_a-btowc.$(OBJEXT) \
 	lib_a-valloc.$(OBJEXT) lib_a-wcrtomb.$(OBJEXT) \
 	lib_a-wcsnrtombs.$(OBJEXT) lib_a-wcsrtombs.$(OBJEXT) \
 	lib_a-wctob.$(OBJEXT)
-am__objects_5 = lib_a-putenv.$(OBJEXT) lib_a-putenv_r.$(OBJEXT) \
+am__objects_6 = lib_a-putenv.$(OBJEXT) lib_a-putenv_r.$(OBJEXT) \
 	lib_a-setenv.$(OBJEXT) lib_a-setenv_r.$(OBJEXT)
-am__objects_6 = lib_a-rpmatch.$(OBJEXT) lib_a-system.$(OBJEXT)
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@am__objects_7 = $(am__objects_4) \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	$(am__objects_5) \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	$(am__objects_6)
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_TRUE@am__objects_7 = $(am__objects_4) \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_TRUE@	$(am__objects_5)
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@am__objects_7 =  \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@	$(am__objects_4)
-@USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_2) \
-@USE_LIBTOOL_FALSE@	$(am__objects_3) $(am__objects_7)
+am__objects_7 = lib_a-rpmatch.$(OBJEXT) lib_a-system.$(OBJEXT)
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@am__objects_8 = $(am__objects_5) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	$(am__objects_6) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	$(am__objects_7)
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_TRUE@am__objects_8 = $(am__objects_5) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_TRUE@	$(am__objects_6)
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@am__objects_8 =  \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@	$(am__objects_5)
+@USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_3) \
+@USE_LIBTOOL_FALSE@	$(am__objects_4) $(am__objects_8)
 lib_a_OBJECTS = $(am_lib_a_OBJECTS)
 LTLIBRARIES = $(noinst_LTLIBRARIES)
-@HAVE_LONG_DOUBLE_TRUE@am__objects_8 = strtold.lo wcstold.lo
-am__objects_9 = __adjust.lo __atexit.lo __call_atexit.lo __exp10.lo \
+@HAVE_LONG_DOUBLE_TRUE@am__objects_9 = strtold.lo wcstold.lo
+@NEWLIB_RETARGETABLE_LOCKING_TRUE@am__objects_10 = lock.lo
+am__objects_11 = __adjust.lo __atexit.lo __call_atexit.lo __exp10.lo \
 	__ten_mu.lo _Exit.lo abort.lo abs.lo aligned_alloc.lo \
 	assert.lo atexit.lo atof.lo atoff.lo atoi.lo atol.lo calloc.lo \
 	div.lo dtoa.lo dtoastub.lo environ.lo envlock.lo eprintf.lo \
@@ -163,28 +169,28 @@  am__objects_9 = __adjust.lo __atexit.lo __call_atexit.lo __exp10.lo \
 	rand_r.lo random.lo realloc.lo reallocf.lo sb_charsets.lo \
 	strtod.lo strtodg.lo strtol.lo strtorx.lo strtoul.lo utoa.lo \
 	wcstod.lo wcstol.lo wcstoul.lo wcstombs.lo wcstombs_r.lo \
-	wctomb.lo wctomb_r.lo $(am__objects_8)
-am__objects_10 = arc4random.lo arc4random_uniform.lo cxa_atexit.lo \
+	wctomb.lo wctomb_r.lo $(am__objects_9) $(am__objects_10)
+am__objects_12 = arc4random.lo arc4random_uniform.lo cxa_atexit.lo \
 	cxa_finalize.lo drand48.lo ecvtbuf.lo efgcvt.lo erand48.lo \
 	jrand48.lo lcong48.lo lrand48.lo mrand48.lo msize.lo mtrim.lo \
 	nrand48.lo rand48.lo seed48.lo srand48.lo strtoll.lo \
 	strtoll_r.lo strtoull.lo strtoull_r.lo wcstoll.lo wcstoll_r.lo \
 	wcstoull.lo wcstoull_r.lo atoll.lo llabs.lo lldiv.lo
-am__objects_11 = a64l.lo btowc.lo getopt.lo getsubopt.lo l64a.lo \
+am__objects_13 = a64l.lo btowc.lo getopt.lo getsubopt.lo l64a.lo \
 	malign.lo mbrlen.lo mbrtowc.lo mbsinit.lo mbsnrtowcs.lo \
 	mbsrtowcs.lo on_exit.lo valloc.lo wcrtomb.lo wcsnrtombs.lo \
 	wcsrtombs.lo wctob.lo
-am__objects_12 = putenv.lo putenv_r.lo setenv.lo setenv_r.lo
-am__objects_13 = rpmatch.lo system.lo
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@am__objects_14 = $(am__objects_11) \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	$(am__objects_12) \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	$(am__objects_13)
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_TRUE@am__objects_14 = $(am__objects_11) \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_TRUE@	$(am__objects_12)
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@am__objects_14 =  \
-@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@	$(am__objects_11)
-@USE_LIBTOOL_TRUE@am_libstdlib_la_OBJECTS = $(am__objects_9) \
-@USE_LIBTOOL_TRUE@	$(am__objects_10) $(am__objects_14)
+am__objects_14 = putenv.lo putenv_r.lo setenv.lo setenv_r.lo
+am__objects_15 = rpmatch.lo system.lo
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@am__objects_16 = $(am__objects_13) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	$(am__objects_14) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_FALSE@	$(am__objects_15)
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_TRUE@am__objects_16 = $(am__objects_13) \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_FALSE@@ELIX_LEVEL_3_TRUE@	$(am__objects_14)
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@am__objects_16 =  \
+@ELIX_LEVEL_1_FALSE@@ELIX_LEVEL_2_TRUE@	$(am__objects_13)
+@USE_LIBTOOL_TRUE@am_libstdlib_la_OBJECTS = $(am__objects_11) \
+@USE_LIBTOOL_TRUE@	$(am__objects_12) $(am__objects_16)
 libstdlib_la_OBJECTS = $(am_libstdlib_la_OBJECTS)
 libstdlib_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
 	$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -367,7 +373,7 @@  GENERAL_SOURCES = __adjust.c __atexit.c __call_atexit.c __exp10.c \
 	quick_exit.c rand.c rand_r.c random.c realloc.c reallocf.c \
 	sb_charsets.c strtod.c strtodg.c strtol.c strtorx.c strtoul.c \
 	utoa.c wcstod.c wcstol.c wcstoul.c wcstombs.c wcstombs_r.c \
-	wctomb.c wctomb_r.c $(am__append_1)
+	wctomb.c wctomb_r.c $(am__append_1) $(am__append_2)
 @NEWLIB_NANO_MALLOC_FALSE@MALIGNR = malignr
 @NEWLIB_NANO_MALLOC_TRUE@MALIGNR = nano-malignr
 @NEWLIB_NANO_MALLOC_FALSE@MALLOPTR = malloptr
@@ -1002,6 +1008,12 @@  lib_a-wcstold.o: wcstold.c
 lib_a-wcstold.obj: wcstold.c
 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-wcstold.obj `if test -f 'wcstold.c'; then $(CYGPATH_W) 'wcstold.c'; else $(CYGPATH_W) '$(srcdir)/wcstold.c'; fi`
 
+lib_a-lock.o: lock.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-lock.o `test -f 'lock.c' || echo '$(srcdir)/'`lock.c
+
+lib_a-lock.obj: lock.c
+	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-lock.obj `if test -f 'lock.c'; then $(CYGPATH_W) 'lock.c'; else $(CYGPATH_W) '$(srcdir)/lock.c'; fi`
+
 lib_a-arc4random.o: arc4random.c
 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-arc4random.o `test -f 'arc4random.c' || echo '$(srcdir)/'`arc4random.c
 
diff --git a/newlib/libc/stdlib/lock.c b/newlib/libc/stdlib/lock.c
new file mode 100644
index 0000000000000000000000000000000000000000..3349ef36d7c7b0dfce065de3c8df4fe8eb05c002
--- /dev/null
+++ b/newlib/libc/stdlib/lock.c
@@ -0,0 +1,130 @@ 
+/*
+FUNCTION
+<<__retarget_lock_init>>, <<__retarget_lock_init_recursive>>, <<__retarget_lock_close>>, <<__retarget_lock_close_recursive>>, <<__retarget_lock_acquire>>, <<__retarget_lock_acquire_recursive>>, <<__retarget_lock_try_acquire>>, <<__retarget_lock_try_acquire_recursive>>, <<__retarget_lock_release>>, <<__retarget_lock_release_recursive>>---locking routines
+
+INDEX
+	__retarget_lock_init
+INDEX
+	__retarget_lock_init_recursive
+INDEX
+	__retarget_lock_close
+INDEX
+	__retarget_lock_close_recursive
+INDEX
+	__retarget_lock_acquire
+INDEX
+	__retarget_lock_acquire_recursive
+INDEX
+	__retarget_lock_try_acquire
+INDEX
+	__retarget_lock_try_acquire_recursive
+INDEX
+	__retarget_lock_release
+INDEX
+	__retarget_lock_release_recursive
+
+ANSI_SYNOPSIS
+	#include <lock.h>
+	void __retarget_lock_init (_LOCK_T * <[lock_ptr]>);
+	void __retarget_lock_init_recursive (_LOCK_T * <[lock_ptr]>);
+	void __retarget_lock_close (_LOCK_T <[lock]>);
+	void __retarget_lock_close_recursive (_LOCK_T <[lock]>);
+	void __retarget_lock_acquire (_LOCK_T <[lock]>);
+	void __retarget_lock_acquire_recursive (_LOCK_T <[lock]>);
+	int __retarget_lock_try_acquire (_LOCK_T <[lock]>);
+	int __retarget_lock_try_acquire_recursive (_LOCK_T <[lock]>);
+	void __retarget_lock_release (_LOCK_T <[lock]>);
+	void __retarget_lock_release_recursive (_LOCK_T <[lock]>);
+
+TRAD_SYNOPSIS
+	void __retarget_lock_init(<[lock_ptr]>)
+	_LOCK_T * <[lock_ptr]>;
+
+	void __retarget_lock_init_recursive(<[lock_ptr]>)
+	_LOCK_T * <[lock_ptr]>;
+
+	void __retarget_lock_close(<[lock]>)
+	_LOCK_T <[lock]>;
+
+	void __retarget_lock_close_recursive(<[lock]>)
+	_LOCK_T <[lock]>;
+
+	void __retarget_lock_acquire(<[lock]>)
+	_LOCK_T <[lock]>;
+
+	void __retarget_lock_acquire_recursive(<[lock]>)
+	_LOCK_T <[lock]>;
+
+	int __retarget_lock_try_acquire(<[lock]>)
+	_LOCK_T <[lock]>;
+
+	int __retarget_lock_try_acquire_recursive(<[lock]>)
+	_LOCK_T <[lock]>;
+
+	void __retarget_lock_release(<[lock]>)
+	_LOCK_T <[lock]>;
+
+	void __retarget_lock_release_recursive(<[lock]>)
+	_LOCK_T <[lock]>;
+
+DESCRIPTION
+These empty functions are used for locking to allow applications to retarget
+them.  They are used in place of the default dummy lock macros when newlib
+is configured with --enable-newlib-retargetable-locking.
+*/
+
+/* dummy lock routines for single-threaded apps */
+
+#include <sys/lock.h>
+
+void _ATTRIBUTE((__weak__))
+__retarget_lock_init (_LOCK_T *lock)
+{
+}
+
+void _ATTRIBUTE((__weak__))
+__retarget_lock_init_recursive(_LOCK_T *lock)
+{
+}
+
+void _ATTRIBUTE((__weak__))
+__retarget_lock_close(_LOCK_T lock)
+{
+}
+
+void _ATTRIBUTE((__weak__))
+__retarget_lock_close_recursive(_LOCK_T lock)
+{
+}
+
+void _ATTRIBUTE((__weak__))
+__retarget_lock_acquire (_LOCK_T lock)
+{
+}
+
+void _ATTRIBUTE((__weak__))
+__retarget_lock_acquire_recursive (_LOCK_T lock)
+{
+}
+
+int _ATTRIBUTE((__weak__))
+__retarget_lock_try_acquire(_LOCK_T lock)
+{
+  return 1;
+}
+
+int _ATTRIBUTE((__weak__))
+__retarget_lock_try_acquire_recursive(_LOCK_T lock)
+{
+  return 1;
+}
+
+void _ATTRIBUTE((__weak__))
+__retarget_lock_release (_LOCK_T lock)
+{
+}
+
+void _ATTRIBUTE((__weak__))
+__retarget_lock_release_recursive (_LOCK_T lock)
+{
+}
diff --git a/newlib/newlib.hin b/newlib/newlib.hin
index d03dfac0eea6a8917a92b8f0f3584c2cd42b9388..397bc9b96eafddace3a75be509157040654b6fde 100644
--- a/newlib/newlib.hin
+++ b/newlib/newlib.hin
@@ -82,6 +82,9 @@ 
 /* Define if small footprint nano-formatted-IO implementation used.  */
 #undef _NANO_FORMATTED_IO
 
+/* Define if using retargetable functions for default lock routines.  */
+#undef _RETARGETABLE_LOCKING
+
 /*
  * Iconv encodings enabled ("to" direction)
  */