Skip to content

Commit 6a03c2f

Browse files
committed
Support for ThreadX
1 parent b8024ea commit 6a03c2f

File tree

7 files changed

+347
-106
lines changed

7 files changed

+347
-106
lines changed

Makefile

Lines changed: 87 additions & 94 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ topic.
115115
| `DEBUG` | | Compiler debugging flag to use (default `-ggdb`) |
116116
| `OPTIM` | | The optimizer flag to use (default `-O3`) |
117117
| `HOST` | | The target host tuple, for cross-compilation (default unset, i.e. native targeting) |
118-
| `RUNTIME` | | The target runtime ecosystem -- default unset, `FreeRTOS-lwIP` and `Linux-lwIP` are recognized |
118+
| `RUNTIME` | | The target runtime ecosystem -- default unset, `FreeRTOS-lwIP`, `Linux-lwIP` and `ThreadX-NetXDuo` are recognized |
119119
| `C_WARNFLAGS` | | The warning flags to use (overriding the generally applicable defaults) |
120120
| `STATIC` | | Build statically linked unit tests |
121121
| `STRIPPED` | | Strip binaries of debugging symbols |

src/wolfsentry_util.c

Lines changed: 212 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,132 @@
2525

2626
#define WOLFSENTRY_SOURCE_ID WOLFSENTRY_SOURCE_ID_WOLFSENTRY_UTIL_C
2727

28+
#if !defined(WOLFSENTRY_HAVE_GNU_ATOMICS) && defined(THREADX)
29+
/* ThreadX atomic operations implementation - global mutex approach */
30+
static TX_MUTEX wolfsentry_threadx_atomic_mutex;
31+
static int wolfsentry_threadx_atomic_mutex_initialized = 0;
32+
33+
/* Initialize the global atomic mutex (call once at startup) */
34+
int wolfsentry_threadx_atomic_init_global(void) {
35+
if (!wolfsentry_threadx_atomic_mutex_initialized) {
36+
if (tx_mutex_create(&wolfsentry_threadx_atomic_mutex,
37+
(char *)"WolfSentry_Global_Atomic", TX_NO_INHERIT) == TX_SUCCESS) {
38+
wolfsentry_threadx_atomic_mutex_initialized = 1;
39+
return 0;
40+
}
41+
return -1;
42+
}
43+
return 0;
44+
}
45+
46+
/* Cleanup the global atomic mutex (call once at shutdown) */
47+
void wolfsentry_threadx_atomic_cleanup_global(void) {
48+
if (wolfsentry_threadx_atomic_mutex_initialized) {
49+
tx_mutex_delete(&wolfsentry_threadx_atomic_mutex);
50+
wolfsentry_threadx_atomic_mutex_initialized = 0;
51+
}
52+
}
53+
54+
/* ThreadX atomic operations using global mutex protection - type-generic using uintptr_t */
55+
uintptr_t wolfsentry_threadx_atomic_add_fetch(volatile uintptr_t *ptr, uintptr_t x) {
56+
uintptr_t result;
57+
if (!wolfsentry_threadx_atomic_mutex_initialized) {
58+
wolfsentry_threadx_atomic_init_global();
59+
}
60+
if (tx_mutex_get(&wolfsentry_threadx_atomic_mutex, TX_WAIT_FOREVER) != TX_SUCCESS) {
61+
return *ptr; /* Return current value on failure */
62+
}
63+
*ptr += x;
64+
result = *ptr;
65+
tx_mutex_put(&wolfsentry_threadx_atomic_mutex);
66+
return result;
67+
}
68+
69+
uintptr_t wolfsentry_threadx_atomic_sub_fetch(volatile uintptr_t *ptr, uintptr_t x) {
70+
uintptr_t result;
71+
if (!wolfsentry_threadx_atomic_mutex_initialized) {
72+
wolfsentry_threadx_atomic_init_global();
73+
}
74+
if (tx_mutex_get(&wolfsentry_threadx_atomic_mutex, TX_WAIT_FOREVER) != TX_SUCCESS) {
75+
return *ptr; /* Return current value on failure */
76+
}
77+
*ptr -= x;
78+
result = *ptr;
79+
tx_mutex_put(&wolfsentry_threadx_atomic_mutex);
80+
return result;
81+
}
82+
83+
uintptr_t wolfsentry_threadx_atomic_fetch_add(volatile uintptr_t *ptr, uintptr_t x) {
84+
uintptr_t result;
85+
if (!wolfsentry_threadx_atomic_mutex_initialized) {
86+
wolfsentry_threadx_atomic_init_global();
87+
}
88+
if (tx_mutex_get(&wolfsentry_threadx_atomic_mutex, TX_WAIT_FOREVER) != TX_SUCCESS) {
89+
return *ptr; /* Return current value on failure */
90+
}
91+
result = *ptr;
92+
*ptr += x;
93+
tx_mutex_put(&wolfsentry_threadx_atomic_mutex);
94+
return result;
95+
}
96+
97+
uintptr_t wolfsentry_threadx_atomic_fetch_sub(volatile uintptr_t *ptr, uintptr_t x) {
98+
uintptr_t result;
99+
if (!wolfsentry_threadx_atomic_mutex_initialized) {
100+
wolfsentry_threadx_atomic_init_global();
101+
}
102+
if (tx_mutex_get(&wolfsentry_threadx_atomic_mutex, TX_WAIT_FOREVER) != TX_SUCCESS) {
103+
return *ptr; /* Return current value on failure */
104+
}
105+
result = *ptr;
106+
*ptr -= x;
107+
tx_mutex_put(&wolfsentry_threadx_atomic_mutex);
108+
return result;
109+
}
110+
111+
void wolfsentry_threadx_atomic_store(volatile uintptr_t *ptr, uintptr_t x) {
112+
if (!wolfsentry_threadx_atomic_mutex_initialized) {
113+
wolfsentry_threadx_atomic_init_global();
114+
}
115+
if (tx_mutex_get(&wolfsentry_threadx_atomic_mutex, TX_WAIT_FOREVER) != TX_SUCCESS) {
116+
return;
117+
}
118+
*ptr = x;
119+
tx_mutex_put(&wolfsentry_threadx_atomic_mutex);
120+
}
121+
122+
uintptr_t wolfsentry_threadx_atomic_load(volatile uintptr_t *ptr) {
123+
uintptr_t result;
124+
if (!wolfsentry_threadx_atomic_mutex_initialized) {
125+
wolfsentry_threadx_atomic_init_global();
126+
}
127+
if (tx_mutex_get(&wolfsentry_threadx_atomic_mutex, TX_WAIT_FOREVER) != TX_SUCCESS) {
128+
return *ptr; /* Return current value on failure */
129+
}
130+
result = *ptr;
131+
tx_mutex_put(&wolfsentry_threadx_atomic_mutex);
132+
return result;
133+
}
134+
135+
int wolfsentry_threadx_atomic_compare_exchange(volatile uintptr_t *ptr, uintptr_t *expected, uintptr_t desired) {
136+
int success = 0;
137+
if (!wolfsentry_threadx_atomic_mutex_initialized) {
138+
wolfsentry_threadx_atomic_init_global();
139+
}
140+
if (tx_mutex_get(&wolfsentry_threadx_atomic_mutex, TX_WAIT_FOREVER) != TX_SUCCESS) {
141+
return 0;
142+
}
143+
if (*ptr == *expected) {
144+
*ptr = desired;
145+
success = 1;
146+
} else {
147+
*expected = *ptr;
148+
}
149+
tx_mutex_put(&wolfsentry_threadx_atomic_mutex);
150+
return success;
151+
}
152+
#endif /* THREADX */
153+
28154
#ifdef WOLFSENTRY_ERROR_STRINGS
29155

30156
static const char *user_defined_sources[WOLFSENTRY_SOURCE_ID_MAX - WOLFSENTRY_SOURCE_ID_USER_BASE + 1] = {0};
@@ -812,8 +938,10 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_init_thread_context(struct wolfse
812938
* the held lock can be safely locked recursively from within the
813939
* interrupt context.
814940
*/
815-
if (thread_context->id == (wolfsentry_thread_id_t)((uintptr_t)WOLFSENTRY_THREAD_NO_ID - 0xffffff))
816-
WOLFSENTRY_ATOMIC_INCREMENT(fallback_thread_id_counter, 0xffffff);
941+
if (thread_context->id == (wolfsentry_thread_id_t)((uintptr_t)WOLFSENTRY_THREAD_NO_ID - 0xffffff)) {
942+
(void)WOLFSENTRY_ATOMIC_INCREMENT(fallback_thread_id_counter, 0xffffff);
943+
}
944+
(void)fallback_thread_id_counter;
817945
WOLFSENTRY_SUCCESS_RETURN(USED_FALLBACK);
818946
} else
819947
WOLFSENTRY_RETURN_OK;
@@ -1509,6 +1637,73 @@ static int freertos_sem_destroy( sem_t * sem )
15091637

15101638
#define sem_destroy freertos_sem_destroy
15111639

1640+
#elif defined(THREADX)
1641+
1642+
#ifndef ETIMEDOUT
1643+
#define ETIMEDOUT 110 /* Connection timed out */
1644+
#endif
1645+
1646+
#define sem_init threadx_sem_init
1647+
static int threadx_sem_init( sem_t * sem,
1648+
int pshared,
1649+
unsigned value )
1650+
{
1651+
(void)pshared;
1652+
if (tx_semaphore_create(sem, NULL, value) != TX_SUCCESS) {
1653+
errno = EINVAL;
1654+
WOLFSENTRY_RETURN_VALUE(-1);
1655+
}
1656+
WOLFSENTRY_RETURN_VALUE(0);
1657+
}
1658+
#define sem_post threadx_sem_post
1659+
static int threadx_sem_post( sem_t * sem )
1660+
{
1661+
if (tx_semaphore_put(sem) != TX_SUCCESS) {
1662+
errno = EINVAL;
1663+
WOLFSENTRY_RETURN_VALUE(-1);
1664+
}
1665+
WOLFSENTRY_RETURN_VALUE(0);
1666+
}
1667+
#define sem_timedwait threadx_sem_timedwait
1668+
static int threadx_sem_timedwait( sem_t * sem,
1669+
const struct timespec * abstime )
1670+
{
1671+
if (tx_semaphore_get(sem, (uint32_t)(TX_TICK_TIME_MS *
1672+
(abstime->tv_sec * 1000) + (abstime->tv_nsec / 1000000))) != TX_SUCCESS) {
1673+
errno = EINVAL;
1674+
WOLFSENTRY_RETURN_VALUE(-1);
1675+
}
1676+
WOLFSENTRY_RETURN_VALUE(0);
1677+
}
1678+
#define sem_wait threadx_sem_wait
1679+
static int threadx_sem_wait( sem_t * sem )
1680+
{
1681+
if (tx_semaphore_get(sem, TX_WAIT_FOREVER) != TX_SUCCESS) {
1682+
errno = EINVAL;
1683+
WOLFSENTRY_RETURN_VALUE(-1);
1684+
}
1685+
WOLFSENTRY_RETURN_VALUE(0);
1686+
}
1687+
#define sem_trywait threadx_sem_trywait
1688+
static int threadx_sem_trywait( sem_t * sem )
1689+
{
1690+
if (tx_semaphore_get(sem, 0) != TX_SUCCESS) {
1691+
errno = EINVAL;
1692+
WOLFSENTRY_RETURN_VALUE(-1);
1693+
}
1694+
WOLFSENTRY_RETURN_VALUE(0);
1695+
}
1696+
static int threadx_sem_destroy( sem_t * sem )
1697+
{
1698+
if (tx_semaphore_delete(sem) != TX_SUCCESS) {
1699+
errno = EINVAL;
1700+
WOLFSENTRY_RETURN_VALUE(-1);
1701+
}
1702+
WOLFSENTRY_RETURN_VALUE(0);
1703+
}
1704+
1705+
#define sem_destroy threadx_sem_destroy
1706+
15121707
#else
15131708

15141709
#error Semaphore builtins not implemented for target -- build wolfSentry with -DWOLFSENTRY_NO_SEM_BUILTIN, and supply semaphore implementation with struct wolfsentry_host_platform_interface argument to wolfsentry_init().
@@ -2847,7 +3042,7 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_shared2mutex_abstimed(struct
28473042
WOLFSENTRY_ERROR_RETURN(SYS_OP_FATAL);
28483043
}
28493044
}
2850-
} else
3045+
} else
28513046
ret = sem_timedwait(&lock->sem_read2write_waiters, abs_timeout);
28523047

28533048
if (ret < 0) {
@@ -3317,6 +3512,19 @@ static wolfsentry_errcode_t wolfsentry_builtin_get_time(void *context, wolfsentr
33173512
WOLFSENTRY_RETURN_OK;
33183513
}
33193514

3515+
#elif defined(THREADX)
3516+
3517+
static wolfsentry_errcode_t wolfsentry_builtin_get_time(void *context, wolfsentry_time_t *now) {
3518+
struct timespec ts;
3519+
uint32_t tick_count;
3520+
(void)context;
3521+
tick_count = tx_time_get();
3522+
ts.tv_sec = (long)tick_count / TX_TICK_TIME_MS;
3523+
ts.tv_nsec = (long)(tick_count % TX_TICK_TIME_MS) * 1000000;
3524+
*now = ((wolfsentry_time_t)ts.tv_sec * (wolfsentry_time_t)1000000) + ((wolfsentry_time_t)ts.tv_nsec / (wolfsentry_time_t)1000);
3525+
WOLFSENTRY_RETURN_OK;
3526+
}
3527+
33203528
#else
33213529

33223530
#include <time.h>
@@ -4264,7 +4472,7 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_base64_decode(const char *src, si
42644472
const char *src_end = src + src_len;
42654473
size_t dest_len = 0;
42664474

4267-
if (WOLFSENTRY_BASE64_DECODED_BUFSPC(src, src_len) > *dest_spc)
4475+
if (WOLFSENTRY_BASE64_DECODED_BUFSPC(src, (int)src_len) > (int)*dest_spc)
42684476
WOLFSENTRY_ERROR_RETURN(BUFFER_TOO_SMALL);
42694477

42704478
for (; src < src_end; ++src) {

wolfsentry/wolfsentry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3341,7 +3341,7 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_user_values_iterate_end(
33413341
(((((len)+3)/4)*3) - ((len) > 1 ? \
33423342
((buf)[(len)-1] == '=') : \
33433343
0) \
3344-
- ((len) > 2 ? ((buf)[(len)-2] == '=') : 0)) \
3344+
- ((len) > 2 ? ((buf)[(len)-2] == '=') : 0))
33453345
/*!< \brief Given valid base64 string `buf` of length `len`, evaluates to the exact decoded length. @hideinitializer */
33463346

33473347
WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_base64_decode(

wolfsentry/wolfsentry_errcodes.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#endif
4040

4141
typedef int32_t wolfsentry_errcode_t; /*!< \brief The structured result code type for wolfSentry. It encodes a failure or success code, a source code file ID, and a line number. */
42-
#ifdef FREERTOS
42+
#if defined(FREERTOS) || defined(THREADX)
4343
#define WOLFSENTRY_ERRCODE_FMT "%d"
4444
#elif defined(PRId32)
4545
#define WOLFSENTRY_ERRCODE_FMT "%" PRId32
@@ -141,9 +141,9 @@ static inline int WOLFSENTRY_ERROR_DECODE_LINE_NUMBER(wolfsentry_errcode_t x) {
141141
#define WOLFSENTRY_ERROR_FMT_ARGS(x) WOLFSENTRY_ERROR_DECODE_ERROR_CODE(x), WOLFSENTRY_ERROR_DECODE_SOURCE_ID(x), WOLFSENTRY_ERROR_DECODE_LINE_NUMBER(x)
142142
#endif /* WOLFSENTRY_ERROR_STRINGS */
143143

144-
#define WOLFSENTRY_ERROR_ENCODE(name) WOLFSENTRY_ERROR_ENCODE_0(WOLFSENTRY_ERROR_ID_ ## name)
144+
#define WOLFSENTRY_ERROR_ENCODE(name) WOLFSENTRY_ERROR_ENCODE_0(WOLFSENTRY_ERROR_ID_##name)
145145
/*!< \brief Compute a `wolfsentry_errcode_t` encoding the current source ID and line number, and the designated short-form error `name` (e.g. `INVALID_ARG`). @hideinitializer */
146-
#define WOLFSENTRY_SUCCESS_ENCODE(x) WOLFSENTRY_ERROR_ENCODE_0(WOLFSENTRY_SUCCESS_ID_ ## x)
146+
#define WOLFSENTRY_SUCCESS_ENCODE(x) WOLFSENTRY_ERROR_ENCODE_0(WOLFSENTRY_SUCCESS_ID_##x)
147147
/*!< \brief Compute a `wolfsentry_errcode_t` encoding the current source ID and line number, and the designated short-form success `name` (e.g. `OK`). @hideinitializer */
148148

149149
#ifdef WOLFSENTRY_FOR_DOXYGEN

wolfsentry/wolfsentry_settings.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,15 @@
110110
#endif
111111
#endif
112112

113+
#ifdef THREADX
114+
#ifdef NEED_THREADX_TYPES
115+
#include <types.h>
116+
#include <stdio.h>
117+
#endif
118+
#include <tx_api.h>
119+
#endif
120+
121+
113122
/*! \addtogroup wolfsentry_init
114123
* @{
115124
*/
@@ -193,13 +202,13 @@
193202
#endif
194203

195204
#ifndef WOLFSENTRY_USE_NONPOSIX_SEMAPHORES
196-
#if defined(__MACH__) || defined(FREERTOS) || defined(_WIN32)
205+
#if defined(__MACH__) || defined(FREERTOS) || defined(_WIN32) || defined(THREADX)
197206
#define WOLFSENTRY_USE_NONPOSIX_SEMAPHORES
198207
#endif
199208
#endif
200209

201210
#ifndef WOLFSENTRY_USE_NONPOSIX_THREADS
202-
#if defined(FREERTOS) || defined(_WIN32)
211+
#if defined(FREERTOS) || defined(_WIN32) || defined(THREADX)
203212
#define WOLFSENTRY_USE_NONPOSIX_THREADS
204213
#endif
205214
#endif
@@ -543,6 +552,10 @@ typedef uint16_t wolfsentry_priority_t;
543552

544553
#define sem_t StaticSemaphore_t
545554

555+
#elif defined(THREADX)
556+
557+
#define sem_t TX_SEMAPHORE
558+
546559
#else
547560

548561
/*! @} */
@@ -589,6 +602,8 @@ typedef uint16_t wolfsentry_priority_t;
589602
typedef pthread_t wolfsentry_thread_id_t;
590603
#elif defined(FREERTOS)
591604
typedef TaskHandle_t wolfsentry_thread_id_t;
605+
#elif defined(THREADX)
606+
typedef TX_THREAD* wolfsentry_thread_id_t;
592607
#else
593608
#error Must supply WOLFSENTRY_THREAD_ID_T for WOLFSENTRY_THREADSAFE on non-POSIX targets.
594609
#endif
@@ -598,6 +613,8 @@ typedef uint16_t wolfsentry_priority_t;
598613
#define WOLFSENTRY_THREAD_GET_ID_HANDLER pthread_self
599614
#elif defined(FREERTOS)
600615
#define WOLFSENTRY_THREAD_GET_ID_HANDLER xTaskGetCurrentTaskHandle
616+
#elif defined(THREADX)
617+
#define WOLFSENTRY_THREAD_GET_ID_HANDLER tx_thread_identify
601618
#else
602619
#error Must supply WOLFSENTRY_THREAD_GET_ID_HANDLER for WOLFSENTRY_THREADSAFE on non-POSIX targets.
603620
#endif

wolfsentry/wolfsentry_util.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,36 @@
165165
#define WOLFSENTRY_ATOMIC_CMPXCHG(ptr, expected, desired, weak_p, success_memorder, failure_memorder) __atomic_compare_exchange_n(ptr, expected, desired, weak_p, success_memorder, failure_memorder)
166166
/*!< \brief Sets `*ptr` to `desired` and returns true iff `*ptr` has the value `*expected`, otherwise sets `*expected` to the actual value of `*ptr` and returns false. @hideinitializer */
167167

168+
#elif defined(THREADX)
169+
170+
/* ThreadX atomic function declarations */
171+
int wolfsentry_threadx_atomic_init_global(void);
172+
void wolfsentry_threadx_atomic_cleanup_global(void);
173+
uintptr_t wolfsentry_threadx_atomic_add_fetch(volatile uintptr_t *ptr, uintptr_t x);
174+
uintptr_t wolfsentry_threadx_atomic_sub_fetch(volatile uintptr_t *ptr, uintptr_t x);
175+
uintptr_t wolfsentry_threadx_atomic_fetch_add(volatile uintptr_t *ptr, uintptr_t x);
176+
uintptr_t wolfsentry_threadx_atomic_fetch_sub(volatile uintptr_t *ptr, uintptr_t x);
177+
void wolfsentry_threadx_atomic_store(volatile uintptr_t *ptr, uintptr_t x);
178+
uintptr_t wolfsentry_threadx_atomic_load(volatile uintptr_t *ptr);
179+
int wolfsentry_threadx_atomic_compare_exchange(volatile uintptr_t *ptr, uintptr_t *expected, uintptr_t desired);
180+
181+
/* Define macros to use ThreadX atomic operations - compatible with existing interface */
182+
#define WOLFSENTRY_ATOMIC_INCREMENT(i, x) ((__typeof__(i))wolfsentry_threadx_atomic_add_fetch((volatile uintptr_t *)&(i), (uintptr_t)(x)))
183+
#define WOLFSENTRY_ATOMIC_DECREMENT(i, x) ((__typeof__(i))wolfsentry_threadx_atomic_sub_fetch((volatile uintptr_t *)&(i), (uintptr_t)(x)))
184+
#define WOLFSENTRY_ATOMIC_POSTINCREMENT(i, x) ((__typeof__(i))wolfsentry_threadx_atomic_fetch_add((volatile uintptr_t *)&(i), (uintptr_t)(x)))
185+
#define WOLFSENTRY_ATOMIC_POSTDECREMENT(i, x) ((__typeof__(i))wolfsentry_threadx_atomic_fetch_sub((volatile uintptr_t *)&(i), (uintptr_t)(x)))
186+
#define WOLFSENTRY_ATOMIC_STORE(i, x) wolfsentry_threadx_atomic_store((volatile uintptr_t *)&(i), (uintptr_t)(x))
187+
#define WOLFSENTRY_ATOMIC_LOAD(i) ((__typeof__(i))wolfsentry_threadx_atomic_load((volatile uintptr_t *)&(i)))
188+
#define WOLFSENTRY_ATOMIC_CMPXCHG(ptr, expected, desired, weak_p, success_memorder, failure_memorder) \
189+
wolfsentry_threadx_atomic_compare_exchange((volatile uintptr_t *)(ptr), (uintptr_t *)(expected), (uintptr_t)(desired))
190+
168191
#else
169192

170193
#if !defined(WOLFSENTRY_ATOMIC_INCREMENT) || !defined(WOLFSENTRY_ATOMIC_DECREMENT) || \
171194
!defined(WOLFSENTRY_ATOMIC_POSTINCREMENT) || !defined(WOLFSENTRY_ATOMIC_POSTDECREMENT) || \
172195
!defined(WOLFSENTRY_ATOMIC_STORE) || !defined(WOLFSENTRY_ATOMIC_LOAD) || \
173196
!defined(WOLFSENTRY_ATOMIC_CMPXCHG)
174-
#error Missing required atomic implementation(s)
197+
#error Missing required atomic implementation(s)
175198
#endif
176199

177200
#endif /* WOLFSENTRY_HAVE_GNU_ATOMICS */

0 commit comments

Comments
 (0)