Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
FORMUS3IC_LAS3
/
embb
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
29d124d0
authored
Nov 14, 2016
by
Michael Schmid
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added FreeRTOS implementation
parent
dd88ea03
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
693 additions
and
399 deletions
+693
-399
CMakeCommon/SetCompilerFlags.cmake
+45
-30
CMakeLists.txt
+7
-1
TC_Toolchain.cmake
+5
-1
base_c/include/embb/base/c/internal/config.h
+9
-1
base_c/include/embb/base/c/internal/platform.h
+26
-1
base_c/src/condition_variable.c
+4
-0
base_c/src/core_set.c
+26
-0
base_c/src/memory_allocation.c
+9
-0
base_c/src/mutex.c
+225
-153
base_c/src/thread.c
+337
-212
No files found.
CMakeCommon/SetCompilerFlags.cmake
View file @
29d124d0
...
@@ -26,36 +26,51 @@
...
@@ -26,36 +26,51 @@
#
#
function
(
SetGNUCompilerFlags compiler_libs
)
function
(
SetGNUCompilerFlags compiler_libs
)
if
(
CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX
)
if
(
CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX
)
set
(
compiler_libs pthread rt PARENT_SCOPE
)
if
(
DEFINED CMAKE_SYSTEM_PROCESSOR
)
# -Wall -> All warnings
set
(
compiler_libs PARENT_SCOPE
)
# -Wextra -> Even more warnings
set
(
common_flags
"-fno-common -Os"
)
# -Werror -> Warnings are errors
set
(
warning_flags
"-W -Wall -Wextra -Wdiv-by-zero -Warray-bounds -Wcast-align -Wignored-qualifiers -Wformat -Wformat-security"
)
set
(
warning_flags
"-Wall -Wextra"
)
set
(
target_flags
"-DAPPKIT_TC277TFT -fshort-double -mcpu=tc27xx -mversion-info"
)
if
(
WARNINGS_ARE_ERRORS STREQUAL ON
)
set
(
warning_flags
"
${
warning_flags
}
-Werror"
)
if
(
WARNINGS_ARE_ERRORS STREQUAL ON
)
endif
()
set
(
warning_flags
"
${
warning_flags
}
-Werror"
)
if
(
CMAKE_COMPILER_IS_GNUCC
)
endif
()
set
(
CMAKE_C_FLAGS
"
${
CMAKE_C_FLAGS
}
-pthread -std=c99
${
warning_flags
}
"
if
(
CMAKE_COMPILER_IS_GNUCC
)
PARENT_SCOPE
)
set
(
CMAKE_C_FLAGS
"
${
CMAKE_C_FLAGS
}
${
common_flags
}
${
warning_flags
}
${
target_flags
}
"
set
(
CMAKE_C_FLAGS_DEBUG
"
${
CMAKE_C_FLAGS_DEBUG
}
-DEMBB_DEBUG"
PARENT_SCOPE
)
PARENT_SCOPE
)
endif
()
set
(
CMAKE_C_FLAGS_RELEASE
"
${
CMAKE_C_FLAGS_RELEASE
}
-DNDEBUG"
else
()
PARENT_SCOPE
)
set
(
compiler_libs pthread rt PARENT_SCOPE
)
set
(
CMAKE_C_FLAGS_COVERAGE
# -Wall -> All warnings
"
${
CMAKE_C_FLAGS_COVERAGE
}
-O0 -fprofile-arcs -ftest-coverage"
# -Wextra -> Even more warnings
PARENT_SCOPE
)
# -Werror -> Warnings are errors
endif
()
set
(
warning_flags
"-Wall -Wextra"
)
if
(
CMAKE_COMPILER_IS_GNUCXX
)
if
(
WARNINGS_ARE_ERRORS STREQUAL ON
)
set
(
CMAKE_CXX_FLAGS
"
${
CMAKE_CXX_FLAGS
}
-pthread -std=c++03
${
warning_flags
}
"
set
(
warning_flags
"
${
warning_flags
}
-Werror"
)
PARENT_SCOPE
)
endif
()
set
(
CMAKE_CXX_FLAGS_DEBUG
"
${
CMAKE_CXX_FLAGS_DEBUG
}
-DEMBB_DEBUG"
if
(
CMAKE_COMPILER_IS_GNUCC
)
PARENT_SCOPE
)
set
(
CMAKE_C_FLAGS
"
${
CMAKE_C_FLAGS
}
-pthread -std=c99
${
warning_flags
}
"
set
(
CMAKE_CXX_FLAGS_RELEASE
"
${
CMAKE_CXX_FLAGS_RELEASE
}
-DNDEBUG"
PARENT_SCOPE
)
PARENT_SCOPE
)
set
(
CMAKE_C_FLAGS_DEBUG
"
${
CMAKE_C_FLAGS_DEBUG
}
-DEMBB_DEBUG"
set
(
CMAKE_CXX_FLAGS_COVERAGE
PARENT_SCOPE
)
"
${
CMAKE_CXX_FLAGS_COVERAGE
}
-O0 -fprofile-arcs -ftest-coverage"
set
(
CMAKE_C_FLAGS_RELEASE
"
${
CMAKE_C_FLAGS_RELEASE
}
-DNDEBUG"
PARENT_SCOPE
)
PARENT_SCOPE
)
endif
()
set
(
CMAKE_C_FLAGS_COVERAGE
"
${
CMAKE_C_FLAGS_COVERAGE
}
-O0 -fprofile-arcs -ftest-coverage"
PARENT_SCOPE
)
endif
()
if
(
CMAKE_COMPILER_IS_GNUCXX
)
set
(
CMAKE_CXX_FLAGS
"
${
CMAKE_CXX_FLAGS
}
-pthread -std=c++03
${
warning_flags
}
"
PARENT_SCOPE
)
set
(
CMAKE_CXX_FLAGS_DEBUG
"
${
CMAKE_CXX_FLAGS_DEBUG
}
-DEMBB_DEBUG"
PARENT_SCOPE
)
set
(
CMAKE_CXX_FLAGS_RELEASE
"
${
CMAKE_CXX_FLAGS_RELEASE
}
-DNDEBUG"
PARENT_SCOPE
)
set
(
CMAKE_CXX_FLAGS_COVERAGE
"
${
CMAKE_CXX_FLAGS_COVERAGE
}
-O0 -fprofile-arcs -ftest-coverage"
PARENT_SCOPE
)
endif
()
endif
()
endif
()
endif
()
endfunction
()
endfunction
()
...
...
CMakeLists.txt
View file @
29d124d0
...
@@ -76,7 +76,7 @@ endif()
...
@@ -76,7 +76,7 @@ endif()
# The set option will be converted to uppercase letters by cmake!! --> ON/OFF
# The set option will be converted to uppercase letters by cmake!! --> ON/OFF
# Note that the help string (second argument) cannot be printed by cmake.
# Note that the help string (second argument) cannot be printed by cmake.
#
#
option
(
BUILD_TESTS
"Specify whether tests should be built"
O
N
)
option
(
BUILD_TESTS
"Specify whether tests should be built"
O
FF
)
option
(
BUILD_EXAMPLES
"Specify whether examples should be built"
OFF
)
option
(
BUILD_EXAMPLES
"Specify whether examples should be built"
OFF
)
option
(
USE_EXCEPTIONS
"Specify whether exceptions should be activated in C++"
ON
)
option
(
USE_EXCEPTIONS
"Specify whether exceptions should be activated in C++"
ON
)
option
(
INSTALL_DOCS
"Specify whether Doxygen docs should be installed"
ON
)
option
(
INSTALL_DOCS
"Specify whether Doxygen docs should be installed"
ON
)
...
@@ -104,6 +104,12 @@ else()
...
@@ -104,6 +104,12 @@ else()
endif
()
endif
()
message
(
" (set with command line option -DUSE_AUTOMATIC_INITIALIZATION=ON/OFF)"
)
message
(
" (set with command line option -DUSE_AUTOMATIC_INITIALIZATION=ON/OFF)"
)
set
(
CMAKE_CXX_STANDARD_LIBRARIES
${
FREE_RTOS_LIB_PATH
}
/iRom/libFreeRTOS_Lib.a
)
set
(
CMAKE_C_STANDARD_LIBRARIES
${
FREE_RTOS_LIB_PATH
}
/iRom/libFreeRTOS_Lib.a
)
set
(
CMAKE_INSTALL_RPATH FREE_RTOS_LIB_PATH
)
set
(
__TriCore__ 1
)
include
(
CMakeCommon/SetCompilerFlags.cmake
)
include
(
CMakeCommon/SetCompilerFlags.cmake
)
SetGNUCompilerFlags
(
compiler_libs compiler_flags
)
SetGNUCompilerFlags
(
compiler_libs compiler_flags
)
SetVisualStudioCompilerFlags
(
compiler_libs compiler_flags
)
SetVisualStudioCompilerFlags
(
compiler_libs compiler_flags
)
...
...
TC_Toolchain.cmake
View file @
29d124d0
...
@@ -2,7 +2,8 @@
...
@@ -2,7 +2,8 @@
SET
(
CMAKE_SYSTEM_NAME Generic
)
SET
(
CMAKE_SYSTEM_NAME Generic
)
#this one not so much
#this one not so much
SET
(
CMAKE_SYSTEM_VERSION 1
)
SET
(
CMAKE_SYSTEM_VERSION 1
)
SET
(
CMAKE_SYSTEM_PROCESSOR TriCore
)
SET
(
CMAKE_SYSTEM_PROCESSOR __TriCore__
)
SET
(
__TriCore__ 1
)
# specify the cross compiler
# specify the cross compiler
SET
(
CMAKE_C_COMPILER C:/HighTec/toolchains/tricore/v4.6.6.0-infineon-1.1/bin/tricore-gcc.exe
)
SET
(
CMAKE_C_COMPILER C:/HighTec/toolchains/tricore/v4.6.6.0-infineon-1.1/bin/tricore-gcc.exe
)
...
@@ -11,6 +12,9 @@ SET(CMAKE_CXX_COMPILER C:/HighTec/toolchains/tricore/v4.6.6.0-infineon-1.1/bin/t
...
@@ -11,6 +12,9 @@ SET(CMAKE_CXX_COMPILER C:/HighTec/toolchains/tricore/v4.6.6.0-infineon-1.1/bin/t
# where is the target environment
# where is the target environment
SET
(
CMAKE_FIND_ROOT_PATH C:/HighTec/toolchains/tricore/v4.6.6.0-infineon-1.1
)
SET
(
CMAKE_FIND_ROOT_PATH C:/HighTec/toolchains/tricore/v4.6.6.0-infineon-1.1
)
SET
(
FREE_RTOS_LIB_PATH C:/data/projekte/freeRTOS_lib/
)
# search for programs in the build host directories
# search for programs in the build host directories
SET
(
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH
)
SET
(
CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH
)
# for libraries and headers in the target directories
# for libraries and headers in the target directories
...
...
base_c/include/embb/base/c/internal/config.h
View file @
29d124d0
...
@@ -46,6 +46,8 @@
...
@@ -46,6 +46,8 @@
*/
*/
#if defined(_M_IA64) || defined(_IA64)
#if defined(_M_IA64) || defined(_IA64)
#define EMBB_PLATFORM_CACHE_LINE_SIZE 128
#define EMBB_PLATFORM_CACHE_LINE_SIZE 128
#elif defined(__TriCore__)
#define EMBB_PLATFORM_CACHE_LINE_SIZE 32
#else
#else
#define EMBB_PLATFORM_CACHE_LINE_SIZE 64
#define EMBB_PLATFORM_CACHE_LINE_SIZE 64
#endif
#endif
...
@@ -86,6 +88,8 @@
...
@@ -86,6 +88,8 @@
#define EMBB_PLATFORM_ARCH_X86
#define EMBB_PLATFORM_ARCH_X86
#elif defined(__arm__)
#elif defined(__arm__)
#define EMBB_PLATFORM_ARCH_ARM
#define EMBB_PLATFORM_ARCH_ARM
#elif defined(__TriCore__)
#define EMBB_PLATFORM_ARCH_TC
#else
#else
#define EMBB_PLATFORM_ARCH_UNKNOWN
#define EMBB_PLATFORM_ARCH_UNKNOWN
#endif
#endif
...
@@ -93,7 +97,11 @@
...
@@ -93,7 +97,11 @@
#if defined(EMBB_PLATFORM_COMPILER_MSVC)
#if defined(EMBB_PLATFORM_COMPILER_MSVC)
#define EMBB_PLATFORM_THREADING_WINTHREADS
#define EMBB_PLATFORM_THREADING_WINTHREADS
#elif defined(EMBB_PLATFORM_COMPILER_GNUC)
#elif defined(EMBB_PLATFORM_COMPILER_GNUC)
#define EMBB_PLATFORM_THREADING_POSIXTHREADS
#if defined(EMBB_PLATFORM_ARCH_TC)
#define EMBB_PLATFORM_THREADING_RTOSTASKS
#else
#define EMBB_PLATFORM_THREADING_POSIXTHREADS
#endif
#else
#else
#error "No thread implementation could be determined"
#error "No thread implementation could be determined"
#endif
#endif
...
...
base_c/include/embb/base/c/internal/platform.h
View file @
29d124d0
...
@@ -71,6 +71,7 @@ typedef CONDITION_VARIABLE embb_condition_t;
...
@@ -71,6 +71,7 @@ typedef CONDITION_VARIABLE embb_condition_t;
#define EMBB_THREAD_SPECIFIC static __declspec(thread)
#define EMBB_THREAD_SPECIFIC static __declspec(thread)
/* EMBB_PLATFORM_THREADING_WINTHREADS */
#elif defined EMBB_PLATFORM_THREADING_POSIXTHREADS
#elif defined EMBB_PLATFORM_THREADING_POSIXTHREADS
#include <pthread.h>
#include <pthread.h>
...
@@ -95,7 +96,31 @@ typedef pthread_cond_t embb_condition_t;
...
@@ -95,7 +96,31 @@ typedef pthread_cond_t embb_condition_t;
#define EMBB_THREAD_SPECIFIC __thread
#define EMBB_THREAD_SPECIFIC __thread
#else
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#elif defined EMBB_PLATFORM_THREADING_RTOSTASKS
#include <FreeRTOS/task.h>
#include <FreeRTOS/semphr.h>
struct
embb_internal_thread_arg_t
;
/**
* Opaque handle for a thread.
*/
typedef
struct
embb_thread_t
{
TaskHandle_t
embb_internal_handle
;
struct
embb_internal_thread_arg_t
*
embb_internal_arg
;
}
embb_thread_t
;
typedef
TaskStatus_t
embb_thread_id_t
;
typedef
SemaphoreHandle_t
embb_mutex_t
;
typedef
SemaphoreHandle_t
embb_condition_t
;
// scm34681: implement FreeRTOS condition variable
#define EMBB_DURATION_MIN_NANOSECONDS 1000
#define EMBB_THREAD_SPECIFIC
#else
/* EMBB_PLATFORM_THREADING_RTOSTASKS */
#error "No threading platform defined!"
#error "No threading platform defined!"
...
...
base_c/src/condition_variable.c
View file @
29d124d0
...
@@ -185,3 +185,7 @@ int embb_condition_destroy(embb_condition_t* condition_var) {
...
@@ -185,3 +185,7 @@ int embb_condition_destroy(embb_condition_t* condition_var) {
}
}
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#ifdef EMBB_PLATFORM_THREADING_RTOSTASKS
#endif
/* EMBB_PLATFORM_THREADING_RTOSTASKS */
base_c/src/core_set.c
View file @
29d124d0
...
@@ -125,6 +125,32 @@ void embb_core_set_init(embb_core_set_t* core_set, int initializer) {
...
@@ -125,6 +125,32 @@ void embb_core_set_init(embb_core_set_t* core_set, int initializer) {
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#ifdef EMBB_PLATFORM_THREADING_RTOSTASKS
#ifdef __TriCore__
#define CORE_COUNT 3
#endif
unsigned
int
embb_core_count_available
()
{
return
CORE_COUNT
;
}
void
embb_core_set_init
(
embb_core_set_t
*
core_set
,
int
initializer
)
{
// scm34681: rework
assert
(
core_set
!=
NULL
);
assert
(
embb_core_count_available
()
<
64
&&
"Core sets are only supported up to 64 processors!"
);
if
(
initializer
==
0
)
{
embb_bitset_clear_all
(
&
core_set
->
rep
);
}
else
{
embb_bitset_set_n
(
&
core_set
->
rep
,
embb_core_count_available
());
}
}
#endif EMBB_PLATFORM_THREADING_RTOSTASKS
void
embb_core_set_add
(
embb_core_set_t
*
core_set
,
unsigned
int
core_number
)
{
void
embb_core_set_add
(
embb_core_set_t
*
core_set
,
unsigned
int
core_number
)
{
assert
(
core_set
!=
NULL
);
assert
(
core_set
!=
NULL
);
assert
(
core_number
<
embb_core_count_available
());
assert
(
core_number
<
embb_core_count_available
());
...
...
base_c/src/memory_allocation.c
View file @
29d124d0
...
@@ -178,6 +178,14 @@ void *embb_alloc_aligned(size_t alignment, size_t size) {
...
@@ -178,6 +178,14 @@ void *embb_alloc_aligned(size_t alignment, size_t size) {
*/
*/
malloc_addr
=
_aligned_malloc
(
size
,
alignment
);
malloc_addr
=
_aligned_malloc
(
size
,
alignment
);
#elif defined EMBB_PLATFORM_COMPILER_GNUC
#elif defined EMBB_PLATFORM_COMPILER_GNUC
#ifdef __TRICORE__
/*
* The TriCore Toolchain uses obsolete function memalign() for
* aligned memory allocation.
*/
#include <malloc.h> // scm3681: rework
malloc_addr
=
memalign
(
alignment
,
size
);
#else
/* __TRICORE__ */
/*
/*
* From the Documentation:
* From the Documentation:
* The posix_memalign() function shall allocate size bytes aligned on a
* The posix_memalign() function shall allocate size bytes aligned on a
...
@@ -190,6 +198,7 @@ void *embb_alloc_aligned(size_t alignment, size_t size) {
...
@@ -190,6 +198,7 @@ void *embb_alloc_aligned(size_t alignment, size_t size) {
int
status
=
posix_memalign
(
&
malloc_addr
,
alignment
,
size
);
int
status
=
posix_memalign
(
&
malloc_addr
,
alignment
,
size
);
EMBB_UNUSED
(
status
);
EMBB_UNUSED
(
status
);
#endif
#endif
#endif
return
malloc_addr
;
return
malloc_addr
;
}
}
...
...
base_c/src/mutex.c
View file @
29d124d0
/*
/*
* Copyright (c) 2014-2016, Siemens AG. All rights reserved.
* Copyright (c) 2014-2016, Siemens AG. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice,
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* this list of conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#include <embb/base/c/mutex.h>
#include <embb/base/c/mutex.h>
#include <embb/base/c/thread.h>
#include <embb/base/c/thread.h>
...
@@ -33,44 +33,44 @@
...
@@ -33,44 +33,44 @@
#ifdef EMBB_PLATFORM_THREADING_WINTHREADS
#ifdef EMBB_PLATFORM_THREADING_WINTHREADS
int
embb_mutex_init
(
embb_mutex_t
*
mutex
,
int
type
)
{
int
embb_mutex_init
(
embb_mutex_t
*
mutex
,
int
type
)
{
if
(
NULL
==
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
/* Critical sections in Windows are always recursive */
/* Critical sections in Windows are always recursive */
InitializeCriticalSection
(
mutex
);
InitializeCriticalSection
(
mutex
);
EMBB_UNUSED
(
type
);
EMBB_UNUSED
(
type
);
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_mutex_lock
(
embb_mutex_t
*
mutex
)
{
int
embb_mutex_lock
(
embb_mutex_t
*
mutex
)
{
if
(
NULL
==
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
EnterCriticalSection
(
mutex
);
EnterCriticalSection
(
mutex
);
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_mutex_try_lock
(
embb_mutex_t
*
mutex
)
{
int
embb_mutex_try_lock
(
embb_mutex_t
*
mutex
)
{
if
(
NULL
==
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
BOOL
success
;
BOOL
success
;
success
=
TryEnterCriticalSection
(
mutex
);
success
=
TryEnterCriticalSection
(
mutex
);
if
(
success
==
FALSE
)
return
EMBB_ERROR
;
if
(
success
==
FALSE
)
return
EMBB_ERROR
;
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_mutex_unlock
(
embb_mutex_t
*
mutex
)
{
int
embb_mutex_unlock
(
embb_mutex_t
*
mutex
)
{
if
(
NULL
==
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
LeaveCriticalSection
(
mutex
);
LeaveCriticalSection
(
mutex
);
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
void
embb_mutex_destroy
(
embb_mutex_t
*
mutex
)
{
void
embb_mutex_destroy
(
embb_mutex_t
*
mutex
)
{
assert
(
NULL
!=
mutex
);
assert
(
NULL
!=
mutex
);
DeleteCriticalSection
(
mutex
);
DeleteCriticalSection
(
mutex
);
}
}
#endif
/* EMBB_PLATFORM_THREADING_WINTHREADS */
#endif
/* EMBB_PLATFORM_THREADING_WINTHREADS */
...
@@ -78,136 +78,208 @@ void embb_mutex_destroy(embb_mutex_t* mutex) {
...
@@ -78,136 +78,208 @@ void embb_mutex_destroy(embb_mutex_t* mutex) {
#ifdef EMBB_PLATFORM_THREADING_POSIXTHREADS
#ifdef EMBB_PLATFORM_THREADING_POSIXTHREADS
int
embb_mutex_init
(
embb_mutex_t
*
mutex
,
int
type
)
{
int
embb_mutex_init
(
embb_mutex_t
*
mutex
,
int
type
)
{
if
(
NULL
==
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
if
(
type
==
EMBB_MUTEX_PLAIN
)
{
if
(
type
==
EMBB_MUTEX_PLAIN
)
{
if
(
pthread_mutex_init
(
mutex
,
NULL
)
!=
0
)
return
EMBB_ERROR
;
if
(
pthread_mutex_init
(
mutex
,
NULL
)
!=
0
)
return
EMBB_ERROR
;
}
else
{
}
else
{
assert
(
type
==
EMBB_MUTEX_RECURSIVE
);
assert
(
type
==
EMBB_MUTEX_RECURSIVE
);
pthread_mutexattr_t
attributes
;
pthread_mutexattr_t
attributes
;
if
(
pthread_mutexattr_init
(
&
attributes
)
!=
0
)
return
EMBB_ERROR
;
if
(
pthread_mutexattr_init
(
&
attributes
)
!=
0
)
return
EMBB_ERROR
;
if
(
pthread_mutexattr_settype
(
&
attributes
,
PTHREAD_MUTEX_RECURSIVE
)
!=
0
)
{
if
(
pthread_mutexattr_settype
(
&
attributes
,
PTHREAD_MUTEX_RECURSIVE
)
!=
0
)
{
pthread_mutexattr_destroy
(
&
attributes
);
pthread_mutexattr_destroy
(
&
attributes
);
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
if
(
pthread_mutex_init
(
mutex
,
&
attributes
)
!=
0
)
{
if
(
pthread_mutex_init
(
mutex
,
&
attributes
)
!=
0
)
{
pthread_mutexattr_destroy
(
&
attributes
);
pthread_mutexattr_destroy
(
&
attributes
);
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
if
(
pthread_mutexattr_destroy
(
&
attributes
)
!=
0
)
return
EMBB_ERROR
;
if
(
pthread_mutexattr_destroy
(
&
attributes
)
!=
0
)
return
EMBB_ERROR
;
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_mutex_lock
(
embb_mutex_t
*
mutex
)
{
int
embb_mutex_lock
(
embb_mutex_t
*
mutex
)
{
if
(
NULL
==
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
int
result
=
pthread_mutex_lock
(
mutex
);
int
result
=
pthread_mutex_lock
(
mutex
);
if
(
result
!=
0
)
{
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_mutex_try_lock
(
embb_mutex_t
*
mutex
)
{
int
embb_mutex_try_lock
(
embb_mutex_t
*
mutex
)
{
if
(
NULL
==
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
int
result
=
pthread_mutex_trylock
(
mutex
);
int
result
=
pthread_mutex_trylock
(
mutex
);
if
(
result
==
0
)
{
if
(
result
==
0
)
{
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
if
(
result
==
EBUSY
)
{
if
(
result
==
EBUSY
)
{
return
EMBB_BUSY
;
return
EMBB_BUSY
;
}
}
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
int
embb_mutex_unlock
(
embb_mutex_t
*
mutex
)
{
int
embb_mutex_unlock
(
embb_mutex_t
*
mutex
)
{
if
(
NULL
==
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
int
result
=
pthread_mutex_unlock
(
mutex
);
int
result
=
pthread_mutex_unlock
(
mutex
);
if
(
result
!=
0
)
{
if
(
result
!=
0
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
void
embb_mutex_destroy
(
embb_mutex_t
*
mutex
)
{
void
embb_mutex_destroy
(
embb_mutex_t
*
mutex
)
{
assert
(
NULL
!=
mutex
);
assert
(
NULL
!=
mutex
);
pthread_mutex_destroy
(
mutex
);
pthread_mutex_destroy
(
mutex
);
}
}
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#ifdef EMBB_PLATFORM_THREADING_RTOSTASKS
#include <FreeRTOS/semphr.h>
#include <FreeRTOS/portmacro.h>
int
embb_mutex_init
(
embb_mutex_t
*
mutex
,
int
type
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
}
/*
* scm34681:
* Type of mutex cannot be determined from SemaphoreHandle_t,
* but mutex gets locked with two different functions.
* ==> only recursive mutexes are used.
* Check Queue_t for type checking. Queue_t not defined in queue.h
* but queue.c...
*/
/*if(type == EMBB_MUTEX_PLAIN) {
mutex = xSemaphoreCreateMutex();
}
else {
assert(type == EMBB_MUTEX_RECURSIVE);*/
mutex
=
xSemaphoreCreateRecursiveMutex
();
/*}*/
EMBB_UNUSED
(
type
);
if
(
mutex
==
NULL
)
{
return
EMBB_ERROR
;
}
return
EMBB_SUCCESS
;
}
int
embb_mutex_lock
(
embb_mutex_t
*
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
}
int
result
=
xSemaphoreTakeRecursive
(
mutex
,
portMAX_DELAY
);
if
(
result
!=
1
)
return
EMBB_ERROR
;
return
EMBB_SUCCESS
;
}
int
embb_mutex_try_lock
(
embb_mutex_t
*
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
}
int
result
=
xSemaphoreTakeRecursive
(
mutex
,
0
);
if
(
result
!=
1
)
return
EMBB_ERROR
;
return
EMBB_SUCCESS
;
}
int
embb_mutex_unlock
(
embb_mutex_t
*
mutex
)
{
if
(
NULL
==
mutex
)
{
return
EMBB_ERROR
;
}
int
result
=
xSemaphoreGiveRecursive
(
mutex
);
if
(
result
!=
1
)
return
EMBB_ERROR
;
return
EMBB_SUCCESS
;
}
void
embb_mutex_destroy
(
embb_mutex_t
*
mutex
)
{
assert
(
NULL
!=
mutex
);
vSemaphoreDelete
(
mutex
);
}
#endif
/* EMBB_PLATFORM_THREADING_RTOSTASKS */
int
embb_spin_init
(
embb_spinlock_t
*
spinlock
)
{
int
embb_spin_init
(
embb_spinlock_t
*
spinlock
)
{
if
(
NULL
==
spinlock
)
{
if
(
NULL
==
spinlock
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
// For now, store the initial value. In the future will use atomic init
// For now, store the initial value. In the future will use atomic init
// function (as soon as available).
// function (as soon as available).
embb_atomic_store_int
(
&
spinlock
->
atomic_spin_variable_
,
0
);
embb_atomic_store_int
(
&
spinlock
->
atomic_spin_variable_
,
0
);
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_spin_lock
(
embb_spinlock_t
*
spinlock
)
{
int
embb_spin_lock
(
embb_spinlock_t
*
spinlock
)
{
if
(
NULL
==
spinlock
)
{
if
(
NULL
==
spinlock
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
int
expected
=
0
;
int
expected
=
0
;
int
spins
=
1
;
int
spins
=
1
;
// try to swap the
// try to swap the
while
(
0
==
embb_atomic_compare_and_swap_int
(
while
(
0
==
embb_atomic_compare_and_swap_int
(
&
spinlock
->
atomic_spin_variable_
,
&
expected
,
1
))
{
&
spinlock
->
atomic_spin_variable_
,
&
expected
,
1
))
{
if
(
0
==
(
spins
&
1023
))
{
if
(
0
==
(
spins
&
1023
))
{
embb_thread_yield
();
embb_thread_yield
();
}
}
spins
++
;
spins
++
;
// reset expected, as CAS might change it...
// reset expected, as CAS might change it...
expected
=
0
;
expected
=
0
;
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_spin_try_lock
(
embb_spinlock_t
*
spinlock
,
int
embb_spin_try_lock
(
embb_spinlock_t
*
spinlock
,
unsigned
int
max_number_spins
)
{
unsigned
int
max_number_spins
)
{
if
(
NULL
==
spinlock
)
{
if
(
NULL
==
spinlock
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
if
(
max_number_spins
==
0
)
if
(
max_number_spins
==
0
)
return
EMBB_BUSY
;
return
EMBB_BUSY
;
int
expected
=
0
;
int
expected
=
0
;
while
(
0
==
embb_atomic_compare_and_swap_int
(
while
(
0
==
embb_atomic_compare_and_swap_int
(
&
spinlock
->
atomic_spin_variable_
,
&
spinlock
->
atomic_spin_variable_
,
&
expected
,
1
))
{
&
expected
,
1
))
{
max_number_spins
--
;
max_number_spins
--
;
if
(
0
==
max_number_spins
)
{
if
(
0
==
max_number_spins
)
{
return
EMBB_BUSY
;
return
EMBB_BUSY
;
}
}
expected
=
0
;
expected
=
0
;
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_spin_unlock
(
embb_spinlock_t
*
spinlock
)
{
int
embb_spin_unlock
(
embb_spinlock_t
*
spinlock
)
{
if
(
NULL
==
spinlock
)
{
if
(
NULL
==
spinlock
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
int
expected
=
1
;
int
expected
=
1
;
return
embb_atomic_compare_and_swap_int
(
&
spinlock
->
atomic_spin_variable_
,
return
embb_atomic_compare_and_swap_int
(
&
spinlock
->
atomic_spin_variable_
,
&
expected
,
0
)
?
&
expected
,
0
)
?
EMBB_SUCCESS
:
EMBB_ERROR
;
EMBB_SUCCESS
:
EMBB_ERROR
;
}
}
void
embb_spin_destroy
(
embb_spinlock_t
*
spinlock
)
{
void
embb_spin_destroy
(
embb_spinlock_t
*
spinlock
)
{
assert
(
NULL
!=
spinlock
);
assert
(
NULL
!=
spinlock
);
// for now, doing nothing here... in future, will call the respective
// for now, doing nothing here... in future, will call the respective
// destroy function for atomics...
// destroy function for atomics...
EMBB_UNUSED
(
spinlock
);
EMBB_UNUSED
(
spinlock
);
}
}
base_c/src/thread.c
View file @
29d124d0
/*
/*
* Copyright (c) 2014-2016, Siemens AG. All rights reserved.
* Copyright (c) 2014-2016, Siemens AG. All rights reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice,
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* this list of conditions and the following disclaimer.
*
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* POSSIBILITY OF SUCH DAMAGE.
*/
*/
#include <embb/base/c/thread.h>
#include <embb/base/c/thread.h>
#include <embb/base/c/internal/thread_index.h>
#include <embb/base/c/internal/thread_index.h>
...
@@ -33,135 +33,135 @@
...
@@ -33,135 +33,135 @@
#include <assert.h>
#include <assert.h>
unsigned
int
embb_thread_get_max_count
()
{
unsigned
int
embb_thread_get_max_count
()
{
return
(
unsigned
int
)(
embb_internal_thread_index_max
());
return
(
unsigned
int
)(
embb_internal_thread_index_max
());
}
}
void
embb_thread_set_max_count
(
unsigned
int
max
)
{
void
embb_thread_set_max_count
(
unsigned
int
max
)
{
embb_internal_thread_index_set_max
(
max
);
embb_internal_thread_index_set_max
(
max
);
}
}
#ifdef EMBB_PLATFORM_THREADING_WINTHREADS
#ifdef EMBB_PLATFORM_THREADING_WINTHREADS
/**
/**
* Used to wrap client thread start function and argument when calling internal
* Used to wrap client thread start function and argument when calling internal
* thread start function embb_internal_thread_start.
* thread start function embb_internal_thread_start.
*/
*/
typedef
struct
embb_internal_thread_arg_t
{
typedef
struct
embb_internal_thread_arg_t
{
embb_thread_start_t
func
;
embb_thread_start_t
func
;
void
*
arg
;
void
*
arg
;
}
embb_internal_thread_arg_t
;
}
embb_internal_thread_arg_t
;
/**
/**
* Used to offer a consistent thread start function signature. Windows threads
* Used to offer a consistent thread start function signature. Windows threads
* have a different signature than Pthreads and C11. This internal start
* have a different signature than Pthreads and C11. This internal start
* function for Windows threads just calls the client start function with the
* function for Windows threads just calls the client start function with the
* given argument.
* given argument.
*/
*/
DWORD
WINAPI
embb_internal_thread_start
(
LPVOID
internalArg
)
{
DWORD
WINAPI
embb_internal_thread_start
(
LPVOID
internalArg
)
{
int
result
=
((
embb_internal_thread_arg_t
*
)
internalArg
)
->
func
(
int
result
=
((
embb_internal_thread_arg_t
*
)
internalArg
)
->
func
(
((
embb_internal_thread_arg_t
*
)
internalArg
)
->
arg
);
((
embb_internal_thread_arg_t
*
)
internalArg
)
->
arg
);
#if !defined(__cplusplus)
#if !defined(__cplusplus)
ExitThread
((
DWORD
)
result
);
/* In C, returning the result code doesn't work */
ExitThread
((
DWORD
)
result
);
/* In C, returning the result code doesn't work */
#else
#else
return
(
DWORD
)
result
;
return
(
DWORD
)
result
;
#endif
#endif
}
}
embb_thread_t
embb_thread_current
()
{
embb_thread_t
embb_thread_current
()
{
embb_thread_t
thread
;
embb_thread_t
thread
;
thread
.
embb_internal_handle
=
GetCurrentThread
();
thread
.
embb_internal_handle
=
GetCurrentThread
();
thread
.
embb_internal_arg
=
NULL
;
thread
.
embb_internal_arg
=
NULL
;
return
thread
;
return
thread
;
}
}
void
embb_thread_yield
()
{
void
embb_thread_yield
()
{
SwitchToThread
();
SwitchToThread
();
}
}
int
embb_thread_create
(
embb_thread_t
*
thread
,
const
embb_core_set_t
*
core_set
,
int
embb_thread_create
(
embb_thread_t
*
thread
,
const
embb_core_set_t
*
core_set
,
embb_thread_start_t
func
,
void
*
arg
)
{
embb_thread_start_t
func
,
void
*
arg
)
{
if
(
thread
==
NULL
)
{
if
(
thread
==
NULL
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
thread
->
embb_internal_arg
=
(
embb_internal_thread_arg_t
*
)
thread
->
embb_internal_arg
=
(
embb_internal_thread_arg_t
*
)
embb_alloc
(
sizeof
(
embb_internal_thread_arg_t
));
embb_alloc
(
sizeof
(
embb_internal_thread_arg_t
));
if
(
thread
->
embb_internal_arg
==
NULL
)
{
if
(
thread
->
embb_internal_arg
==
NULL
)
{
thread
->
embb_internal_handle
=
NULL
;
thread
->
embb_internal_handle
=
NULL
;
return
EMBB_NOMEM
;
return
EMBB_NOMEM
;
}
}
thread
->
embb_internal_arg
->
func
=
func
;
thread
->
embb_internal_arg
->
func
=
func
;
thread
->
embb_internal_arg
->
arg
=
arg
;
thread
->
embb_internal_arg
->
arg
=
arg
;
thread
->
embb_internal_handle
=
CreateThread
(
thread
->
embb_internal_handle
=
CreateThread
(
0
,
/* no security */
0
,
/* no security */
0
,
/* default stack size */
0
,
/* default stack size */
embb_internal_thread_start
,
/* entry function */
embb_internal_thread_start
,
/* entry function */
(
LPVOID
)
thread
->
embb_internal_arg
,
/* parameters */
(
LPVOID
)
thread
->
embb_internal_arg
,
/* parameters */
0
,
/* no creation arguments */
0
,
/* no creation arguments */
0
);
/* no system thread ID */
0
);
/* no system thread ID */
if
(
thread
->
embb_internal_handle
==
NULL
)
{
if
(
thread
->
embb_internal_handle
==
NULL
)
{
embb_free
(
thread
->
embb_internal_arg
);
embb_free
(
thread
->
embb_internal_arg
);
thread
->
embb_internal_arg
=
NULL
;
thread
->
embb_internal_arg
=
NULL
;
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
if
(
core_set
!=
NULL
)
{
/* Set thread affinity, if a core set is given */
if
(
core_set
!=
NULL
)
{
/* Set thread affinity, if a core set is given */
DWORD_PTR
core_mask
=
0
;
DWORD_PTR
core_mask
=
0
;
DWORD
bit_mask
=
1
;
DWORD
bit_mask
=
1
;
assert
(
embb_core_count_available
()
<
64
);
assert
(
embb_core_count_available
()
<
64
);
for
(
unsigned
int
i
=
0
;
i
<
embb_core_count_available
();
i
++
)
{
for
(
unsigned
int
i
=
0
;
i
<
embb_core_count_available
();
i
++
)
{
if
(
embb_core_set_contains
(
core_set
,
i
))
{
if
(
embb_core_set_contains
(
core_set
,
i
))
{
core_mask
|=
bit_mask
;
core_mask
|=
bit_mask
;
}
}
bit_mask
<<=
1
;
bit_mask
<<=
1
;
}
}
if
(
SetThreadAffinityMask
(
thread
->
embb_internal_handle
,
core_mask
)
if
(
SetThreadAffinityMask
(
thread
->
embb_internal_handle
,
core_mask
)
==
(
DWORD_PTR
)
NULL
)
{
==
(
DWORD_PTR
)
NULL
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_thread_join
(
embb_thread_t
*
thread
,
int
*
result_code
)
{
int
embb_thread_join
(
embb_thread_t
*
thread
,
int
*
result_code
)
{
if
(
thread
==
NULL
)
{
if
(
thread
==
NULL
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
BOOL
success
;
BOOL
success
;
DWORD
result
;
DWORD
result
;
result
=
WaitForSingleObject
(
thread
->
embb_internal_handle
,
INFINITE
);
result
=
WaitForSingleObject
(
thread
->
embb_internal_handle
,
INFINITE
);
embb_free
(
thread
->
embb_internal_arg
);
embb_free
(
thread
->
embb_internal_arg
);
if
(
result
!=
WAIT_OBJECT_0
)
{
if
(
result
!=
WAIT_OBJECT_0
)
{
/* WAIT_OBJECT_0 indicates successful waiting */
/* WAIT_OBJECT_0 indicates successful waiting */
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
if
(
result_code
!=
NULL
)
{
/* != NULL means the client wants a result code */
if
(
result_code
!=
NULL
)
{
/* != NULL means the client wants a result code */
if
(
GetExitCodeThread
(
thread
->
embb_internal_handle
,
&
result
)
!=
0
)
{
if
(
GetExitCodeThread
(
thread
->
embb_internal_handle
,
&
result
)
!=
0
)
{
*
result_code
=
(
int
)
result
;
*
result_code
=
(
int
)
result
;
}
else
{
}
else
{
*
result_code
=
0
;
/* Error on obtaining result code */
*
result_code
=
0
;
/* Error on obtaining result code */
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
}
}
success
=
CloseHandle
(
thread
->
embb_internal_handle
);
success
=
CloseHandle
(
thread
->
embb_internal_handle
);
if
(
success
==
FALSE
)
{
if
(
success
==
FALSE
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
/*return embb_internal_thread_counter_try_decrement();*/
/*return embb_internal_thread_counter_try_decrement();*/
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_thread_equal
(
const
embb_thread_t
*
lhs
,
const
embb_thread_t
*
rhs
)
{
int
embb_thread_equal
(
const
embb_thread_t
*
lhs
,
const
embb_thread_t
*
rhs
)
{
if
(
lhs
==
NULL
||
rhs
==
NULL
)
{
if
(
lhs
==
NULL
||
rhs
==
NULL
)
{
return
0
;
return
0
;
}
}
embb_thread_id_t
idLhs
=
GetThreadId
(
lhs
->
embb_internal_handle
);
embb_thread_id_t
idLhs
=
GetThreadId
(
lhs
->
embb_internal_handle
);
embb_thread_id_t
idRhs
=
GetThreadId
(
rhs
->
embb_internal_handle
);
embb_thread_id_t
idRhs
=
GetThreadId
(
rhs
->
embb_internal_handle
);
if
(
idLhs
==
idRhs
)
{
if
(
idLhs
==
idRhs
)
{
return
1
;
return
1
;
}
}
return
0
;
return
0
;
}
}
#endif
/* EMBB_PLATFORM_THREADING_WINTHREADS */
#endif
/* EMBB_PLATFORM_THREADING_WINTHREADS */
...
@@ -181,122 +181,247 @@ int embb_thread_equal(const embb_thread_t* lhs, const embb_thread_t* rhs) {
...
@@ -181,122 +181,247 @@ int embb_thread_equal(const embb_thread_t* lhs, const embb_thread_t* rhs) {
#endif
/* EMBB_PLATFORM_HAS_HEADER_SYSINFO */
#endif
/* EMBB_PLATFORM_HAS_HEADER_SYSINFO */
/**
/**
* Used to wrap client thread start function and argument when calling internal
* Used to wrap client thread start function and argument when calling internal
* thread start function embb_internal_thread_start.
* thread start function embb_internal_thread_start.
*/
*/
typedef
struct
embb_internal_thread_arg_t
{
typedef
struct
embb_internal_thread_arg_t
{
embb_thread_start_t
func
;
embb_thread_start_t
func
;
void
*
arg
;
void
*
arg
;
int
result
;
int
result
;
}
embb_internal_thread_arg_t
;
}
embb_internal_thread_arg_t
;
/**
/**
* Used to offer a consistent thread start function signature. POSIX threads
* Used to offer a consistent thread start function signature. POSIX threads
* have a different signature than C11 threads. This internal start function
* have a different signature than C11 threads. This internal start function
* for POSIX threads just calls the client start function with the given
* for POSIX threads just calls the client start function with the given
* argument.
* argument.
*/
*/
void
*
embb_internal_thread_start
(
void
*
internalArg
)
{
void
*
embb_internal_thread_start
(
void
*
internalArg
)
{
((
embb_internal_thread_arg_t
*
)
internalArg
)
->
result
=
((
embb_internal_thread_arg_t
*
)
internalArg
)
->
result
=
((
embb_internal_thread_arg_t
*
)
internalArg
)
->
func
(
((
embb_internal_thread_arg_t
*
)
internalArg
)
->
func
(
((
struct
embb_internal_thread_arg_t
*
)
internalArg
)
->
arg
);
((
struct
embb_internal_thread_arg_t
*
)
internalArg
)
->
arg
);
return
NULL
;
return
NULL
;
}
}
embb_thread_t
embb_thread_current
()
{
embb_thread_t
embb_thread_current
()
{
embb_thread_t
thread
;
embb_thread_t
thread
;
thread
.
embb_internal_handle
=
pthread_self
();
thread
.
embb_internal_handle
=
pthread_self
();
thread
.
embb_internal_arg
=
NULL
;
thread
.
embb_internal_arg
=
NULL
;
return
thread
;
return
thread
;
}
}
void
embb_thread_yield
()
{
void
embb_thread_yield
()
{
pthread_yield
();
pthread_yield
();
}
}
int
embb_thread_create
(
embb_thread_t
*
thread
,
const
embb_core_set_t
*
core_set
,
int
embb_thread_create
(
embb_thread_t
*
thread
,
const
embb_core_set_t
*
core_set
,
embb_thread_start_t
func
,
void
*
arg
)
{
embb_thread_start_t
func
,
void
*
arg
)
{
if
(
thread
==
NULL
)
{
if
(
thread
==
NULL
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
pthread_attr_t
attr
;
/* Used to set thread affinities */
pthread_attr_t
attr
;
/* Used to set thread affinities */
int
status
=
pthread_attr_init
(
&
attr
);
int
status
=
pthread_attr_init
(
&
attr
);
if
(
status
!=
0
)
return
EMBB_ERROR
;
if
(
status
!=
0
)
return
EMBB_ERROR
;
if
(
core_set
!=
NULL
)
{
if
(
core_set
!=
NULL
)
{
#if defined(EMBB_PLATFORM_HAS_GLIB_CPU) || \
#if defined(EMBB_PLATFORM_HAS_GLIB_CPU) || \
defined(EMBB_PLATFORM_HAS_HEADER_CPUSET)
defined(EMBB_PLATFORM_HAS_HEADER_CPUSET)
assert
(
embb_core_count_available
()
<
CPU_SETSIZE
&&
assert
(
embb_core_count_available
()
<
CPU_SETSIZE
&&
"Core sets are only supported up to CPU_SETSIZE processors!"
);
"Core sets are only supported up to CPU_SETSIZE processors!"
);
#ifdef EMBB_PLATFORM_HAS_GLIB_CPU
#ifdef EMBB_PLATFORM_HAS_GLIB_CPU
cpu_set_t
cpuset
;
cpu_set_t
cpuset
;
#else
#else
cpuset_t
cpuset
;
cpuset_t
cpuset
;
#endif
#endif
CPU_ZERO
(
&
cpuset
);
/* Disable all processors */
CPU_ZERO
(
&
cpuset
);
/* Disable all processors */
for
(
unsigned
int
i
=
0
;
i
<
embb_core_count_available
();
i
++
)
{
for
(
unsigned
int
i
=
0
;
i
<
embb_core_count_available
();
i
++
)
{
if
(
embb_core_set_contains
(
core_set
,
i
))
{
if
(
embb_core_set_contains
(
core_set
,
i
))
{
CPU_SET
(
i
,
&
cpuset
);
CPU_SET
(
i
,
&
cpuset
);
}
}
}
}
status
=
pthread_attr_setaffinity_np
(
&
attr
,
sizeof
(
cpuset
),
&
cpuset
);
status
=
pthread_attr_setaffinity_np
(
&
attr
,
sizeof
(
cpuset
),
&
cpuset
);
if
(
status
!=
0
)
{
if
(
status
!=
0
)
{
thread
->
embb_internal_arg
=
NULL
;
thread
->
embb_internal_arg
=
NULL
;
thread
->
embb_internal_handle
=
0
;
thread
->
embb_internal_handle
=
0
;
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
#else
#else
embb_log_write
(
"base_c"
,
EMBB_LOG_LEVEL_WARNING
,
"Could not set thread "
embb_log_write
(
"base_c"
,
EMBB_LOG_LEVEL_WARNING
,
"Could not set thread "
"affinity, since no implementation available!
\n
"
);
"affinity, since no implementation available!
\n
"
);
#endif
#endif
}
}
/* Dynamic allocation of thread arguments. Freed on call of join. */
/* Dynamic allocation of thread arguments. Freed on call of join. */
thread
->
embb_internal_arg
=
(
embb_internal_thread_arg_t
*
)
thread
->
embb_internal_arg
=
(
embb_internal_thread_arg_t
*
)
embb_alloc
(
sizeof
(
embb_internal_thread_arg_t
));
embb_alloc
(
sizeof
(
embb_internal_thread_arg_t
));
if
(
thread
->
embb_internal_arg
==
NULL
)
{
if
(
thread
->
embb_internal_arg
==
NULL
)
{
thread
->
embb_internal_handle
=
0
;
thread
->
embb_internal_handle
=
0
;
pthread_attr_destroy
(
&
attr
);
pthread_attr_destroy
(
&
attr
);
return
EMBB_NOMEM
;
return
EMBB_NOMEM
;
}
}
thread
->
embb_internal_arg
->
func
=
func
;
thread
->
embb_internal_arg
->
func
=
func
;
thread
->
embb_internal_arg
->
arg
=
arg
;
thread
->
embb_internal_arg
->
arg
=
arg
;
status
=
pthread_create
(
status
=
pthread_create
(
&
(
thread
->
embb_internal_handle
),
/* pthread handle */
&
(
thread
->
embb_internal_handle
),
/* pthread handle */
&
attr
,
/* additional attributes,
&
attr
,
/* additional attributes,
e.g., affinities */
e.g., affinities */
embb_internal_thread_start
,
/* thread start function */
embb_internal_thread_start
,
/* thread start function */
(
void
*
)(
thread
->
embb_internal_arg
));
/* arguments to thread start func. */
(
void
*
)(
thread
->
embb_internal_arg
));
/* arguments to thread start func. */
if
(
status
!=
0
)
return
EMBB_ERROR
;
if
(
status
!=
0
)
return
EMBB_ERROR
;
status
=
pthread_attr_destroy
(
&
attr
);
status
=
pthread_attr_destroy
(
&
attr
);
if
(
status
!=
0
)
return
EMBB_ERROR
;
if
(
status
!=
0
)
return
EMBB_ERROR
;
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_thread_join
(
embb_thread_t
*
thread
,
int
*
result_code
)
{
int
embb_thread_join
(
embb_thread_t
*
thread
,
int
*
result_code
)
{
if
(
thread
==
NULL
)
{
if
(
thread
==
NULL
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
int
status
=
0
;
int
status
=
0
;
status
=
pthread_join
(
thread
->
embb_internal_handle
,
NULL
);
status
=
pthread_join
(
thread
->
embb_internal_handle
,
NULL
);
if
(
thread
->
embb_internal_arg
!=
NULL
)
{
if
(
thread
->
embb_internal_arg
!=
NULL
)
{
if
(
result_code
!=
NULL
)
{
if
(
result_code
!=
NULL
)
{
*
result_code
=
thread
->
embb_internal_arg
->
result
;
*
result_code
=
thread
->
embb_internal_arg
->
result
;
}
}
embb_free
(
thread
->
embb_internal_arg
);
embb_free
(
thread
->
embb_internal_arg
);
}
}
if
(
status
!=
0
)
{
if
(
status
!=
0
)
{
return
EMBB_ERROR
;
return
EMBB_ERROR
;
}
}
return
EMBB_SUCCESS
;
return
EMBB_SUCCESS
;
}
}
int
embb_thread_equal
(
const
embb_thread_t
*
lhs
,
const
embb_thread_t
*
rhs
)
{
int
embb_thread_equal
(
const
embb_thread_t
*
lhs
,
const
embb_thread_t
*
rhs
)
{
if
(
lhs
==
NULL
||
rhs
==
NULL
)
{
if
(
lhs
==
NULL
||
rhs
==
NULL
)
{
return
0
;
return
0
;
}
}
return
pthread_equal
(
lhs
->
embb_internal_handle
,
rhs
->
embb_internal_handle
);
return
pthread_equal
(
lhs
->
embb_internal_handle
,
rhs
->
embb_internal_handle
);
}
}
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#endif
/* EMBB_PLATFORM_THREADING_POSIXTHREADS */
#ifdef EMBB_PLATFORM_THREADING_RTOSTASKS
#include <FreeRTOS/task.h>
/**
* Used to wrap client thread start function and argument when calling internal
* thread start function embb_internal_thread_start.
*/
typedef
struct
embb_internal_thread_arg_t
{
embb_thread_start_t
func
;
void
*
arg
;
int
result
;
}
embb_internal_thread_arg_t
;
/**
* Used to offer a consistent thread start function signature. POSIX threads
* have a different signature than C11 threads. This internal start function
* for POSIX threads just calls the client start function with the given
* argument.
*/
void
*
embb_internal_thread_start
(
void
*
internalArg
)
{
for
(;;)
{
((
embb_internal_thread_arg_t
*
)
internalArg
)
->
result
=
((
embb_internal_thread_arg_t
*
)
internalArg
)
->
func
(
((
struct
embb_internal_thread_arg_t
*
)
internalArg
)
->
arg
);
vTaskDelete
(
NULL
);
}
}
embb_thread_t
embb_thread_current
()
{
embb_thread_t
thread
;
thread
.
embb_internal_handle
=
xTaskGetCurrentTaskHandle
();
thread
.
embb_internal_arg
=
NULL
;
return
thread
;
}
void
embb_thread_yield
()
{
taskYIELD
();
}
int
embb_thread_create
(
embb_thread_t
*
thread
,
const
embb_core_set_t
*
core_set
,
embb_thread_start_t
func
,
void
*
arg
)
{
int
status
;
if
(
thread
==
NULL
)
{
return
EMBB_ERROR
;
}
thread
->
embb_internal_arg
=
(
embb_internal_thread_arg_t
*
)
embb_alloc
(
sizeof
(
embb_internal_thread_arg_t
));
if
(
thread
->
embb_internal_arg
==
NULL
)
{
thread
->
embb_internal_handle
=
NULL
;
return
EMBB_NOMEM
;
}
thread
->
embb_internal_arg
->
func
=
func
;
thread
->
embb_internal_arg
->
arg
=
arg
;
status
=
xTaskCreate
(
embb_internal_thread_start
,
// entry function
0
,
// task name (not needed)
128
,
// stack size
thread
->
embb_internal_arg
,
// parameters
1
,
// priority
thread
->
embb_internal_handle
);
// thread handle
if
(
status
!=
1
)
{
embb_free
(
thread
->
embb_internal_arg
);
thread
->
embb_internal_arg
=
NULL
;
return
EMBB_ERROR
;
}
/*if (core_set != NULL) { // scm34681: implement core affinity
DWORD_PTR core_mask = 0;
DWORD bit_mask = 1;
assert(embb_core_count_available() < 64);
for (unsigned int i = 0; i < embb_core_count_available(); i++) {
if (embb_core_set_contains(core_set, i)) {
core_mask |= bit_mask;
}
bit_mask <<= 1;
}
if (SetThreadAffinityMask(thread->embb_internal_handle, core_mask)
== (DWORD_PTR)NULL) {
return EMBB_ERROR;
}
}*/
return
EMBB_SUCCESS
;
}
int
embb_thread_join
(
embb_thread_t
*
thread
,
int
*
result_code
)
{
if
(
thread
==
NULL
)
{
return
EMBB_ERROR
;
}
int
status
=
0
;
while
(
thread
->
embb_internal_handle
!=
NULL
&&
status
++
<
10000
);
// scm34681: rework
if
(
thread
->
embb_internal_arg
!=
NULL
)
{
if
(
result_code
!=
NULL
)
{
*
result_code
=
thread
->
embb_internal_arg
->
result
;
}
embb_free
(
thread
->
embb_internal_arg
);
}
return
EMBB_SUCCESS
;
}
int
embb_thread_equal
(
const
embb_thread_t
*
lhs
,
const
embb_thread_t
*
rhs
)
{
if
(
lhs
==
NULL
||
rhs
==
NULL
)
{
return
0
;
}
TaskStatus_t
lhs_info
;
TaskStatus_t
rhs_info
;
vTaskGetInfo
(
lhs
->
embb_internal_handle
,
&
lhs_info
,
0
,
0
);
vTaskGetInfo
(
lhs
->
embb_internal_handle
,
&
rhs_info
,
0
,
0
);
return
lhs_info
.
xTaskNumber
==
rhs_info
.
xTaskNumber
;
}
#endif
/* EMBB_PLATFORM_THREADING_RTOSTASKS */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment