-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
newlib: Initial thread-safe implementation
- Loading branch information
Showing
6 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
MODULE = newlib_thread_safe | ||
|
||
include $(RIOTBASE)/Makefile.base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Copyright (C) 2015 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 <sys/reent.h> | ||
|
||
#include <thread.h> | ||
#include <mutex.h> | ||
|
||
#if MODULE_NEWLIB_THREAD_SAFE | ||
static volatile kernel_pid_t _env_owner = KERNEL_PID_UNDEF; | ||
static atomic_int_t _env_lock_recursion; | ||
static mutex_t _env_mutex; | ||
#endif | ||
|
||
/** | ||
* @brief __env_lock needs to provide recursive mutex locking | ||
*/ | ||
void __env_lock(struct _reent *_r) | ||
{ | ||
/* TODO another way would be to avoid rescheduling other tasks */ | ||
#if MODULE_NEWLIB_THREAD_SAFE | ||
switch (mutex_trylock(&_env_mutex)) | ||
{ | ||
case 0: | ||
/* mutex is already locked */ | ||
if (_env_owner != thread_getpid()) { | ||
/* we are not the owner, so we wait till it's released and | ||
* fall-trough the case statement */ | ||
mutex_lock(&_env_mutex); | ||
} | ||
|
||
continue; | ||
|
||
case 1: | ||
/* mutex now locked by us */ | ||
atomic_inc(&_env_lock_recursion); | ||
_env_owner = thread_getpid(); | ||
break; | ||
} | ||
#else | ||
(void) _r; | ||
#endif | ||
} | ||
|
||
void __env_unlock(struct _reent *_r) | ||
{ | ||
#if MODULE_NEWLIB_THREAD_SAFE | ||
if (atomic_dec(&_env_lock_recursion) == 1) { | ||
/* we just released the last recursion lock call */ | ||
|
||
_env_owner = KERNEL_PID_UNDEF; | ||
mutex_unlock(&_env_mutex); | ||
} | ||
#else | ||
(void) _r; | ||
#endif | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Copyright (C) 2015 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 <sys/reent.h> | ||
|
||
#include <thread.h> | ||
#include <mutex.h> | ||
|
||
#if MODULE_NEWLIB_THREAD_SAFE | ||
static volatile kernel_pid_t _malloc_owner = KERNEL_PID_UNDEF; | ||
static atomic_int_t _malloc_lock_recursion; | ||
static mutex_t _malloc_mutex; | ||
#endif | ||
|
||
/** | ||
* @brief __malloc_lock needs to provide recursive mutex locking | ||
*/ | ||
void __malloc_lock(struct _reent *_r) | ||
{ | ||
/* TODO another way would be to avoid rescheduling other tasks */ | ||
#if MODULE_NEWLIB_THREAD_SAFE | ||
switch (mutex_trylock(&_malloc_mutex)) | ||
{ | ||
case 0: | ||
/* mutex is already locked */ | ||
if (_malloc_owner != thread_getpid()) { | ||
/* we are not the owner, so we wait till it's released and | ||
* fall-trough the case statement */ | ||
mutex_lock(&_malloc_mutex); | ||
} | ||
|
||
continue; | ||
|
||
case 1: | ||
/* mutex now locked by us */ | ||
atomic_inc(&_malloc_lock_recursion); | ||
_malloc_owner = thread_getpid(); | ||
break; | ||
} | ||
#else | ||
(void) _r; | ||
#endif | ||
} | ||
|
||
void __malloc_unlock(struct _reent *_r) | ||
{ | ||
#if MODULE_NEWLIB_THREAD_SAFE | ||
if (atomic_dec(&_malloc_lock_recursion) == 1) { | ||
/* we just released the last recursion lock call */ | ||
|
||
_malloc_owner = KERNEL_PID_UNDEF; | ||
mutex_unlock(&_malloc_mutex); | ||
} | ||
#else | ||
(void) _r; | ||
#endif | ||
} |