Skip to content

Commit

Permalink
🎯 Sync smart & scheduler codes (RT-Thread#8537)
Browse files Browse the repository at this point in the history
Signed-off-by: Shell <[email protected]>
Co-authored-by: xqyjlj <[email protected]>
  • Loading branch information
polarvid and xqyjlj authored Feb 23, 2024
1 parent 6fe69d7 commit 71560ba
Show file tree
Hide file tree
Showing 71 changed files with 6,107 additions and 2,218 deletions.
4 changes: 2 additions & 2 deletions bsp/qemu-vexpress-a9/applications/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <rtthread.h>

int main(void)
{
printf("Hello RT-Thread!\n");
rt_kprintf("Hello RT-Thread!\n");

return 0;
}
2 changes: 1 addition & 1 deletion bsp/qemu-vexpress-a9/drivers/secondary_cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ void rt_hw_secondary_cpu_up(void)
*plat_boot_reg-- = (void *)(size_t)-1;
*plat_boot_reg = (void *)entry;
rt_hw_dsb();
rt_hw_ipi_send(0, 1 << 1);
rt_hw_ipi_send(0, RT_CPU_MASK ^ (1 << rt_hw_cpu_id()));
}

/* Interface */
Expand Down
2 changes: 1 addition & 1 deletion components/dfs/dfs_v2/filesystems/romfs/dfs_romfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion components/dfs/dfs_v2/src/dfs_pcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
12 changes: 4 additions & 8 deletions components/drivers/audio/audio_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand Down
16 changes: 10 additions & 6 deletions components/drivers/include/ipc/completion.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion components/drivers/ipc/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -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')
121 changes: 64 additions & 57 deletions components/drivers/ipc/completion.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);

Expand Down Expand Up @@ -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)
{
Expand All @@ -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;
}
Expand All @@ -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);

/* perform a schedule */
rt_schedule();
}
else
{
rt_spin_unlock_irqrestore(&(completion->spinlock), level);
error = rt_thread_resume(suspend_thread);
if (error)
{
LOG_D("%s: failed to resume thread", __func__);
}
}

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);

Loading

0 comments on commit 71560ba

Please sign in to comment.