🎯 Sync smart & scheduler codes (#8537)

Signed-off-by: Shell <smokewood@qq.com>
Co-authored-by: xqyjlj <xqyjlj@126.com>
This commit is contained in:
Shell
2024-02-23 17:49:15 +08:00
committed by GitHub
co-authored by xqyjlj
parent 6fe69d7431
commit 71560bafb5
71 changed files with 6218 additions and 2329 deletions
@@ -352,7 +352,7 @@ static int dfs_romfs_getdents(struct dfs_file *file, struct dirent *dirp, uint32
d->d_namlen = rt_strlen(name);
d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
rt_strncpy(d->d_name, name, DFS_PATH_MAX);
rt_strncpy(d->d_name, name, DIRENT_NAME_MAX);
/* move to next position */
++ file->fpos;
+4 -1
View File
@@ -822,7 +822,10 @@ static int dfs_page_insert(struct dfs_page *page)
rt_list_insert_before(&aspace->list_inactive, &page->space_node);
aspace->pages_count ++;
RT_ASSERT(_dfs_page_insert(aspace, page) == 0);
if (_dfs_page_insert(aspace, page))
{
RT_ASSERT(0);
}
if (aspace->pages_count > RT_PAGECACHE_ASPACE_COUNT)
{
+4 -8
View File
@@ -21,9 +21,7 @@ static void _rt_pipe_resume_writer(struct rt_audio_pipe *pipe)
RT_ASSERT(pipe->flag & RT_PIPE_FLAG_BLOCK_WR);
/* get suspended thread */
thread = rt_list_entry(pipe->suspended_write_list.next,
struct rt_thread,
tlist);
thread = RT_THREAD_LIST_NODE_ENTRY(pipe->suspended_write_list.next);
/* resume the write thread */
rt_thread_resume(thread);
@@ -73,7 +71,7 @@ static rt_ssize_t rt_pipe_read(rt_device_t dev,
rt_thread_suspend(thread);
/* waiting on suspended read list */
rt_list_insert_before(&(pipe->suspended_read_list),
&(thread->tlist));
&RT_THREAD_LIST_NODE(thread));
rt_hw_interrupt_enable(level);
rt_schedule();
@@ -103,9 +101,7 @@ static void _rt_pipe_resume_reader(struct rt_audio_pipe *pipe)
RT_ASSERT(pipe->flag & RT_PIPE_FLAG_BLOCK_RD);
/* get suspended thread */
thread = rt_list_entry(pipe->suspended_read_list.next,
struct rt_thread,
tlist);
thread = RT_THREAD_LIST_NODE_ENTRY(pipe->suspended_read_list.next);
/* resume the read thread */
rt_thread_resume(thread);
@@ -161,7 +157,7 @@ static rt_ssize_t rt_pipe_write(rt_device_t dev,
rt_thread_suspend(thread);
/* waiting on suspended read list */
rt_list_insert_before(&(pipe->suspended_write_list),
&(thread->tlist));
&RT_THREAD_LIST_NODE(thread));
rt_hw_interrupt_enable(level);
rt_schedule();
+10 -6
View File
@@ -13,18 +13,22 @@
#include <rtconfig.h>
/**
* Completion
* Completion - A tiny IPC implementation for resource-constrained scenarios
*
* It's an IPC using one CPU word with the encoding:
*
* BIT | MAX-1 ----------------- 1 | 0 |
* CONTENT | suspended_thread & ~1 | completed flag |
*/
struct rt_completion
{
rt_uint32_t flag;
/* suspended list */
rt_list_t suspended_list;
struct rt_spinlock spinlock;
/* suspended thread, and completed flag */
rt_base_t susp_thread_n_flag;
};
#define RT_COMPLETION_INIT(comp) {0}
void rt_completion_init(struct rt_completion *completion);
rt_err_t rt_completion_wait(struct rt_completion *completion,
rt_int32_t timeout);
+1 -1
View File
@@ -8,6 +8,6 @@ if not GetDepend('RT_USING_HEAP'):
SrcRemove(src, 'dataqueue.c')
SrcRemove(src, 'pipe.c')
group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_DEVICE_IPC'], CPPPATH = CPPPATH)
group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_DEVICE_IPC'], CPPPATH = CPPPATH, LOCAL_CPPDEFINES=['__RT_IPC_SOURCE__'])
Return('group')
+64 -57
View File
@@ -8,13 +8,24 @@
* 2012-09-30 Bernard first version.
* 2021-08-18 chenyingchun add comments
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
* 2024-01-25 Shell reduce resource usage in completion for better synchronization
* and smaller footprint.
*/
#define DBG_TAG "drivers.ipc"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include <rthw.h>
#include <rtdevice.h>
#define RT_COMPLETED 1
#define RT_UNCOMPLETED 0
#define RT_COMPLETION_FLAG(comp) ((comp)->susp_thread_n_flag & 1)
#define RT_COMPLETION_THREAD(comp) ((rt_thread_t)((comp)->susp_thread_n_flag & ~1))
#define RT_COMPLETION_NEW_STAT(thread, flag) (((flag) & 1) | (((rt_base_t)thread) & ~1))
static struct rt_spinlock _completion_lock = RT_SPINLOCK_INIT;
/**
* @brief This function will initialize a completion object.
@@ -23,14 +34,9 @@
*/
void rt_completion_init(struct rt_completion *completion)
{
rt_base_t level;
RT_ASSERT(completion != RT_NULL);
rt_spin_lock_init(&(completion->spinlock));
level = rt_spin_lock_irqsave(&(completion->spinlock));
completion->flag = RT_UNCOMPLETED;
rt_list_init(&completion->suspended_list);
rt_spin_unlock_irqrestore(&(completion->spinlock), level);
completion->susp_thread_n_flag = RT_COMPLETION_NEW_STAT(RT_NULL, RT_UNCOMPLETED);
}
RTM_EXPORT(rt_completion_init);
@@ -64,11 +70,11 @@ rt_err_t rt_completion_wait(struct rt_completion *completion,
result = RT_EOK;
thread = rt_thread_self();
level = rt_spin_lock_irqsave(&(completion->spinlock));
if (completion->flag != RT_COMPLETED)
level = rt_spin_lock_irqsave(&_completion_lock);
if (RT_COMPLETION_FLAG(completion) != RT_COMPLETED)
{
/* only one thread can suspend on complete */
RT_ASSERT(rt_list_isempty(&(completion->suspended_list)));
RT_ASSERT(RT_COMPLETION_THREAD(completion) == RT_NULL);
if (timeout == 0)
{
@@ -81,40 +87,43 @@ rt_err_t rt_completion_wait(struct rt_completion *completion,
thread->error = RT_EOK;
/* suspend thread */
rt_thread_suspend_with_flag(thread, RT_UNINTERRUPTIBLE);
/* add to suspended list */
rt_list_insert_before(&(completion->suspended_list),
&(thread->tlist));
/* current context checking */
RT_DEBUG_NOT_IN_INTERRUPT;
/* start timer */
if (timeout > 0)
result = rt_thread_suspend_with_flag(thread, RT_UNINTERRUPTIBLE);
if (result == RT_EOK)
{
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),
RT_TIMER_CTRL_SET_TIME,
&timeout);
rt_timer_start(&(thread->thread_timer));
/* add to suspended thread */
completion->susp_thread_n_flag = RT_COMPLETION_NEW_STAT(thread, RT_UNCOMPLETED);
/* current context checking */
RT_DEBUG_NOT_IN_INTERRUPT;
/* start timer */
if (timeout > 0)
{
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),
RT_TIMER_CTRL_SET_TIME,
&timeout);
rt_timer_start(&(thread->thread_timer));
}
/* enable interrupt */
rt_spin_unlock_irqrestore(&_completion_lock, level);
/* do schedule */
rt_schedule();
/* thread is waked up */
result = thread->error;
level = rt_spin_lock_irqsave(&_completion_lock);
}
/* enable interrupt */
rt_spin_unlock_irqrestore(&(completion->spinlock), level);
/* do schedule */
rt_schedule();
/* thread is waked up */
result = thread->error;
level = rt_spin_lock_irqsave(&(completion->spinlock));
}
}
/* clean completed flag */
completion->flag = RT_UNCOMPLETED;
/* clean completed flag & remove susp_thread on the case of waking by timeout */
completion->susp_thread_n_flag = RT_COMPLETION_NEW_STAT(RT_NULL, RT_UNCOMPLETED);
__exit:
rt_spin_unlock_irqrestore(&(completion->spinlock), level);
rt_spin_unlock_irqrestore(&_completion_lock, level);
return result;
}
@@ -128,35 +137,33 @@ RTM_EXPORT(rt_completion_wait);
void rt_completion_done(struct rt_completion *completion)
{
rt_base_t level;
rt_err_t error;
rt_thread_t suspend_thread;
RT_ASSERT(completion != RT_NULL);
if (completion->flag == RT_COMPLETED)
level = rt_spin_lock_irqsave(&_completion_lock);
if (RT_COMPLETION_FLAG(completion) == RT_COMPLETED)
{
rt_spin_unlock_irqrestore(&_completion_lock, level);
return;
}
level = rt_spin_lock_irqsave(&(completion->spinlock));
completion->flag = RT_COMPLETED;
if (!rt_list_isempty(&(completion->suspended_list)))
suspend_thread = RT_COMPLETION_THREAD(completion);
if (suspend_thread)
{
/* there is one thread in suspended list */
struct rt_thread *thread;
/* get thread entry */
thread = rt_list_entry(completion->suspended_list.next,
struct rt_thread,
tlist);
/* resume it */
rt_thread_resume(thread);
rt_spin_unlock_irqrestore(&(completion->spinlock), level);
error = rt_thread_resume(suspend_thread);
if (error)
{
LOG_D("%s: failed to resume thread", __func__);
}
}
/* perform a schedule */
rt_schedule();
}
else
{
rt_spin_unlock_irqrestore(&(completion->spinlock), level);
}
completion->susp_thread_n_flag = RT_COMPLETION_NEW_STAT(RT_NULL, RT_COMPLETED);
rt_spin_unlock_irqrestore(&_completion_lock, level);
}
RTM_EXPORT(rt_completion_done);
+59 -100
View File
@@ -8,6 +8,7 @@
* 2012-09-30 Bernard first version.
* 2016-10-31 armink fix some resume push and pop thread bugs
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
* 2024-01-25 Shell porting to susp_list API
*/
#include <rthw.h>
@@ -121,27 +122,32 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
thread->error = RT_EOK;
/* suspend thread on the push list */
rt_thread_suspend_with_flag(thread, RT_UNINTERRUPTIBLE);
rt_list_insert_before(&(queue->suspended_push_list), &(thread->tlist));
/* start timer */
if (timeout > 0)
result = rt_thread_suspend_to_list(thread, &queue->suspended_push_list,
RT_IPC_FLAG_FIFO, RT_UNINTERRUPTIBLE);
if (result == RT_EOK)
{
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),
RT_TIMER_CTRL_SET_TIME,
&timeout);
rt_timer_start(&(thread->thread_timer));
/* start timer */
if (timeout > 0)
{
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),
RT_TIMER_CTRL_SET_TIME,
&timeout);
rt_timer_start(&(thread->thread_timer));
}
/* enable interrupt */
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
/* do schedule */
rt_schedule();
/* thread is waked up */
level = rt_spin_lock_irqsave(&(queue->spinlock));
/* error may be modified by waker, so take the lock before accessing it */
result = thread->error;
}
/* enable interrupt */
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
/* do schedule */
rt_schedule();
/* thread is waked up */
result = thread->error;
level = rt_spin_lock_irqsave(&(queue->spinlock));
if (result != RT_EOK) goto __exit;
}
@@ -159,15 +165,10 @@ rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
}
/* there is at least one thread in suspended list */
if (!rt_list_isempty(&(queue->suspended_pop_list)))
if (rt_susp_list_dequeue(&queue->suspended_push_list,
RT_THREAD_RESUME_RES_THR_ERR))
{
/* get thread entry */
thread = rt_list_entry(queue->suspended_pop_list.next,
struct rt_thread,
tlist);
/* resume it */
rt_thread_resume(thread);
/* unlock and perform a schedule */
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
/* perform a schedule */
@@ -239,29 +240,32 @@ rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
thread->error = RT_EOK;
/* suspend thread on the pop list */
rt_thread_suspend_with_flag(thread, RT_UNINTERRUPTIBLE);
rt_list_insert_before(&(queue->suspended_pop_list), &(thread->tlist));
/* start timer */
if (timeout > 0)
result = rt_thread_suspend_to_list(thread, &queue->suspended_pop_list,
RT_IPC_FLAG_FIFO, RT_UNINTERRUPTIBLE);
if (result == RT_EOK)
{
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),
RT_TIMER_CTRL_SET_TIME,
&timeout);
rt_timer_start(&(thread->thread_timer));
/* start timer */
if (timeout > 0)
{
/* reset the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),
RT_TIMER_CTRL_SET_TIME,
&timeout);
rt_timer_start(&(thread->thread_timer));
}
/* enable interrupt */
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
/* do schedule */
rt_schedule();
/* thread is waked up */
level = rt_spin_lock_irqsave(&(queue->spinlock));
result = thread->error;
if (result != RT_EOK)
goto __exit;
}
/* enable interrupt */
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
/* do schedule */
rt_schedule();
/* thread is waked up */
result = thread->error;
level = rt_spin_lock_irqsave(&(queue->spinlock));
if (result != RT_EOK)
goto __exit;
}
*data_ptr = queue->queue[queue->get_index].data_ptr;
@@ -280,15 +284,10 @@ rt_err_t rt_data_queue_pop(struct rt_data_queue *queue,
if (rt_data_queue_len(queue) <= queue->lwm)
{
/* there is at least one thread in suspended list */
if (!rt_list_isempty(&(queue->suspended_push_list)))
if (rt_susp_list_dequeue(&queue->suspended_push_list,
RT_THREAD_RESUME_RES_THR_ERR))
{
/* get thread entry */
thread = rt_list_entry(queue->suspended_push_list.next,
struct rt_thread,
tlist);
/* resume it */
rt_thread_resume(thread);
/* unlock and perform a schedule */
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
/* perform a schedule */
@@ -364,7 +363,6 @@ RTM_EXPORT(rt_data_queue_peek);
void rt_data_queue_reset(struct rt_data_queue *queue)
{
rt_base_t level;
struct rt_thread *thread;
RT_ASSERT(queue != RT_NULL);
RT_ASSERT(queue->magic == DATAQUEUE_MAGIC);
@@ -382,52 +380,13 @@ void rt_data_queue_reset(struct rt_data_queue *queue)
/* wakeup all suspend threads */
/* resume on pop list */
while (!rt_list_isempty(&(queue->suspended_pop_list)))
{
/* disable interrupt */
level = rt_spin_lock_irqsave(&(queue->spinlock));
/* get next suspend thread */
thread = rt_list_entry(queue->suspended_pop_list.next,
struct rt_thread,
tlist);
/* set error code to -RT_ERROR */
thread->error = -RT_ERROR;
/*
* resume thread
* In rt_thread_resume function, it will remove current thread from
* suspend list
*/
rt_thread_resume(thread);
/* enable interrupt */
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
}
rt_susp_list_resume_all_irq(&queue->suspended_pop_list, RT_ERROR,
&(queue->spinlock));
/* resume on push list */
while (!rt_list_isempty(&(queue->suspended_push_list)))
{
/* disable interrupt */
level = rt_spin_lock_irqsave(&(queue->spinlock));
rt_susp_list_resume_all_irq(&queue->suspended_push_list, RT_ERROR,
&(queue->spinlock));
/* get next suspend thread */
thread = rt_list_entry(queue->suspended_push_list.next,
struct rt_thread,
tlist);
/* set error code to -RT_ERROR */
thread->error = -RT_ERROR;
/*
* resume thread
* In rt_thread_resume function, it will remove current thread from
* suspend list
*/
rt_thread_resume(thread);
/* enable interrupt */
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
}
rt_exit_critical();
rt_schedule();
+9 -12
View File
@@ -64,7 +64,10 @@ static void _workqueue_thread_entry(void *parameter)
{
/* no software timer exist, suspend self. */
rt_thread_suspend_with_flag(rt_thread_self(), RT_UNINTERRUPTIBLE);
/* release lock after suspend so we will not lost any wakeups */
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
rt_schedule();
continue;
}
@@ -105,13 +108,11 @@ static rt_err_t _workqueue_submit_work(struct rt_workqueue *queue,
work->workqueue = queue;
/* whether the workqueue is doing work */
if (queue->work_current == RT_NULL &&
((queue->work_thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK))
if (queue->work_current == RT_NULL)
{
/* resume work thread */
/* resume work thread, and do a re-schedule if succeed */
rt_thread_resume(queue->work_thread);
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
rt_schedule();
}
else
{
@@ -187,13 +188,11 @@ static void _delayed_work_timeout_handler(void *parameter)
work->flags |= RT_WORK_STATE_PENDING;
}
/* whether the workqueue is doing work */
if (queue->work_current == RT_NULL &&
((queue->work_thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK))
if (queue->work_current == RT_NULL)
{
/* resume work thread */
/* resume work thread, and do a re-schedule if succeed */
rt_thread_resume(queue->work_thread);
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
rt_schedule();
}
else
{
@@ -346,13 +345,11 @@ rt_err_t rt_workqueue_urgent_work(struct rt_workqueue *queue, struct rt_work *wo
rt_list_remove(&(work->list));
rt_list_insert_after(&queue->work_list, &(work->list));
/* whether the workqueue is doing work */
if (queue->work_current == RT_NULL &&
((queue->work_thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK))
if (queue->work_current == RT_NULL)
{
/* resume work thread */
/* resume work thread, and do a re-schedule if succeed */
rt_thread_resume(queue->work_thread);
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
rt_schedule();
}
else
{
+20 -27
View File
@@ -216,15 +216,23 @@ long list_thread(void)
rt_uint8_t *ptr;
#ifdef RT_USING_SMP
if (thread->oncpu != RT_CPU_DETACHED)
rt_kprintf("%-*.*s %3d %3d %4d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->oncpu, thread->bind_cpu, thread->current_priority);
/* no synchronization applied since it's only for debug */
if (RT_SCHED_CTX(thread).oncpu != RT_CPU_DETACHED)
rt_kprintf("%-*.*s %3d %3d %4d ", maxlen, RT_NAME_MAX,
thread->parent.name, RT_SCHED_CTX(thread).oncpu,
RT_SCHED_CTX(thread).bind_cpu,
RT_SCHED_PRIV(thread).current_priority);
else
rt_kprintf("%-*.*s N/A %3d %4d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->bind_cpu, thread->current_priority);
rt_kprintf("%-*.*s N/A %3d %4d ", maxlen, RT_NAME_MAX,
thread->parent.name,
RT_SCHED_CTX(thread).bind_cpu,
RT_SCHED_PRIV(thread).current_priority);
#else
rt_kprintf("%-*.*s %3d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->current_priority);
/* no synchronization applied since it's only for debug */
rt_kprintf("%-*.*s %3d ", maxlen, RT_NAME_MAX, thread->parent.name, RT_SCHED_PRIV(thread).current_priority);
#endif /*RT_USING_SMP*/
stat = (thread->stat & RT_THREAD_STAT_MASK);
stat = (RT_SCHED_CTX(thread).stat & RT_THREAD_STAT_MASK);
if (stat == RT_THREAD_READY) rt_kprintf(" ready ");
else if ((stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) rt_kprintf(" suspend");
else if (stat == RT_THREAD_INIT) rt_kprintf(" init ");
@@ -250,7 +258,7 @@ long list_thread(void)
thread->stack_size,
(thread->stack_size - ((rt_ubase_t) ptr - (rt_ubase_t) thread->stack_addr)) * 100
/ thread->stack_size,
thread->remaining_tick,
RT_SCHED_PRIV(thread).remaining_tick,
rt_strerror(thread->error),
thread);
#endif
@@ -263,21 +271,6 @@ long list_thread(void)
return 0;
}
static void show_wait_queue(struct rt_list_node *list)
{
struct rt_thread *thread;
struct rt_list_node *node;
for (node = list->next; node != list; node = node->next)
{
thread = rt_list_entry(node, struct rt_thread, tlist);
rt_kprintf("%.*s", RT_NAME_MAX, thread->parent.name);
if (node->next != list)
rt_kprintf("/");
}
}
#ifdef RT_USING_SEMAPHORE
long list_sem(void)
{
@@ -326,7 +319,7 @@ long list_sem(void)
sem->parent.parent.name,
sem->value,
rt_list_len(&sem->parent.suspend_thread));
show_wait_queue(&(sem->parent.suspend_thread));
rt_susp_list_print(&(sem->parent.suspend_thread));
rt_kprintf("\n");
}
else
@@ -395,7 +388,7 @@ long list_event(void)
e->parent.parent.name,
e->set,
rt_list_len(&e->parent.suspend_thread));
show_wait_queue(&(e->parent.suspend_thread));
rt_susp_list_print(&(e->parent.suspend_thread));
rt_kprintf("\n");
}
else
@@ -464,7 +457,7 @@ long list_mutex(void)
m->hold,
m->priority,
rt_list_len(&m->parent.suspend_thread));
show_wait_queue(&(m->parent.suspend_thread));
rt_susp_list_print(&(m->parent.suspend_thread));
rt_kprintf("\n");
}
else
@@ -537,7 +530,7 @@ long list_mailbox(void)
m->entry,
m->size,
rt_list_len(&m->parent.suspend_thread));
show_wait_queue(&(m->parent.suspend_thread));
rt_susp_list_print(&(m->parent.suspend_thread));
rt_kprintf("\n");
}
else
@@ -607,7 +600,7 @@ long list_msgqueue(void)
m->parent.parent.name,
m->entry,
rt_list_len(&m->parent.suspend_thread));
show_wait_queue(&(m->parent.suspend_thread));
rt_susp_list_print(&(m->parent.suspend_thread));
rt_kprintf("\n");
}
else
@@ -744,7 +737,7 @@ long list_mempool(void)
mp->block_total_count,
mp->block_free_count,
suspend_thread_count);
show_wait_queue(&(mp->suspend_thread));
rt_susp_list_print(&(mp->suspend_thread));
rt_kprintf("\n");
}
else
@@ -46,7 +46,17 @@ int8_t rt_tz_is_dst(void);
struct itimerspec;
#if defined(_GNU_SOURCE) && (defined(__x86_64__) || defined(__i386__))
/* 'struct timeval' is defined on __x86_64__ toolchain */
#if !defined(__x86_64__) && !defined(_TIMEVAL_DEFINED)
#define _TIMEVAL_DEFINED
struct timeval
{
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* and microseconds */
};
#endif /* _TIMEVAL_DEFINED */
#if defined(_GNU_SOURCE) && (defined(__x86_64__) || defined(__i386__) || defined(RT_USING_SMART))
/* linux x86 platform gcc use! */
#define _TIMEVAL_DEFINED
/* Values for the first argument to `getitimer' and `setitimer'. */
@@ -71,16 +81,7 @@ struct itimerval
/* Time to the next timer expiration. */
struct timeval it_value;
};
#endif /* defined(_GNU_SOURCE) && (defined(__x86_64__) || defined(__i386__)) */
#ifndef _TIMEVAL_DEFINED
#define _TIMEVAL_DEFINED
struct timeval
{
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* and microseconds */
};
#endif /* _TIMEVAL_DEFINED */
#endif /* defined(_GNU_SOURCE) && (defined(__x86_64__) || defined(__i386__)) || defined(RT_USING_SMART) */
#if defined(__ARMCC_VERSION) || defined(_WIN32) || (defined(__ICCARM__) && (__VER__ < 8010001))
struct timespec
+1 -1
View File
@@ -203,7 +203,7 @@ void dlmodule_destroy_subthread(struct rt_dlmodule *module, rt_thread_t thread)
rt_enter_critical();
/* remove thread from thread_list (ready or defunct thread list) */
rt_list_remove(&(thread->tlist));
rt_list_remove(&RT_THREAD_LIST_NODE(thread));
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_CLOSE &&
(thread->thread_timer.parent.type == (RT_Object_Class_Static | RT_Object_Class_Timer)))
@@ -285,7 +285,7 @@ rt_err_t _pthread_cond_timedwait(pthread_cond_t *cond,
rt_thread_suspend(thread);
/* Only support FIFO */
rt_list_insert_before(&(sem->parent.suspend_thread), &(thread->tlist));
rt_list_insert_before(&(sem->parent.suspend_thread), &RT_THREAD_LIST_NODE(thread));
/**
rt_ipc_list_suspend(&(sem->parent.suspend_thread),
+16
View File
@@ -28,6 +28,22 @@
#define FUTEX_CLOCK_REALTIME 256
#define FUTEX_WAITERS 0x80000000
#define FUTEX_OWNER_DIED 0x40000000
#define FUTEX_TID_MASK 0x3fffffff
struct robust_list
{
struct robust_list *next;
};
struct robust_list_head
{
struct robust_list list;
long futex_offset;
struct robust_list *list_op_pending;
};
/* for pmutex op */
#define PMUTEX_INIT 0
#define PMUTEX_LOCK 1
+3 -46
View File
@@ -168,7 +168,6 @@ enum lwp_exit_request_type
struct termios *get_old_termios(void);
void lwp_setcwd(char *buf);
char *lwp_getcwd(void);
void lwp_request_thread_exit(rt_thread_t thread_to_exit);
int lwp_check_exit_request(void);
void lwp_terminate(struct rt_lwp *lwp);
@@ -213,52 +212,10 @@ pid_t exec(char *filename, int debug, int argc, char **argv);
/* ctime lwp API */
int timer_list_free(rt_list_t *timer_list);
struct rt_futex;
rt_err_t lwp_futex(struct rt_lwp *lwp, struct rt_futex *futex, int *uaddr, int op, int val, const struct timespec *timeout);
rt_err_t lwp_futex_init(void);
rt_err_t lwp_futex(struct rt_lwp *lwp, int *uaddr, int op, int val,
const struct timespec *timeout, int *uaddr2, int val3);
#ifdef ARCH_MM_MMU
struct __pthread {
/* Part 1 -- these fields may be external or
* * internal (accessed via asm) ABI. Do not change. */
struct pthread *self;
uintptr_t *dtv;
struct pthread *prev, *next; /* non-ABI */
uintptr_t sysinfo;
uintptr_t canary, canary2;
/* Part 2 -- implementation details, non-ABI. */
int tid;
int errno_val;
volatile int detach_state;
volatile int cancel;
volatile unsigned char canceldisable, cancelasync;
unsigned char tsd_used:1;
unsigned char dlerror_flag:1;
unsigned char *map_base;
size_t map_size;
void *stack;
size_t stack_size;
size_t guard_size;
void *result;
struct __ptcb *cancelbuf;
void **tsd;
struct {
volatile void *volatile head;
long off;
volatile void *volatile pending;
} robust_list;
volatile int timer_id;
locale_t locale;
volatile int killlock[1];
char *dlerror_buf;
void *stdio_locks;
/* Part 3 -- the positions of these fields relative to
* * the end of the structure is external and internal ABI. */
uintptr_t canary_at_end;
uintptr_t *dtv_copy;
};
#endif
#ifdef __cplusplus
}
+727 -145
View File
File diff suppressed because it is too large Load Diff
+54
View File
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-11-01 Shell Init ver.
*/
#ifndef __LWP_FUTEX_INTERNAL_H__
#define __LWP_FUTEX_INTERNAL_H__
#define DBG_TAG "lwp.futex"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include "rt_uthash.h"
#include "lwp_internal.h"
#include "lwp_pid.h"
#include <rtthread.h>
#include <lwp.h>
#ifdef ARCH_MM_MMU
#include <lwp_user_mm.h>
#endif /* ARCH_MM_MMU */
struct shared_futex_key
{
rt_mem_obj_t mobj;
rt_base_t offset;
};
DEFINE_RT_UTHASH_TYPE(shared_futex_entry, struct shared_futex_key, key);
struct rt_futex
{
union {
/* for private futex */
struct lwp_avl_struct node;
/* for shared futex */
struct shared_futex_entry entry;
};
rt_list_t waiting_thread;
struct rt_object *custom_obj;
rt_mutex_t mutex;
};
typedef struct rt_futex *rt_futex_t;
rt_err_t futex_global_table_add(struct shared_futex_key *key, rt_futex_t futex);
rt_err_t futex_global_table_find(struct shared_futex_key *key, rt_futex_t *futex);
rt_err_t futex_global_table_delete(struct shared_futex_key *key);
#endif /* __LWP_FUTEX_INTERNAL_H__ */
+65
View File
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-11-01 Shell Init ver.
*/
#include "lwp_futex_internal.h"
static struct shared_futex_entry *_futex_hash_head;
rt_err_t futex_global_table_add(struct shared_futex_key *key, rt_futex_t futex)
{
rt_err_t rc = 0;
struct shared_futex_entry *entry = &futex->entry;
futex->entry.key.mobj = key->mobj;
futex->entry.key.offset = key->offset;
RT_UTHASH_ADD(_futex_hash_head, key, sizeof(struct shared_futex_key), entry);
return rc;
}
rt_err_t futex_global_table_find(struct shared_futex_key *key, rt_futex_t *futex)
{
rt_err_t rc;
rt_futex_t found_futex;
struct shared_futex_entry *entry;
RT_UTHASH_FIND(_futex_hash_head, key, sizeof(struct shared_futex_key), entry);
if (entry)
{
rc = RT_EOK;
found_futex = rt_container_of(entry, struct rt_futex, entry);
}
else
{
rc = -RT_ENOENT;
found_futex = RT_NULL;
}
*futex = found_futex;
return rc;
}
rt_err_t futex_global_table_delete(struct shared_futex_key *key)
{
rt_err_t rc;
struct shared_futex_entry *entry;
RT_UTHASH_FIND(_futex_hash_head, key, sizeof(struct shared_futex_key), entry);
if (entry)
{
RT_UTHASH_DELETE(_futex_hash_head, entry);
rc = RT_EOK;
}
else
{
rc = -RT_ENOENT;
}
return rc;
}
+6 -6
View File
@@ -17,7 +17,7 @@
static rt_err_t _mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, rt_bool_t interruptable)
{
DEF_RETURN_CODE(rc);
LWP_DEF_RETURN_CODE(rc);
int retry;
rt_int32_t effect_timeout;
@@ -92,19 +92,19 @@ static rt_err_t _mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, rt_bool_t i
RT_ASSERT(0);
}
RETURN(rc);
LWP_RETURN(rc);
}
rt_err_t lwp_mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, rt_bool_t interruptable)
{
DEF_RETURN_CODE(rc);
LWP_DEF_RETURN_CODE(rc);
rc = _mutex_take_safe(mtx, timeout, interruptable);
RETURN(rc);
LWP_RETURN(rc);
}
rt_err_t lwp_mutex_release_safe(rt_mutex_t mtx)
{
DEF_RETURN_CODE(rc);
LWP_DEF_RETURN_CODE(rc);
rc = rt_mutex_release(mtx);
if (rc)
@@ -113,7 +113,7 @@ rt_err_t lwp_mutex_release_safe(rt_mutex_t mtx)
rt_backtrace();
}
RETURN(rc);
LWP_RETURN(rc);
}
rt_err_t lwp_critical_enter(struct rt_lwp *lwp)
+4 -4
View File
@@ -86,13 +86,13 @@ rt_err_t lwp_critical_exit(struct rt_lwp *lwp);
* There tend to be chances where a return value is returned without correctly init
*/
#ifndef LWP_DEBUG
#define DEF_RETURN_CODE(name) rt_err_t name
#define RETURN(name) return name
#define LWP_DEF_RETURN_CODE(name) rt_err_t name;RT_UNUSED(name)
#define LWP_RETURN(name) return name
#else
#define _LWP_UNINITIALIZED_RC 0xbeefcafe
#define DEF_RETURN_CODE(name) rt_err_t name = _LWP_UNINITIALIZED_RC
#define RETURN(name) {RT_ASSERT(name != _LWP_UNINITIALIZED_RC);return name;}
#define LWP_DEF_RETURN_CODE(name) rt_err_t name = _LWP_UNINITIALIZED_RC
#define LWP_RETURN(name) {RT_ASSERT(name != _LWP_UNINITIALIZED_RC);return name;}
#endif /* LWP_DEBUG */
#endif /* __LWP_INTERNAL_H__ */
+40 -41
View File
@@ -8,7 +8,9 @@
* 2019-10-12 Jesven first version
* 2023-07-25 Shell Remove usage of rt_hw_interrupt API in the lwp
* 2023-09-16 zmq810150896 Increased versatility of some features on dfs v2
* 2024-01-25 Shell porting to susp_list API
*/
#define __RT_IPC_SOURCE__
#define DBG_TAG "lwp.ipc"
#define DBG_LVL DBG_WARNING
@@ -124,11 +126,9 @@ rt_inline rt_err_t rt_channel_list_resume(rt_list_t *list)
struct rt_thread *thread;
/* get the first thread entry waiting for sending */
thread = rt_list_entry(list->next, struct rt_thread, tlist);
thread = rt_susp_list_dequeue(list, RT_THREAD_RESUME_RES_THR_ERR);
rt_thread_resume(thread);
return RT_EOK;
return thread ? RT_EOK : -RT_ERROR;
}
/**
@@ -136,15 +136,8 @@ rt_inline rt_err_t rt_channel_list_resume(rt_list_t *list)
*/
rt_inline rt_err_t _channel_list_resume_all_locked(rt_list_t *list)
{
struct rt_thread *thread;
/* wakeup all suspended threads for sending */
while (!rt_list_isempty(list))
{
thread = rt_list_entry(list->next, struct rt_thread, tlist);
thread->error = -RT_ERROR;
rt_thread_resume(thread);
}
rt_susp_list_resume_all(list, RT_ERROR);
return RT_EOK;
}
@@ -155,12 +148,7 @@ rt_inline rt_err_t _channel_list_resume_all_locked(rt_list_t *list)
rt_inline rt_err_t rt_channel_list_suspend(rt_list_t *list, struct rt_thread *thread)
{
/* suspend thread */
rt_err_t ret = rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE);
if (ret == RT_EOK)
{
rt_list_insert_before(list, &(thread->tlist)); /* list end */
}
rt_err_t ret = rt_thread_suspend_to_list(thread, list, RT_IPC_FLAG_FIFO, RT_INTERRUPTIBLE);
return ret;
}
@@ -372,10 +360,13 @@ static rt_err_t wakeup_sender_wait_reply(void *object, struct rt_thread *thread)
static void sender_timeout(void *parameter)
{
rt_sched_lock_level_t slvl;
struct rt_thread *thread = (struct rt_thread *)parameter;
rt_channel_t ch;
ch = (rt_channel_t)(thread->wakeup.user_data);
rt_sched_lock(&slvl);
ch = (rt_channel_t)(thread->wakeup_handle.user_data);
if (ch->stat == RT_IPC_STAT_ACTIVE && ch->reply == thread)
{
ch->stat = RT_IPC_STAT_IDLE;
@@ -399,14 +390,14 @@ static void sender_timeout(void *parameter)
l = l->next;
}
}
thread->error = -RT_ETIMEOUT;
thread->wakeup.func = RT_NULL;
rt_list_remove(&(thread->tlist));
thread->wakeup_handle.func = RT_NULL;
thread->error = RT_ETIMEOUT;
/* insert to schedule ready list */
rt_schedule_insert_thread(thread);
rt_sched_insert_thread(thread);
/* do schedule */
rt_schedule();
rt_sched_unlock_n_resched(slvl);
}
/**
@@ -522,7 +513,7 @@ static rt_err_t _send_recv_timeout(rt_channel_t ch, rt_channel_msg_t data, int n
static rt_err_t _do_send_recv_timeout(rt_channel_t ch, rt_channel_msg_t data, int need_reply, rt_channel_msg_t data_ret, rt_int32_t time, rt_ipc_msg_t msg)
{
DEF_RETURN_CODE(rc);
LWP_DEF_RETURN_CODE(rc);
rt_thread_t thread_recv;
rt_thread_t thread_send = 0;
void (*old_timeout_func)(void *) = 0;
@@ -627,9 +618,12 @@ static rt_err_t _do_send_recv_timeout(rt_channel_t ch, rt_channel_msg_t data, in
if (!need_reply || rc == RT_EOK)
{
thread_recv = rt_list_entry(ch->parent.suspend_thread.next, struct rt_thread, tlist);
rt_sched_lock_level_t slvl;
rt_sched_lock(&slvl);
thread_recv = RT_THREAD_LIST_NODE_ENTRY(ch->parent.suspend_thread.next);
thread_recv->msg_ret = msg; /* to the first suspended receiver */
thread_recv->error = RT_EOK;
rt_sched_unlock(slvl);
rt_channel_list_resume(&ch->parent.suspend_thread);
}
break;
@@ -706,7 +700,7 @@ rt_err_t rt_raw_channel_send_recv_timeout(rt_channel_t ch, rt_channel_msg_t data
*/
rt_err_t rt_raw_channel_reply(rt_channel_t ch, rt_channel_msg_t data)
{
DEF_RETURN_CODE(rc);
LWP_DEF_RETURN_CODE(rc);
rt_ipc_msg_t msg;
struct rt_thread *thread;
rt_base_t level;
@@ -758,7 +752,7 @@ rt_err_t rt_raw_channel_reply(rt_channel_t ch, rt_channel_msg_t data)
rt_schedule();
}
RETURN(rc);
LWP_RETURN(rc);
}
static rt_err_t wakeup_receiver(void *object, struct rt_thread *thread)
@@ -783,24 +777,27 @@ static void receiver_timeout(void *parameter)
{
struct rt_thread *thread = (struct rt_thread *)parameter;
rt_channel_t ch;
rt_base_t level;
rt_sched_lock_level_t slvl;
ch = (rt_channel_t)(thread->wakeup.user_data);
rt_sched_lock(&slvl);
ch = (rt_channel_t)(thread->wakeup_handle.user_data);
level = rt_spin_lock_irqsave(&ch->slock);
ch->stat = RT_IPC_STAT_IDLE;
thread->error = -RT_ETIMEOUT;
thread->wakeup.func = RT_NULL;
thread->wakeup_handle.func = RT_NULL;
rt_list_remove(&(thread->tlist));
rt_spin_lock(&ch->slock);
ch->stat = RT_IPC_STAT_IDLE;
rt_list_remove(&RT_THREAD_LIST_NODE(thread));
/* insert to schedule ready list */
rt_schedule_insert_thread(thread);
rt_sched_insert_thread(thread);
_rt_channel_check_wq_wakup_locked(ch);
rt_spin_unlock_irqrestore(&ch->slock, level);
rt_spin_unlock(&ch->slock);
/* do schedule */
rt_schedule();
rt_sched_unlock_n_resched(slvl);
}
/**
@@ -808,7 +805,7 @@ static void receiver_timeout(void *parameter)
*/
static rt_err_t _rt_raw_channel_recv_timeout(rt_channel_t ch, rt_channel_msg_t data, rt_int32_t time)
{
DEF_RETURN_CODE(rc);
LWP_DEF_RETURN_CODE(rc);
struct rt_thread *thread;
rt_ipc_msg_t msg_ret;
void (*old_timeout_func)(void *) = 0;
@@ -839,10 +836,12 @@ static rt_err_t _rt_raw_channel_recv_timeout(rt_channel_t ch, rt_channel_msg_t d
rt_list_remove(ch->wait_msg.next); /* remove the message from the channel */
if (msg_ret->need_reply)
{
rt_sched_lock_level_t slvl;
rt_sched_lock(&slvl);
RT_ASSERT(ch->wait_thread.next != &ch->wait_thread);
thread = rt_list_entry(ch->wait_thread.next, struct rt_thread, tlist);
thread = RT_THREAD_LIST_NODE_ENTRY(ch->wait_thread.next);
rt_list_remove(ch->wait_thread.next);
rt_sched_unlock(slvl);
ch->reply = thread; /* record the waiting sender */
ch->stat = RT_IPC_STAT_ACTIVE; /* no valid suspened receivers */
}
@@ -912,7 +911,7 @@ static rt_err_t _rt_raw_channel_recv_timeout(rt_channel_t ch, rt_channel_msg_t d
rt_spin_unlock_irqrestore(&ch->slock, level);
RETURN(rc);
LWP_RETURN(rc);
}
rt_err_t rt_raw_channel_recv(rt_channel_t ch, rt_channel_msg_t data)
+71
View File
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-11-30 Shell Add itimer support
*/
#define _GNU_SOURCE
#include <sys/time.h>
#undef _GNU_SOURCE
#define DBG_TAG "lwp.signal"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
#include <rthw.h>
#include <rtthread.h>
#include <string.h>
#include "lwp_internal.h"
#include "sys/signal.h"
#include "syscall_generic.h"
rt_err_t lwp_signal_setitimer(rt_lwp_t lwp, int which, const struct itimerspec *restrict new, struct itimerspec *restrict old)
{
rt_err_t rc = RT_EOK;
timer_t timerid = 0;
int flags = 0;
if (lwp->signal.real_timer == LWP_SIG_INVALID_TIMER)
{
struct sigevent sevp = {
.sigev_signo = SIGALRM,
.sigev_notify = SIGEV_SIGNAL,
};
rc = timer_create(CLOCK_REALTIME_ALARM, &sevp, &timerid);
if (rc == RT_EOK)
{
RT_ASSERT(timerid != LWP_SIG_INVALID_TIMER);
lwp->signal.real_timer = timerid;
}
else
{
/* failed to create timer */
}
}
else
{
timerid = lwp->signal.real_timer;
}
if (rc == RT_EOK)
{
switch (which)
{
case ITIMER_REAL:
rc = timer_settime(timerid, flags, new, old);
break;
default:
rc = -ENOSYS;
LOG_W("%s() unsupported timer", __func__);
break;
}
}
return rc;
}
+39 -112
View File
@@ -14,8 +14,12 @@
* error
* 2023-10-27 shell Format codes of sys_exit(). Fix the data racing where lock is missed
* Add reference on pid/tid, so the resource is not freed while using.
* 2024-01-25 shell porting to new sched API
*/
/* includes scheduler related API */
#define __RT_IPC_SOURCE__
#include <rthw.h>
#include <rtthread.h>
@@ -59,7 +63,7 @@ int lwp_pid_init(void)
void lwp_pid_lock_take(void)
{
DEF_RETURN_CODE(rc);
LWP_DEF_RETURN_CODE(rc);
rc = lwp_mutex_take_safe(&pid_mtx, RT_WAITING_FOREVER, 0);
/* should never failed */
@@ -382,7 +386,7 @@ rt_lwp_t lwp_create(rt_base_t flags)
}
}
LOG_D("%s(pid=%d) => %p", __func__, new_lwp->pid, new_lwp);
LOG_D("%s(pid=%d) => %p", __func__, new_lwp ? new_lwp->pid : -1, new_lwp);
return new_lwp;
}
@@ -699,6 +703,7 @@ pid_t lwp_name2pid(const char *name)
pid_t pid = 0;
rt_thread_t main_thread;
char* process_name = RT_NULL;
rt_sched_lock_level_t slvl;
lwp_pid_lock_take();
for (idx = 0; idx < RT_LWP_MAX_NR; idx++)
@@ -713,10 +718,12 @@ pid_t lwp_name2pid(const char *name)
if (!rt_strncmp(name, process_name, RT_NAME_MAX))
{
main_thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling);
if (!(main_thread->stat & RT_THREAD_CLOSE))
rt_sched_lock(&slvl);
if (!(rt_sched_thread_get_stat(main_thread) == RT_THREAD_CLOSE))
{
pid = lwp->pid;
}
rt_sched_unlock(slvl);
}
}
}
@@ -767,7 +774,7 @@ static sysret_t _lwp_wait_and_recycle(struct rt_lwp *child, rt_thread_t cur_thr,
error = rt_thread_suspend_with_flag(cur_thr, RT_INTERRUPTIBLE);
if (error == 0)
{
rt_list_insert_before(&child->wait_list, &(cur_thr->tlist));
rt_list_insert_before(&child->wait_list, &RT_THREAD_LIST_NODE(cur_thr));
LWP_UNLOCK(child);
rt_set_errno(RT_EINTR);
@@ -898,15 +905,15 @@ static void print_thread_info(struct rt_thread* thread, int maxlen)
rt_uint8_t stat;
#ifdef RT_USING_SMP
if (thread->oncpu != RT_CPU_DETACHED)
rt_kprintf("%-*.*s %3d %3d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->oncpu, thread->current_priority);
if (RT_SCHED_CTX(thread).oncpu != RT_CPU_DETACHED)
rt_kprintf("%-*.*s %3d %3d ", maxlen, RT_NAME_MAX, thread->parent.name, RT_SCHED_CTX(thread).oncpu, RT_SCHED_PRIV(thread).current_priority);
else
rt_kprintf("%-*.*s N/A %3d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->current_priority);
rt_kprintf("%-*.*s N/A %3d ", maxlen, RT_NAME_MAX, thread->parent.name, RT_SCHED_PRIV(thread).current_priority);
#else
rt_kprintf("%-*.*s %3d ", maxlen, RT_NAME_MAX, thread->parent.name, thread->current_priority);
#endif /*RT_USING_SMP*/
stat = (thread->stat & RT_THREAD_STAT_MASK);
stat = (RT_SCHED_CTX(thread).stat & RT_THREAD_STAT_MASK);
if (stat == RT_THREAD_READY) rt_kprintf(" ready ");
else if ((stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK) rt_kprintf(" suspend");
else if (stat == RT_THREAD_INIT) rt_kprintf(" init ");
@@ -932,7 +939,7 @@ static void print_thread_info(struct rt_thread* thread, int maxlen)
thread->stack_size,
(thread->stack_size + (rt_uint32_t)(rt_size_t)thread->stack_addr - (rt_uint32_t)(rt_size_t)ptr) * 100
/ thread->stack_size,
thread->remaining_tick,
RT_SCHED_PRIV(thread).remaining_tick,
thread->error);
#endif
}
@@ -1066,99 +1073,15 @@ MSH_CMD_EXPORT_ALIAS(cmd_killall, killall, kill processes by name);
int lwp_check_exit_request(void)
{
rt_thread_t thread = rt_thread_self();
rt_base_t expected = LWP_EXIT_REQUEST_TRIGGERED;
if (!thread->lwp)
{
return 0;
}
if (thread->exit_request == LWP_EXIT_REQUEST_TRIGGERED)
{
thread->exit_request = LWP_EXIT_REQUEST_IN_PROCESS;
return 1;
}
return 0;
}
static int found_thread(struct rt_lwp* lwp, rt_thread_t thread)
{
int found = 0;
rt_base_t level;
rt_list_t *list;
level = rt_spin_lock_irqsave(&thread->spinlock);
list = lwp->t_grp.next;
while (list != &lwp->t_grp)
{
rt_thread_t iter_thread;
iter_thread = rt_list_entry(list, struct rt_thread, sibling);
if (thread == iter_thread)
{
found = 1;
break;
}
list = list->next;
}
rt_spin_unlock_irqrestore(&thread->spinlock, level);
return found;
}
void lwp_request_thread_exit(rt_thread_t thread_to_exit)
{
rt_thread_t main_thread;
rt_base_t level;
rt_list_t *list;
struct rt_lwp *lwp;
lwp = lwp_self();
if ((!thread_to_exit) || (!lwp))
{
return;
}
level = rt_spin_lock_irqsave(&thread_to_exit->spinlock);
main_thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling);
if (thread_to_exit == main_thread)
{
goto finish;
}
if ((struct rt_lwp *)thread_to_exit->lwp != lwp)
{
goto finish;
}
for (list = lwp->t_grp.next; list != &lwp->t_grp; list = list->next)
{
rt_thread_t thread;
thread = rt_list_entry(list, struct rt_thread, sibling);
if (thread != thread_to_exit)
{
continue;
}
if (thread->exit_request == LWP_EXIT_REQUEST_NONE)
{
thread->exit_request = LWP_EXIT_REQUEST_TRIGGERED;
}
if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
{
thread->error = -RT_EINTR;
rt_hw_dsb();
rt_thread_wakeup(thread);
}
break;
}
while (found_thread(lwp, thread_to_exit))
{
rt_thread_mdelay(10);
}
finish:
rt_spin_unlock_irqrestore(&thread_to_exit->spinlock, level);
return;
return rt_atomic_compare_exchange_strong(&thread->exit_request, &expected,
LWP_EXIT_REQUEST_IN_PROCESS);
}
static void _wait_sibling_exit(rt_lwp_t lwp, rt_thread_t curr_thread);
@@ -1193,34 +1116,32 @@ void lwp_terminate(struct rt_lwp *lwp)
static void _wait_sibling_exit(rt_lwp_t lwp, rt_thread_t curr_thread)
{
rt_base_t level;
rt_sched_lock_level_t slvl;
rt_list_t *list;
rt_thread_t thread;
rt_base_t expected = LWP_EXIT_REQUEST_NONE;
/* broadcast exit request for sibling threads */
LWP_LOCK(lwp);
for (list = lwp->t_grp.next; list != &lwp->t_grp; list = list->next)
{
thread = rt_list_entry(list, struct rt_thread, sibling);
level = rt_spin_lock_irqsave(&thread->spinlock);
if (thread->exit_request == LWP_EXIT_REQUEST_NONE)
{
thread->exit_request = LWP_EXIT_REQUEST_TRIGGERED;
}
rt_spin_unlock_irqrestore(&thread->spinlock, level);
level = rt_spin_lock_irqsave(&thread->spinlock);
if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
rt_atomic_compare_exchange_strong(&thread->exit_request, &expected,
LWP_EXIT_REQUEST_TRIGGERED);
rt_sched_lock(&slvl);
/* dont release, otherwise thread may have been freed */
if (rt_sched_thread_is_suspended(thread))
{
thread->error = RT_EINTR;
rt_spin_unlock_irqrestore(&thread->spinlock, level);
rt_sched_unlock(slvl);
rt_hw_dsb();
rt_thread_wakeup(thread);
}
else
{
rt_spin_unlock_irqrestore(&thread->spinlock, level);
rt_sched_unlock(slvl);
}
}
LWP_UNLOCK(lwp);
@@ -1240,6 +1161,7 @@ static void _wait_sibling_exit(rt_lwp_t lwp, rt_thread_t curr_thread)
subthread_is_terminated = (int)(curr_thread->sibling.prev == &lwp->t_grp);
if (!subthread_is_terminated)
{
rt_sched_lock_level_t slvl;
rt_thread_t sub_thread;
rt_list_t *list;
int all_subthread_in_init = 1;
@@ -1247,13 +1169,18 @@ static void _wait_sibling_exit(rt_lwp_t lwp, rt_thread_t curr_thread)
/* check all subthread is in init state */
for (list = curr_thread->sibling.prev; list != &lwp->t_grp; list = list->prev)
{
rt_sched_lock(&slvl);
sub_thread = rt_list_entry(list, struct rt_thread, sibling);
if ((sub_thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
if (rt_sched_thread_get_stat(sub_thread) != RT_THREAD_INIT)
{
rt_sched_unlock(slvl);
all_subthread_in_init = 0;
break;
}
else
{
rt_sched_unlock(slvl);
}
}
if (all_subthread_in_init)
{
@@ -1344,7 +1271,7 @@ static void _resr_cleanup(struct rt_lwp *lwp)
LWP_UNLOCK(lwp);
if (!rt_list_isempty(&lwp->wait_list))
{
thread = rt_list_entry(lwp->wait_list.next, struct rt_thread, tlist);
thread = RT_THREAD_LIST_NODE_ENTRY(lwp->wait_list.next);
thread->error = RT_EOK;
thread->msg_ret = (void*)(rt_size_t)lwp->lwp_ret;
rt_thread_resume(thread);
+22 -5
View File
@@ -11,7 +11,7 @@
* remove lwp_signal_backup/restore() to reduce architecture codes
* update the generation, pending and delivery routines
*/
#define __RT_IPC_SOURCE__
#define DBG_TAG "lwp.signal"
#define DBG_LVL DBG_INFO
#include <rtdbg.h>
@@ -408,6 +408,8 @@ rt_err_t lwp_signal_init(struct lwp_signal *sig)
{
rt_err_t rc = RT_EOK;
sig->real_timer = LWP_SIG_INVALID_TIMER;
memset(&sig->sig_dispatch_thr, 0, sizeof(sig->sig_dispatch_thr));
memset(&sig->sig_action, 0, sizeof(sig->sig_action));
@@ -423,6 +425,7 @@ rt_err_t lwp_signal_detach(struct lwp_signal *signal)
{
rt_err_t ret = RT_EOK;
timer_delete(signal->real_timer);
lwp_sigqueue_clear(&signal->sig_queue);
return ret;
@@ -561,27 +564,41 @@ void lwp_thread_signal_catch(void *exp_frame)
static int _do_signal_wakeup(rt_thread_t thread, int sig)
{
int need_schedule;
rt_sched_lock_level_t slvl;
if (!_sigismember(&thread->signal.sigset_mask, sig))
{
if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
rt_sched_lock(&slvl);
int stat = rt_sched_thread_get_stat(thread);
if ((stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
{
if ((thread->stat & RT_SIGNAL_COMMON_WAKEUP_MASK) != RT_SIGNAL_COMMON_WAKEUP_MASK)
if ((stat & RT_SIGNAL_COMMON_WAKEUP_MASK) != RT_SIGNAL_COMMON_WAKEUP_MASK)
{
thread->error = RT_EINTR;
rt_sched_unlock(slvl);
rt_thread_wakeup(thread);
need_schedule = 1;
}
else if ((sig == SIGKILL) && ((thread->stat & RT_SIGNAL_KILL_WAKEUP_MASK) != RT_SIGNAL_KILL_WAKEUP_MASK))
else if ((sig == SIGKILL || sig == SIGSTOP) &&
((stat & RT_SIGNAL_KILL_WAKEUP_MASK) != RT_SIGNAL_KILL_WAKEUP_MASK))
{
thread->error = RT_EINTR;
rt_sched_unlock(slvl);
rt_thread_wakeup(thread);
need_schedule = 1;
}
else
{
rt_sched_unlock(slvl);
need_schedule = 0;
}
}
else
{
rt_sched_unlock(slvl);
need_schedule = 0;
}
}
else
need_schedule = 0;
@@ -838,7 +855,7 @@ rt_err_t lwp_thread_signal_kill(rt_thread_t thread, long signo, long code, long
LOG_D("%s(signo=%d)", __func__, signo);
if (!thread || signo < 0 || signo >= _LWP_NSIG)
if (!thread || signo <= 0 || signo >= _LWP_NSIG)
{
ret = -RT_EINVAL;
}
+9
View File
@@ -17,6 +17,9 @@
#include <rtthread.h>
#include <sys/signal.h>
struct timespec;
struct itimerspec;
#ifdef __cplusplus
extern "C" {
#endif
@@ -28,6 +31,7 @@ extern "C" {
#define LWP_SIG_USER_SA_FLAGS \
(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART | \
SA_NODEFER | SA_RESETHAND | SA_EXPOSE_TAGBITS)
#define LWP_SIG_INVALID_TIMER ((timer_t)-1)
typedef enum {
LWP_SIG_MASK_CMD_BLOCK,
@@ -40,6 +44,7 @@ typedef enum {
* LwP implementation of POSIX signal
*/
struct lwp_signal {
timer_t real_timer;
struct lwp_sigqueue sig_queue;
rt_thread_t sig_dispatch_thr[_LWP_NSIG];
@@ -167,6 +172,10 @@ rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset,
*/
void lwp_thread_signal_pending(rt_thread_t thread, lwp_sigset_t *sigset);
rt_err_t lwp_signal_setitimer(struct rt_lwp *lwp, int which,
const struct itimerspec *restrict new,
struct itimerspec *restrict old);
#ifdef __cplusplus
}
#endif
+34 -40
View File
@@ -14,7 +14,7 @@
* 2023-07-06 Shell adapt the signal API, and clone, fork to new implementation of lwp signal
* 2023-07-27 Shell Move tid_put() from lwp_free() to sys_exit()
*/
#define __RT_IPC_SOURCE__
#define _GNU_SOURCE
/* RT-Thread System call */
@@ -1120,7 +1120,7 @@ sysret_t sys_getpriority(int which, id_t who)
if (lwp)
{
rt_thread_t thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling);
prio = thread->current_priority;
prio = RT_SCHED_PRIV(thread).current_priority;
}
lwp_pid_lock_release();
@@ -1808,7 +1808,7 @@ rt_thread_t sys_thread_create(void *arg[])
}
#ifdef RT_USING_SMP
thread->bind_cpu = lwp->bind_cpu;
RT_SCHED_CTX(thread).bind_cpu = lwp->bind_cpu;
#endif
thread->cleanup = lwp_cleanup;
thread->user_entry = (void (*)(void *))arg[1];
@@ -1935,15 +1935,15 @@ long _sys_clone(void *arg[])
RT_NULL,
RT_NULL,
self->stack_size,
self->init_priority,
self->init_tick);
RT_SCHED_PRIV(self).init_priority,
RT_SCHED_PRIV(self).init_tick);
if (!thread)
{
goto fail;
}
#ifdef RT_USING_SMP
thread->bind_cpu = lwp->bind_cpu;
RT_SCHED_CTX(self).bind_cpu = lwp->bind_cpu;
#endif
thread->cleanup = lwp_cleanup;
thread->user_entry = RT_NULL;
@@ -2120,8 +2120,8 @@ sysret_t _sys_fork(void)
RT_NULL,
RT_NULL,
self_thread->stack_size,
self_thread->init_priority,
self_thread->init_tick);
RT_SCHED_PRIV(self_thread).init_priority,
RT_SCHED_PRIV(self_thread).init_tick);
if (!thread)
{
SET_ERRNO(ENOMEM);
@@ -4231,6 +4231,9 @@ sysret_t sys_sigtimedwait(const sigset_t *sigset, siginfo_t *info, const struct
struct timespec ktimeout;
struct timespec *ptimeout;
/* for RT_ASSERT */
RT_UNUSED(ret);
/* Fit sigset size to lwp set */
if (sizeof(lwpset) < sigsize)
{
@@ -5505,7 +5508,7 @@ sysret_t sys_sched_setaffinity(pid_t pid, size_t size, void *set)
sysret_t sys_sched_getaffinity(const pid_t pid, size_t size, void *set)
{
#ifdef ARCH_MM_MMU
DEF_RETURN_CODE(rc);
LWP_DEF_RETURN_CODE(rc);
void *mask;
struct rt_lwp *lwp;
rt_bool_t need_release = RT_FALSE;
@@ -5571,7 +5574,7 @@ sysret_t sys_sched_getaffinity(const pid_t pid, size_t size, void *set)
kmem_put(mask);
RETURN(rc);
LWP_RETURN(rc);
#else
return -1;
#endif
@@ -5679,13 +5682,11 @@ sysret_t sys_sched_yield(void)
return 0;
}
sysret_t sys_sched_getparam(const pid_t pid, void *param)
sysret_t sys_sched_getparam(const pid_t tid, void *param)
{
struct sched_param *sched_param = RT_NULL;
struct rt_lwp *lwp = NULL;
rt_thread_t main_thread;
rt_thread_t thread;
int ret = -1;
rt_bool_t need_release = RT_FALSE;
if (!lwp_user_accessable(param, sizeof(struct sched_param)))
{
@@ -5698,27 +5699,16 @@ sysret_t sys_sched_getparam(const pid_t pid, void *param)
return -ENOMEM;
}
if (pid > 0)
{
need_release = RT_TRUE;
lwp_pid_lock_take();
lwp = lwp_from_pid_locked(pid);
}
else if (pid == 0)
{
lwp = lwp_self();
}
thread = lwp_tid_get_thread_and_inc_ref(tid);
if (lwp)
if (thread)
{
main_thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling);
if (need_release)
lwp_pid_lock_release();
sched_param->sched_priority = main_thread->current_priority;
sched_param->sched_priority = RT_SCHED_PRIV(thread).current_priority;
ret = 0;
}
lwp_tid_dec_ref(thread);
lwp_put_to_user((void *)param, sched_param, sizeof(struct sched_param));
kmem_put(sched_param);
@@ -5800,7 +5790,7 @@ sysret_t sys_sched_getscheduler(int tid, int *policy, void *param)
}
thread = lwp_tid_get_thread_and_inc_ref(tid);
sched_param->sched_priority = thread->current_priority;
sched_param->sched_priority = RT_SCHED_PRIV(thread).current_priority;
lwp_tid_dec_ref(thread);
lwp_put_to_user((void *)param, sched_param, sizeof(struct sched_param));
@@ -6814,20 +6804,24 @@ sysret_t sys_memfd_create()
{
return 0;
}
sysret_t sys_setitimer(int which, const struct itimerspec *restrict new, struct itimerspec *restrict old)
{
int ret = 0;
timer_t timerid = 0;
struct sigevent sevp_k = {0};
sysret_t rc = 0;
rt_lwp_t lwp = lwp_self();
struct itimerspec new_value_k;
struct itimerspec old_value_k;
sevp_k.sigev_notify = SIGEV_SIGNAL;
sevp_k.sigev_signo = SIGALRM;
ret = timer_create(CLOCK_REALTIME_ALARM, &sevp_k, &timerid);
if (ret != 0)
if (lwp_get_from_user(&new_value_k, (void *)new, sizeof(*new)) != sizeof(*new))
{
return GET_ERRNO();
return -EFAULT;
}
return sys_timer_settime(timerid,0,new,old);
rc = lwp_signal_setitimer(lwp, which, &new_value_k, &old_value_k);
if (old && lwp_put_to_user(old, (void *)&old_value_k, sizeof old_value_k) != sizeof old_value_k)
return -EFAULT;
return rc;
}
const static struct rt_syscall_def func_table[] =
+2 -12
View File
@@ -25,22 +25,12 @@
#define MM_PA_TO_OFF(pa) ((uintptr_t)(pa) >> MM_PAGE_SHIFT)
#define PV_OFFSET (rt_kmem_pvoff())
#ifndef RT_USING_SMP
typedef rt_spinlock_t mm_spinlock;
#define MM_PGTBL_LOCK_INIT(aspace)
#define MM_PGTBL_LOCK(aspace) (rt_hw_spin_lock(&((aspace)->pgtbl_lock)))
#define MM_PGTBL_UNLOCK(aspace) (rt_hw_spin_unlock(&((aspace)->pgtbl_lock)))
#else
typedef struct rt_spinlock mm_spinlock;
typedef struct rt_spinlock mm_spinlock_t;
#define MM_PGTBL_LOCK_INIT(aspace) (rt_spin_lock_init(&((aspace)->pgtbl_lock)))
#define MM_PGTBL_LOCK(aspace) (rt_spin_lock(&((aspace)->pgtbl_lock)))
#define MM_PGTBL_UNLOCK(aspace) (rt_spin_unlock(&((aspace)->pgtbl_lock)))
#endif /* RT_USING_SMP */
struct rt_aspace;
struct rt_varea;
struct rt_mem_obj;
@@ -53,7 +43,7 @@ typedef struct rt_aspace
rt_size_t size;
void *page_table;
mm_spinlock pgtbl_lock;
mm_spinlock_t pgtbl_lock;
struct _aspace_tree tree;
struct rt_mutex bst_lock;
@@ -0,0 +1,9 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = []
group = DefineGroup('LIBADT', src, depend = [], CPPPATH = CPPPATH)
Return('group')
+16
View File
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-11-01 Shell Init ver.
*/
#ifndef __LIBADT_DICT_H__
#define __LIBADT_DICT_H__
#include "rt_uthash.h"
#endif
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-11-01 Shell Porting to RTT API
*/
#ifndef __LIBADT_RT_UTHASH_H__
#define __LIBADT_RT_UTHASH_H__
#include <rtthread.h>
#define uthash_malloc(sz) rt_malloc(sz)
#define uthash_free(ptr, sz) rt_free(ptr)
/**
* for performance consideration, using libc implementations
* as the default case. If you care about the compatibility
* problem, define the RT_UTHASH_CONFIG_COMPATIBILITY_FIRST
* before including the rt_uthash.h.
*/
#ifndef RT_UTHASH_CONFIG_COMPATIBILITY_FIRST
#define uthash_bzero(a, n) memset(a, '\0', n)
#define uthash_strlen(s) strlen(s)
#else
#define uthash_bzero(a, n) rt_memset(a, '\0', n)
#define uthash_strlen(s) rt_strlen(s)
#endif /* RT_UTHASH_CONFIG_COMPATIBILITY_FIRST */
/* if any fatal happen, throw an exception and return a failure */
#define uthash_fatal(msg) \
do \
{ \
LOG_E(msg); \
return -RT_ENOMEM; \
} while (0)
#include "uthash.h"
#define DEFINE_RT_UTHASH_TYPE(entry_name, key_type, key_name) \
typedef struct entry_name \
{ \
key_type key_name; \
UT_hash_handle hh; \
} *entry_name##_t;
#define RT_UTHASH_ADD(head, key_member, keylen_in, value) \
HASH_ADD(hh, head, key_member, keylen_in, value)
#define RT_UTHASH_FIND(head, key_ptr, keylen_in, pval) \
HASH_FIND(hh, head, key_ptr, keylen_in, pval)
#define RT_UTHASH_DELETE(head, pobj) HASH_DELETE(hh, head, pobj)
#endif /* __LIBADT_RT_UTHASH_H__ */
File diff suppressed because it is too large Load Diff
+3 -5
View File
@@ -89,7 +89,7 @@ void rt_prio_queue_detach(struct rt_prio_queue *que)
rt_base_t level = rt_hw_interrupt_disable();
/* get next suspend thread */
thread = rt_list_entry(que->suspended_pop_list.next, struct rt_thread, tlist);
thread = RT_THREAD_LIST_NODE_ENTRY(que->suspended_pop_list.next);
/* set error code to -RT_ERROR */
thread->error = -RT_ERROR;
@@ -160,9 +160,7 @@ rt_err_t rt_prio_queue_push(struct rt_prio_queue *que,
rt_thread_t thread;
/* get thread entry */
thread = rt_list_entry(que->suspended_pop_list.next,
struct rt_thread,
tlist);
thread = RT_THREAD_LIST_NODE_ENTRY(que->suspended_pop_list.next);
/* resume it */
rt_thread_resume(thread);
rt_hw_interrupt_enable(level);
@@ -207,7 +205,7 @@ rt_err_t rt_prio_queue_pop(struct rt_prio_queue *que,
thread->error = RT_EOK;
rt_thread_suspend(thread);
rt_list_insert_before(&(que->suspended_pop_list), &(thread->tlist));
rt_list_insert_before(&(que->suspended_pop_list), &RT_THREAD_LIST_NODE(thread));
if (timeout > 0)
{
+3 -7
View File
@@ -336,7 +336,7 @@ rt_err_t rt_vbus_post(rt_uint8_t id,
rt_enter_critical();
rt_thread_suspend(thread);
rt_list_insert_after(&_chn_suspended_threads[id], &thread->tlist);
rt_list_insert_after(&_chn_suspended_threads[id], &RT_THREAD_LIST_NODE(thread));
if (timeout > 0)
{
rt_timer_control(&(thread->thread_timer),
@@ -443,9 +443,7 @@ static void rt_vbus_notify_chn(unsigned char chnr, rt_err_t err)
{
rt_thread_t thread;
thread = rt_list_entry(_chn_suspended_threads[chnr].next,
struct rt_thread,
tlist);
thread = RT_THREAD_LIST_NODE_ENTRY(_chn_suspended_threads[chnr].next);
thread->error = err;
rt_thread_resume(thread);
}
@@ -855,9 +853,7 @@ static int _chn0_actor(unsigned char *dp, size_t dsize)
{
rt_thread_t thread;
thread = rt_list_entry(_chn_suspended_threads[chnr].next,
struct rt_thread,
tlist);
thread = RT_THREAD_LIST_NODE_ENTRY(_chn_suspended_threads[chnr].next);
rt_thread_resume(thread);
}
rt_exit_critical();
+1 -3
View File
@@ -43,9 +43,7 @@ void rt_wm_que_dump(struct rt_watermark_queue *wg)
{
rt_thread_t thread;
thread = rt_list_entry(wg->suspended_threads.next,
struct rt_thread,
tlist);
thread = RT_THREAD_LIST_NODE_ENTRY(wg->suspended_threads.next);
rt_kprintf(" %.*s", RT_NAME_MAX, thread->parent.name);
}
rt_kprintf("\n");
+2 -4
View File
@@ -64,7 +64,7 @@ rt_inline rt_err_t rt_wm_que_inc(struct rt_watermark_queue *wg,
thread = rt_thread_self();
thread->error = RT_EOK;
rt_thread_suspend(thread);
rt_list_insert_after(&wg->suspended_threads, &thread->tlist);
rt_list_insert_after(&wg->suspended_threads, &RT_THREAD_LIST_NODE(thread));
if (timeout > 0)
{
rt_timer_control(&(thread->thread_timer),
@@ -116,9 +116,7 @@ rt_inline void rt_wm_que_dec(struct rt_watermark_queue *wg)
{
rt_thread_t thread;
thread = rt_list_entry(wg->suspended_threads.next,
struct rt_thread,
tlist);
thread = RT_THREAD_LIST_NODE_ENTRY(wg->suspended_threads.next);
rt_thread_resume(thread);
need_sched = 1;
}