Commit 0f63d113 authored by Peng Chen's avatar Peng Chen Committed by Anas Nashif
Browse files

cmsis_rtos_v1: fix thread instances management.



add a bitarray into struct osThreadDef_t to indicate whether the
thread is used or not, then we can get the first available thread
by searching this array when creating a new thread, and update this
array to add a free thread when terminating a thread.

Signed-off-by: default avatarChen Peng1 <peng1.chen@intel.com>
parent 40f4091d
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@
#include <stdint.h>
#include <stddef.h>
#include <kernel.h>
#include <sys/bitarray.h>
 
#ifdef  __cplusplus
extern "C"
@@ -172,6 +173,8 @@ typedef struct os_thread_def {
  struct k_poll_signal *poll_signal;
  struct k_poll_event   *poll_event;
  int32_t            signal_results;
  ///< a bitarray used to indicate whether the thread is used or not, 0: unused, 1: used
  void                 *status_mask;
} osThreadDef_t;
 
/// Timer Definition structure contains timer parameters.
@@ -288,8 +291,11 @@ static K_THREAD_STACK_ARRAY_DEFINE(stacks_##name, instances, CONFIG_CMSIS_THREAD
static struct k_thread cm_thread_##name[instances]; \
static struct k_poll_signal wait_signal_##name; \
static struct k_poll_event wait_events_##name; \
static SYS_BITARRAY_DEFINE(bitarray_##name, instances); \
static osThreadDef_t os_thread_def_##name = \
{ (name), (priority), (instances), (stacksz), (void *)(stacks_##name), (cm_thread_##name), (&wait_signal_##name), (&wait_events_##name), 0 }
{ (name), (priority), (instances), (stacksz), (void *)(stacks_##name), \
	(cm_thread_##name), (&wait_signal_##name), \
	(&wait_events_##name), 0, (void *)(&bitarray_##name)}
#endif
 
/// Access a Thread definition.
+8 −0
Original line number Diff line number Diff line
@@ -1460,6 +1460,10 @@ static inline void unpend_all(_wait_q_t *wait_q)
	}
}

#ifdef CONFIG_CMSIS_RTOS_V1
extern void z_thread_cmsis_status_mask_clear(struct k_thread *thread);
#endif

static void end_thread(struct k_thread *thread)
{
	/* We hold the lock, and the thread is known not to be running
@@ -1482,6 +1486,10 @@ static void end_thread(struct k_thread *thread)

		z_thread_monitor_exit(thread);

#ifdef CONFIG_CMSIS_RTOS_V1
		z_thread_cmsis_status_mask_clear(thread);
#endif

#ifdef CONFIG_USERSPACE
		z_mem_domain_exit_thread(thread);
		z_thread_perms_all_clear(thread);
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ config CMSIS_RTOS_V1
	bool "CMSIS RTOS v1 API"
	depends on THREAD_CUSTOM_DATA
	depends on POLL
	depends on THREAD_STACK_INFO
	help
	  This enables CMSIS RTOS v1 API support. This is an OS-integration
	  layer which allows applications using CMSIS RTOS APIs to build on
+34 −3
Original line number Diff line number Diff line
@@ -34,6 +34,23 @@ static void zephyr_thread_wrapper(void *arg1, void *arg2, void *arg3)
	fun_ptr(arg1);
}

/* clear related bit in cmsis thread status bitarray
 * when terminating a thread
 */
void z_thread_cmsis_status_mask_clear(struct k_thread *thread)
{
	uint32_t offset, instance;

	osThreadDef_t *thread_def = (osThreadDef_t *)(thread->custom_data);

	if (thread_def != NULL) {
		/* get thread instance index according to stack address */
		offset = thread->stack_info.start - (uintptr_t)thread_def->stack_mem;
		instance = offset / K_THREAD_STACK_LEN(CONFIG_CMSIS_THREAD_MAX_STACK_SIZE);
		sys_bitarray_clear_bit((sys_bitarray_t *)(thread_def->status_mask), instance);
	}
}

/**
 * @brief Create a new thread.
 */
@@ -43,6 +60,8 @@ osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *arg)
	uint32_t prio;
	k_tid_t tid;
	uint32_t stacksz;
	int ret;
	size_t instance;

	k_thread_stack_t
	   (*stk_ptr)[K_THREAD_STACK_LEN(CONFIG_CMSIS_THREAD_MAX_STACK_SIZE)];
@@ -67,6 +86,13 @@ osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *arg)
		 (thread_def->tpriority <= osPriorityRealtime),
		 "invalid priority\n");

	/* get an available thread instance */
	ret = sys_bitarray_alloc((sys_bitarray_t *)(thread_def->status_mask),
			1, &instance);
	if (ret != 0) {
		return NULL;
	}

	stacksz = thread_def->stacksize;
	if (stacksz == 0U) {
		stacksz = CONFIG_CMSIS_THREAD_MAX_STACK_SIZE;
@@ -77,17 +103,22 @@ osThreadId osThreadCreate(const osThreadDef_t *thread_def, void *arg)
			K_POLL_MODE_NOTIFY_ONLY, thread_def->poll_signal);

	cm_thread = thread_def->cm_thread;
	atomic_dec((atomic_t *)&thread_def->instances);
	stk_ptr = thread_def->stack_mem;
	prio = cmsis_to_zephyr_priority(thread_def->tpriority);
	k_thread_custom_data_set((void *)thread_def);

	tid = k_thread_create(&cm_thread[thread_def->instances],
			stk_ptr[thread_def->instances], stacksz,
	tid = k_thread_create(&cm_thread[instance],
			stk_ptr[instance], stacksz,
			(k_thread_entry_t)zephyr_thread_wrapper,
			(void *)arg, NULL, thread_def->pthread,
			prio, 0, K_NO_WAIT);

	/* make custom_data pointer of thread point to its source thread_def,
	 * then we can use it to release thread instances
	 * when terminating threads
	 */
	tid->custom_data = (void *)thread_def;

	return ((osThreadId)tid);
}

+1 −0
Original line number Diff line number Diff line
@@ -6,3 +6,4 @@ CONFIG_MAX_THREAD_BYTES=4
CONFIG_IRQ_OFFLOAD=y
CONFIG_CMSIS_THREAD_MAX_STACK_SIZE=2048
CONFIG_SMP=n
CONFIG_THREAD_STACK_INFO=y
Loading