Allow locking routine to be retargeted

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 link time that you know which system you are
targeting.

This patch adds a new configure option
--enable-newlib-retargetable-locking to use dummy empty 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. To allow for any size of lock, the _LOCK_T type is
changed into pointer to struct _lock and the _init function are tasked
with allocating the locks. The platform being targeted must provide the
static locks. A dummy implementation of the locking routines and static
lock is provided for single-threaded applications to link successfully
out of the box.

To ensure that the behavior is consistent (either no locking whatsoever
or working locking), the dummy implementation is strongly defined such
that a partial retargeting will cause a doubly defined link error.
Indeed, the linker will only pull in the file providing the dummy
implementation if it cannot find an implementation for one of the
routine or lock.
This commit is contained in:
Thomas Preud'homme 2016-10-25 17:38:19 +01:00 committed by Jeff Johnston
parent fa55c610fa
commit bd54749095
10 changed files with 316 additions and 14 deletions

25
newlib/configure vendored
View File

@ -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" \

View File

@ -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

32
newlib/libc/configure vendored
View File

@ -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

View File

@ -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)

View File

@ -3,10 +3,13 @@
/* dummy lock routines for single-threaded aps */
#include <newlib.h>
#include <_ansi.h>
#if !defined(_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 /* !defined(_RETARGETABLE_LOCKING) */
#endif /* __SYS_LOCK_H__ */

View File

@ -6,6 +6,11 @@ INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
LIB_SOURCES = __dprintf.c unctrl.c ffs.c init.c fini.c
if NEWLIB_RETARGETABLE_LOCKING
LIB_SOURCES += \
lock.c
endif
libmisc_la_LDFLAGS = -Xcompiler -nostdlib
if USE_LIBTOOL
@ -21,5 +26,5 @@ endif # USE_LIBTOOL
include $(srcdir)/../../Makefile.shared
CHEWOUT_FILES = unctrl.def ffs.def
CHEWOUT_FILES = unctrl.def lock.def ffs.def
CHAPTERS = misc.tex

View File

@ -53,6 +53,9 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@NEWLIB_RETARGETABLE_LOCKING_TRUE@am__append_1 = \
@NEWLIB_RETARGETABLE_LOCKING_TRUE@ lock.c
DIST_COMMON = $(srcdir)/../../Makefile.shared $(srcdir)/Makefile.in \
$(srcdir)/Makefile.am
subdir = misc
@ -72,14 +75,19 @@ LIBRARIES = $(noinst_LIBRARIES)
ARFLAGS = cru
lib_a_AR = $(AR) $(ARFLAGS)
lib_a_LIBADD =
am__objects_1 = lib_a-__dprintf.$(OBJEXT) lib_a-unctrl.$(OBJEXT) \
lib_a-ffs.$(OBJEXT) lib_a-init.$(OBJEXT) lib_a-fini.$(OBJEXT)
@USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_1)
@NEWLIB_RETARGETABLE_LOCKING_TRUE@am__objects_1 = \
@NEWLIB_RETARGETABLE_LOCKING_TRUE@ lib_a-lock.$(OBJEXT)
am__objects_2 = lib_a-__dprintf.$(OBJEXT) lib_a-unctrl.$(OBJEXT) \
lib_a-ffs.$(OBJEXT) lib_a-init.$(OBJEXT) lib_a-fini.$(OBJEXT) \
$(am__objects_1)
@USE_LIBTOOL_FALSE@am_lib_a_OBJECTS = $(am__objects_2)
lib_a_OBJECTS = $(am_lib_a_OBJECTS)
LTLIBRARIES = $(noinst_LTLIBRARIES)
libmisc_la_LIBADD =
am__objects_2 = __dprintf.lo unctrl.lo ffs.lo init.lo fini.lo
@USE_LIBTOOL_TRUE@am_libmisc_la_OBJECTS = $(am__objects_2)
@NEWLIB_RETARGETABLE_LOCKING_TRUE@am__objects_3 = lock.lo
am__objects_4 = __dprintf.lo unctrl.lo ffs.lo init.lo fini.lo \
$(am__objects_3)
@USE_LIBTOOL_TRUE@am_libmisc_la_OBJECTS = $(am__objects_4)
libmisc_la_OBJECTS = $(am_libmisc_la_OBJECTS)
libmisc_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@ -252,7 +260,7 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AUTOMAKE_OPTIONS = cygnus
INCLUDES = $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS)
LIB_SOURCES = __dprintf.c unctrl.c ffs.c init.c fini.c
LIB_SOURCES = __dprintf.c unctrl.c ffs.c init.c fini.c $(am__append_1)
libmisc_la_LDFLAGS = -Xcompiler -nostdlib
@USE_LIBTOOL_TRUE@noinst_LTLIBRARIES = libmisc.la
@USE_LIBTOOL_TRUE@libmisc_la_SOURCES = $(LIB_SOURCES)
@ -271,7 +279,7 @@ DOCBOOK_CHEW = ${top_srcdir}/../doc/makedocbook.py
DOCBOOK_OUT_FILES = $(CHEWOUT_FILES:.def=.xml)
DOCBOOK_CHAPTERS = $(CHAPTERS:.tex=.xml)
CLEANFILES = $(CHEWOUT_FILES) $(CHEWOUT_FILES:.def=.ref) $(DOCBOOK_OUT_FILES)
CHEWOUT_FILES = unctrl.def ffs.def
CHEWOUT_FILES = unctrl.def lock.def ffs.def
CHAPTERS = misc.tex
all: all-am
@ -372,6 +380,12 @@ lib_a-fini.o: fini.c
lib_a-fini.obj: fini.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(lib_a_CFLAGS) $(CFLAGS) -c -o lib_a-fini.obj `if test -f 'fini.c'; then $(CYGPATH_W) 'fini.c'; else $(CYGPATH_W) '$(srcdir)/fini.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`
mostlyclean-libtool:
-rm -f *.lo

157
newlib/libc/misc/lock.c Normal file
View File

@ -0,0 +1,157 @@
/*
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
__lock___sinit_recursive_mutex
INDEX
__lock___sfp_recursive_mutex
INDEX
__lock___atexit_recursive_mutex
INDEX
__lock___at_quick_exit_mutex
INDEX
__lock___malloc_recursive_mutex
INDEX
__lock___env_recursive_mutex
INDEX
__lock___tz_mutex
INDEX
__lock___dd_hash_mutex
INDEX
__lock___arc4random_mutex
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>
struct __lock __lock___sinit_recursive_mutex;
struct __lock __lock___sfp_recursive_mutex;
struct __lock __lock___atexit_recursive_mutex;
struct __lock __lock___at_quick_exit_mutex;
struct __lock __lock___malloc_recursive_mutex;
struct __lock __lock___env_recursive_mutex;
struct __lock __lock___tz_mutex;
struct __lock __lock___dd_hash_mutex;
struct __lock __lock___arc4random_mutex;
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
Newlib was configured to allow the target platform to provide the locking
routines and static locks at link time. As such, a dummy default
implementation of these routines and static locks is provided for
single-threaded application to link successfully out of the box on bare-metal
systems.
For multi-threaded applications the target platform is required to provide
an implementation for @strong{all} these routines and static locks. If some
routines or static locks are missing, the link will fail with doubly defined
symbols.
PORTABILITY
These locking routines and static lock are newlib-specific. Supporting OS
subroutines are required for linking multi-threaded applications.
*/
/* dummy lock routines and static locks for single-threaded apps */
#ifndef __SINGLE_THREAD__
#include <sys/lock.h>
struct __lock {
char unused;
};
struct __lock __lock___sinit_recursive_mutex;
struct __lock __lock___sfp_recursive_mutex;
struct __lock __lock___atexit_recursive_mutex;
struct __lock __lock___at_quick_exit_mutex;
struct __lock __lock___malloc_recursive_mutex;
struct __lock __lock___env_recursive_mutex;
struct __lock __lock___tz_mutex;
struct __lock __lock___dd_hash_mutex;
struct __lock __lock___arc4random_mutex;
void
__retarget_lock_init (_LOCK_T *lock)
{
}
void
__retarget_lock_init_recursive(_LOCK_T *lock)
{
}
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)
{
return 1;
}
int
__retarget_lock_try_acquire_recursive(_LOCK_T lock)
{
return 1;
}
void
__retarget_lock_release (_LOCK_T lock)
{
}
void
__retarget_lock_release_recursive (_LOCK_T lock)
{
}
#endif /* !defined(__SINGLE_THREAD__) */

View File

@ -4,11 +4,15 @@ This chapter describes miscellaneous routines not covered elsewhere.
@menu
* ffs:: Return first bit set in a word
* __retarget_lock_init:: Retargetable locking routines
* unctrl:: Return printable representation of a character
@end menu
@page
@include misc/ffs.def
@page
@include misc/lock.def
@page
@include misc/unctrl.def

View File

@ -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)
*/