-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
newlib: Initial thread-safe implementation #4529
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
MODULE = newlib_thread_safe | ||
|
||
include $(RIOTBASE)/Makefile.base |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# define the compile test file | ||
define __has_reent_small_test | ||
#include <sys/reent.h>\n | ||
#ifndef _REENT_SMALL\n | ||
#error wasting 1KB\n | ||
#endif | ||
endef | ||
|
||
# compile the tests | ||
__has_reent := $(shell echo "\#include <sys/reent.h>\n" | $(CC) -E $(CFLAGS) $(INCLUDES) - 2> /dev/null > /dev/null; echo $$?) | ||
__has_reent_small := $(shell echo "$(__has_reent_small_test)" | $(CC) -E $(CFLAGS) $(INCLUDES) - 2> /dev/null > /dev/null; echo $$?) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here it isn't possible to remove the \n. Use printf instead of echo (-e)? |
||
|
||
# check if we use REENT_SMALL | ||
ifeq (0, $(__has_reent)) | ||
ifeq (0, $(__has_reent_small)) | ||
export USE_NEWLIB_THREAD_SAFE := 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the export doesn't generate an environment variable. |
||
else | ||
$(shell $(COLOR_ECHO) "\n$(COLOR_YELLOW)_REENT_SMALL not defined, thread-safe newlib disabled!\n$(COLOR_RESET)" 1>&2) | ||
endif | ||
else | ||
$(shell $(COLOR_ECHO) "\n$(COLOR_YELLOW)MODULE_NEWLIB_THREAD_SAFE defined but <sys/reent.h> not found in toolchain path, thread-safe newlib is disabled!\n\n$(COLOR_RESET)\n" 1>&2) | ||
endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* Copyright (C) 2016 Engineering-Spirit | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser General | ||
* Public License v2.1. See the file LICENSE in the top level directory for more | ||
* details. | ||
*/ | ||
|
||
/** | ||
* @ingroup sys_newlib | ||
* @{ | ||
* | ||
* @file | ||
* @brief Newlib thread-safe env implementation | ||
* | ||
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include "newlib_lock.h" | ||
|
||
#if USE_NEWLIB_THREAD_SAFE | ||
static recursive_mutex_t _env = RECURSIVE_MUTEX_INIT; | ||
#endif | ||
|
||
/** | ||
* @brief __env_lock needs to provide recursive mutex locking | ||
*/ | ||
void __env_lock(struct _reent *_r) | ||
{ | ||
(void) _r; | ||
|
||
/* TODO another way would be to avoid rescheduling other tasks */ | ||
#if USE_NEWLIB_THREAD_SAFE | ||
__recursive_lock(&_env); | ||
#endif | ||
} | ||
|
||
void __env_unlock(struct _reent *_r) | ||
{ | ||
(void) _r; | ||
|
||
#if USE_NEWLIB_THREAD_SAFE | ||
__recursive_unlock(&_env); | ||
#endif | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* Copyright (C) 2016 Engineering-Spirit | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser General | ||
* Public License v2.1. See the file LICENSE in the top level directory for more | ||
* details. | ||
*/ | ||
|
||
/** | ||
* @ingroup sys_newlib | ||
* @{ | ||
* | ||
* @file | ||
* @brief Newlib thread-safe malloc implementation | ||
* | ||
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include "newlib_lock.h" | ||
|
||
#if USE_NEWLIB_THREAD_SAFE | ||
static recursive_mutex_t _malloc = RECURSIVE_MUTEX_INIT; | ||
#endif | ||
|
||
/** | ||
* @brief __malloc_lock needs to provide recursive mutex locking | ||
*/ | ||
void __malloc_lock(struct _reent *_r) | ||
{ | ||
(void) _r; | ||
|
||
/* TODO another way would be to avoid rescheduling other tasks */ | ||
#if USE_NEWLIB_THREAD_SAFE | ||
__recursive_lock(&_malloc); | ||
#endif | ||
} | ||
|
||
void __malloc_unlock(struct _reent *_r) | ||
{ | ||
(void) _r; | ||
|
||
#if USE_NEWLIB_THREAD_SAFE | ||
__recursive_unlock(&_malloc); | ||
#endif | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* Copyright (C) 2016 Engineering-Spirit | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser General | ||
* Public License v2.1. See the file LICENSE in the top level directory for more | ||
* details. | ||
*/ | ||
|
||
/** | ||
* @ingroup sys_newlib | ||
* @{ | ||
* | ||
* @file | ||
* @brief Newlib thread-safe recursive implementation | ||
* | ||
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include <assert.h> | ||
|
||
#include "arch/irq_arch.h" | ||
#include "newlib_lock.h" | ||
|
||
void __recursive_init(recursive_mutex_t *rm) | ||
{ | ||
recursive_mutex_t empty_mutex = RECURSIVE_MUTEX_INIT; | ||
*rm = empty_mutex; | ||
} | ||
|
||
/** | ||
* @brief __recursive_lock needs to provide recursive mutex locking | ||
*/ | ||
void __recursive_lock(recursive_mutex_t *rm) | ||
{ | ||
/* TODO another way would be to avoid rescheduling other tasks */ | ||
#if USE_NEWLIB_THREAD_SAFE | ||
|
||
/* check if the mutex lock is not called from an interrupt */ | ||
assert(!(irq_arch_in())); | ||
|
||
/* try to lock the recursive mutex */ | ||
switch (mutex_trylock(&rm->mutex)) | ||
{ | ||
case 0: | ||
/* mutex is already locked */ | ||
if (rm->owner != thread_getpid()) { | ||
/* we are not the owner, so we wait till it's released and | ||
* fall-trough the case statement */ | ||
mutex_lock(&rm->mutex); | ||
} | ||
|
||
/* fall-trough */ | ||
|
||
case 1: | ||
/* mutex now locked by us */ | ||
atomic_inc(&rm->recursion); | ||
rm->owner = thread_getpid(); | ||
break; | ||
} | ||
#else | ||
(void) rm; | ||
#endif | ||
} | ||
|
||
void __recursive_unlock(recursive_mutex_t *rm) | ||
{ | ||
#if USE_NEWLIB_THREAD_SAFE | ||
/* check if the mutex unlock is not called from an interrupt */ | ||
assert(!(irq_arch_in())); | ||
|
||
/* check if the unlocking thread is the same as the locking thread */ | ||
assert(rm->owner == thread_getpid()); | ||
|
||
/* decrease the recursion counter */ | ||
if (atomic_dec(&rm->recursion) == 1) { | ||
/* we just released the last recursion lock call */ | ||
|
||
rm->owner = KERNEL_PID_UNDEF; | ||
mutex_unlock(&rm->mutex); | ||
} | ||
#else | ||
(void) rm; | ||
#endif | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* Copyright (C) 2016 Engineering-Spirit | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser General | ||
* Public License v2.1. See the file LICENSE in the top level directory for more | ||
* details. | ||
*/ | ||
|
||
/** | ||
* @ingroup sys_newlib | ||
* @{ | ||
* | ||
* @file | ||
* @brief Newlib thread-safe recursive lock implementation | ||
* | ||
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl> | ||
* | ||
* @} | ||
*/ | ||
|
||
#ifndef THREAD_SAFE_NEWLIB_LOCK_H_ | ||
#define THREAD_SAFE_NEWLIB_LOCK_H_ | ||
|
||
#include <sys/reent.h> | ||
|
||
#include <thread.h> | ||
#include <mutex.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @brief An recursive mutex implementation that can be used for newlib's | ||
* thread-safe implementation | ||
*/ | ||
typedef struct recursive_mutex | ||
{ | ||
volatile kernel_pid_t owner; /**< owner of the recursive mutex */ | ||
atomic_int_t recursion; /**< number of recursive lock calls */ | ||
mutex_t mutex; /**< mutex that is locked recursively */ | ||
} recursive_mutex_t; | ||
|
||
/** | ||
* @brief Initialization values for a recursive mutex | ||
*/ | ||
#define RECURSIVE_MUTEX_INIT { KERNEL_PID_UNDEF, { 0 }, MUTEX_INIT } | ||
|
||
/** | ||
* @brief initialize the recursive mutex if it's not yet initialized | ||
* | ||
* @param[in] rm recursive mutex structure | ||
*/ | ||
void __recursive_init(recursive_mutex_t *rm); | ||
|
||
/** | ||
* @brief lock the mutex recursively, try to lock the mutex. | ||
* - If the mutex is free claim ownership. | ||
* - If the mutex is locked by us already; increase the recursion count | ||
* - If the mutex is locked by another task; wait for the mutex to be freed | ||
* | ||
* @param[in] rm recursive mutex structure | ||
*/ | ||
void __recursive_lock(recursive_mutex_t *rm); | ||
|
||
/** | ||
* @brief release the mutex recursively, if the last lock is freeed release the mutex | ||
* | ||
* @param[in] rm recursive mutex structure | ||
*/ | ||
void __recursive_unlock(recursive_mutex_t *rm); | ||
|
||
#ifdef __cplusplus | ||
}; | ||
#endif | ||
|
||
#endif /* THREAD_SAFE_NEWLIB_LOCK_H_ */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the \n results in an error: "stdin>:1:23: error: extra tokens at end of #include directive [-Werror]", adding -e to the echo command solves it ( -e: enable interpretation of backslash escapes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
echo is really the worst way to get a text string in shell scripts. There
is no standard specification and the flags and default behaviour differ
between almost every platform (OSX, Linux, BSD, windows etc.)
Also, the \n is redundant since echo will add a newline to the string (on
all platforms that I know of) when called with no flags.
Den 23 aug. 2016 09:52 skrev "Pieter Willemsen" notifications@github.com:
In sys/newlib/thread_safe/Makefile.include
#4529 (comment):
the \n results in an error: "stdin>:1:23: error: extra tokens at end of
#include directive [-Werror]", adding -e to the echo command solves it (
-e: enable interpretation of backslash escapes)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/RIOT-OS/RIOT/pull/4529/files/0b380225290d6b1efeea9a7bbb273684b417672d#r75816861,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AATYQu8sumUmNCJsn-omBi-6etbn_ofjks5qiqa9gaJpZM4G43Px
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing the \n solved it.