diff mbox

[newlib] Allow locking routine to be retargeted

Message ID cb017b6f-5d89-9bd5-884c-bb67146f8245@foss.arm.com
State Superseded
Headers show

Commit Message

Thomas Preudhomme Jan. 12, 2017, 10:51 a.m. UTC
On 11/01/17 19:14, Freddie Chopin wrote:
> On Wed, 2017-01-11 at 17:48 +0000, Thomas Preudhomme wrote:

>> Very well. How about the attached patch?

>

> Hmm... Trying to apply that to newlib-2.5.0 fails with:

>

> (Stripping trailing CRs from patch; use --binary to disable.)

> patching file newlib/configure

> Hunk #1 succeeded at 802 (offset 4 lines).

> Hunk #2 succeeded at 1474 (offset 4 lines).

> Hunk #3 succeeded at 2476 (offset 4 lines).

> Hunk #4 FAILED at 11790.

> Hunk #5 FAILED at 11896.

> Hunk #6 succeeded at 12469 (offset 34 lines).

> 2 out of 6 hunks FAILED -- saving rejects to file newlib/configure.rej


My bad. I've rebased it on latest master branch. Please find the patch attached.

Best regards,

Thomas

Comments

Freddie Chopin Jan. 12, 2017, 4:20 p.m. UTC | #1
On Thu, 2017-01-12 at 10:51 +0000, Thomas Preudhomme wrote:
> My bad. I've rebased it on latest master branch. Please find the

> patch attached.


Thanks! Now it builds fine (;

In my very limited testing it seems to work very nicely and the idea of
using "struct _lock;" is very clever, as it allows me to do the
retargeting in a very clean way:

--- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 ---

struct _lock : public distortos::Mutex
{
	using Mutex::Mutex;
};

_lock _lock___sinit_lock {distortos::Mutex::Type::recursive, distortos::Mutex::Protocol::priorityInheritance};
_lock _lock___sfp_lock {distortos::Mutex::Type::recursive, distortos::Mutex::Protocol::priorityInheritance};
_lock _lock___atexit_lock {distortos::Mutex::Type::recursive, distortos::Mutex::Protocol::priorityInheritance};
_lock _lock___malloc_lock_object {distortos::Mutex::Type::recursive, distortos::Mutex::Protocol::priorityInheritance};

void __retarget_lock_init (_LOCK_T *lock)
{
	*lock = new _lock {distortos::Mutex::Type::normal, distortos::Mutex::Protocol::priorityInheritance};
}

void __retarget_lock_close(_LOCK_T lock)
{
	delete lock;
}

void __retarget_lock_acquire (_LOCK_T lock)
{
	lock->lock();
}

void __retarget_lock_release (_LOCK_T lock)
{
	lock->unlock();
}

...

--- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 ---

But I still see a big issue with the weak objects that you provided in
lock.c... The problem here is that now the user can redefine just 3 of
them, so the last one will be taken from the weak definition that you
provided. There will be no error/warning during compilation or linking.
This will of course fail terribly during run-time due to mismatched
types... While this may seem a bit unlikely at the first glance, the
possible scenario that would lead to that is:
1. today newlib adds this very cool feature and adds weak objects for
all used locks.
2. after some time RTOS developers start to support it and also provide
their own versions of the locks needed by newlib.
3. after some more time newlib adds another lock somewhere, along with
the object.
At this moment all users of code created during step 2 linked with
newlib version from step 3 will result in undefined behaviour whenever
the new lock is used...

You also missed some of the locks that are used by newlib:
newlib/libc/posix/telldir.c:__LOCK_INIT(static, dd_hash_lock);
newlib/libc/time/tzlock.c:__LOCK_INIT(static, __tz_lock_object);
newlib/libc/stdlib/quick_exit.c:__LOCK_INIT(static, atexit_mutex);
newlib/libc/stdlib/envlock.c:__LOCK_INIT_RECURSIVE(static, __env_lock_object);

Maybe it would be somehow possible to bind all of the objects (and
maybe even functions) together, so that when user provides just one
definition, all other weak definitions will be immediately disabled?
This way the user would either have to provide all or none, without an
option to only provide some of the objects/functions. This is my only
concern - I have nothing against providing weak definitions, but the
possibility of overriding only some of the objects is a bit disturbing.

Regards,
FCh
Thomas Preudhomme Jan. 12, 2017, 4:55 p.m. UTC | #2
Hi Freddie,

On 12/01/17 16:20, Freddie Chopin wrote:
> On Thu, 2017-01-12 at 10:51 +0000, Thomas Preudhomme wrote:

>> My bad. I've rebased it on latest master branch. Please find the

>> patch attached.

>

> Thanks! Now it builds fine (;

>

> In my very limited testing it seems to work very nicely and the idea of

> using "struct _lock;" is very clever, as it allows me to do the

> retargeting in a very clean way:

>

> --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 ---

>

> struct _lock : public distortos::Mutex

> {

> 	using Mutex::Mutex;

> };

>

> _lock _lock___sinit_lock {distortos::Mutex::Type::recursive, distortos::Mutex::Protocol::priorityInheritance};

> _lock _lock___sfp_lock {distortos::Mutex::Type::recursive, distortos::Mutex::Protocol::priorityInheritance};

> _lock _lock___atexit_lock {distortos::Mutex::Type::recursive, distortos::Mutex::Protocol::priorityInheritance};

> _lock _lock___malloc_lock_object {distortos::Mutex::Type::recursive, distortos::Mutex::Protocol::priorityInheritance};

>

> void __retarget_lock_init (_LOCK_T *lock)

> {

> 	*lock = new _lock {distortos::Mutex::Type::normal, distortos::Mutex::Protocol::priorityInheritance};

> }

>

> void __retarget_lock_close(_LOCK_T lock)

> {

> 	delete lock;

> }

>

> void __retarget_lock_acquire (_LOCK_T lock)

> {

> 	lock->lock();

> }

>

> void __retarget_lock_release (_LOCK_T lock)

> {

> 	lock->unlock();

> }

>

> ...

>

> --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 ---

>

> But I still see a big issue with the weak objects that you provided in

> lock.c... The problem here is that now the user can redefine just 3 of

> them, so the last one will be taken from the weak definition that you

> provided. There will be no error/warning during compilation or linking.

> This will of course fail terribly during run-time due to mismatched

> types... While this may seem a bit unlikely at the first glance, the

> possible scenario that would lead to that is:

> 1. today newlib adds this very cool feature and adds weak objects for

> all used locks.

> 2. after some time RTOS developers start to support it and also provide

> their own versions of the locks needed by newlib.

> 3. after some more time newlib adds another lock somewhere, along with

> the object.

> At this moment all users of code created during step 2 linked with

> newlib version from step 3 will result in undefined behaviour whenever

> the new lock is used...

>

> You also missed some of the locks that are used by newlib:

> newlib/libc/posix/telldir.c:__LOCK_INIT(static, dd_hash_lock);

> newlib/libc/time/tzlock.c:__LOCK_INIT(static, __tz_lock_object);

> newlib/libc/stdlib/quick_exit.c:__LOCK_INIT(static, atexit_mutex);

> newlib/libc/stdlib/envlock.c:__LOCK_INIT_RECURSIVE(static, __env_lock_object);

>

> Maybe it would be somehow possible to bind all of the objects (and

> maybe even functions) together, so that when user provides just one

> definition, all other weak definitions will be immediately disabled?

> This way the user would either have to provide all or none, without an

> option to only provide some of the objects/functions. This is my only

> concern - I have nothing against providing weak definitions, but the

> possibility of overriding only some of the objects is a bit disturbing.


That's a very valid concern indeed. Thanks a lot for this feedback. I'll think 
about it and see if I can come up with a solution.

Best regards,

Thomas
Thomas Preudhomme Jan. 13, 2017, 11:25 a.m. UTC | #3
On 12/01/17 16:55, Thomas Preudhomme wrote:
> Hi Freddie,

>

> On 12/01/17 16:20, Freddie Chopin wrote:

>> On Thu, 2017-01-12 at 10:51 +0000, Thomas Preudhomme wrote:

>>> My bad. I've rebased it on latest master branch. Please find the

>>> patch attached.

>>

>> Thanks! Now it builds fine (;

>>

>> In my very limited testing it seems to work very nicely and the idea of

>> using "struct _lock;" is very clever, as it allows me to do the

>> retargeting in a very clean way:

>>

>> --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 ---

>>

>> struct _lock : public distortos::Mutex

>> {

>>     using Mutex::Mutex;

>> };

>>

>> _lock _lock___sinit_lock {distortos::Mutex::Type::recursive,

>> distortos::Mutex::Protocol::priorityInheritance};

>> _lock _lock___sfp_lock {distortos::Mutex::Type::recursive,

>> distortos::Mutex::Protocol::priorityInheritance};

>> _lock _lock___atexit_lock {distortos::Mutex::Type::recursive,

>> distortos::Mutex::Protocol::priorityInheritance};

>> _lock _lock___malloc_lock_object {distortos::Mutex::Type::recursive,

>> distortos::Mutex::Protocol::priorityInheritance};

>>

>> void __retarget_lock_init (_LOCK_T *lock)

>> {

>>     *lock = new _lock {distortos::Mutex::Type::normal,

>> distortos::Mutex::Protocol::priorityInheritance};

>> }

>>

>> void __retarget_lock_close(_LOCK_T lock)

>> {

>>     delete lock;

>> }

>>

>> void __retarget_lock_acquire (_LOCK_T lock)

>> {

>>     lock->lock();

>> }

>>

>> void __retarget_lock_release (_LOCK_T lock)

>> {

>>     lock->unlock();

>> }

>>

>> ...

>>

>> --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 --- >8 ---

>>

>> But I still see a big issue with the weak objects that you provided in

>> lock.c... The problem here is that now the user can redefine just 3 of

>> them, so the last one will be taken from the weak definition that you

>> provided. There will be no error/warning during compilation or linking.

>> This will of course fail terribly during run-time due to mismatched

>> types... While this may seem a bit unlikely at the first glance, the

>> possible scenario that would lead to that is:

>> 1. today newlib adds this very cool feature and adds weak objects for

>> all used locks.

>> 2. after some time RTOS developers start to support it and also provide

>> their own versions of the locks needed by newlib.

>> 3. after some more time newlib adds another lock somewhere, along with

>> the object.

>> At this moment all users of code created during step 2 linked with

>> newlib version from step 3 will result in undefined behaviour whenever

>> the new lock is used...

>>

>> You also missed some of the locks that are used by newlib:

>> newlib/libc/posix/telldir.c:__LOCK_INIT(static, dd_hash_lock);

>> newlib/libc/time/tzlock.c:__LOCK_INIT(static, __tz_lock_object);

>> newlib/libc/stdlib/quick_exit.c:__LOCK_INIT(static, atexit_mutex);

>> newlib/libc/stdlib/envlock.c:__LOCK_INIT_RECURSIVE(static, __env_lock_object);

>>

>> Maybe it would be somehow possible to bind all of the objects (and

>> maybe even functions) together, so that when user provides just one

>> definition, all other weak definitions will be immediately disabled?

>> This way the user would either have to provide all or none, without an

>> option to only provide some of the objects/functions. This is my only

>> concern - I have nothing against providing weak definitions, but the

>> possibility of overriding only some of the objects is a bit disturbing.

>

> That's a very valid concern indeed. Thanks a lot for this feedback. I'll think

> about it and see if I can come up with a solution.


Actually the dummy function and lock do not have to be weakly defined to be able 
to be retargeted. Members of a static library only gets pulled if they solve an 
undefined reference. Otherwise, they are ignored.

All we need is for the retargeted functions and locks provided by a platform to 
be linked before newlib. Then if all functions and locks are retargeted the 
lock.o member with all dummy definitions in newlib static library is ignored, 
otherwise it would be pulled in during the link and ld would give a linking 
error because some of the lock and function would be defined twice.

How does that sounds?

Best regards,

Thomas
diff mbox

Patch

diff --git a/newlib/configure b/newlib/configure
index 2ac07fe06bfc795d94ba36d0061e4f8135146125..de28c25b3c4aaeed14b6d0ee8354fdd5c5c3115a 100755
--- a/newlib/configure
+++ b/newlib/configure
@@ -802,6 +802,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
@@ -1473,6 +1474,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
@@ -2474,6 +2476,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 ||
@@ -11780,7 +11794,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11783 "configure"
+#line 11797 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11886,7 +11900,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11889 "configure"
+#line 11903 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12455,6 +12469,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 bfaf038c7f495d32d05ae8caff0172f464895ffe..354c07ca580edf75da59fb858ca2c434e0b1a4e9 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
@@ -458,6 +469,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 4dc4d1bf703f388ecd3b4e0d8bef6786f7995021..dabe44fd98d74a2e029a22a217953dd52575736f 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..9a8e2528c79a89d5807da8c4bb0e65151870bf42 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,46 @@  typedef int _LOCK_RECURSIVE_T;
 #define __lock_release(lock) (_CAST_VOID 0)
 #define __lock_release_recursive(lock) (_CAST_VOID 0)
 
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct _lock;
+typedef struct _lock * _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)
+
+#ifdef __cplusplus
+}
+#endif
+
+#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..c0b8a173a3bae16cd91d231dff7de2b4bb8cd9e3
--- /dev/null
+++ b/newlib/libc/stdlib/lock.c
@@ -0,0 +1,108 @@ 
+/*
+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]>);
+
+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>
+
+struct _lock {
+  char unused;
+};
+
+struct _lock _ATTRIBUTE((__weak__)) _lock___sinit_lock;
+struct _lock _ATTRIBUTE((__weak__)) _lock___sfp_lock;
+struct _lock _ATTRIBUTE((__weak__)) _lock___atexit_lock;
+struct _lock _ATTRIBUTE((__weak__)) _lock___malloc_lock_object;
+
+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)
  */