-
Notifications
You must be signed in to change notification settings - Fork 5.2k
【增加】增加smp_ipi_call #9427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
【增加】增加smp_ipi_call #9427
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
947062c
smp_ipi
zhuzhuzhus 7efc223
smp_ipi
zhuzhuzhus 4290ee9
smp_call
zhuzhuzhus b9171fe
smp_call
zhuzhuzhus 66cee98
SMP
zhuzhuzhus 57305fa
SMP
zhuzhuzhus 56c6edb
smp
zhuzhuzhus e3f0b0e
smp
zhuzhuzhus ad2aba6
smp
zhuzhuzhus dd62e4f
smp
zhuzhuzhus d0b86c8
smp
zhuzhuzhus f0dc4c9
smp
zhuzhuzhus 35112e2
smp
zhuzhuzhus 36ed8be
smp
zhuzhuzhus 15bda9b
smp_ipi
zhuzhuzhus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from building import * | ||
|
||
cwd = GetCurrentDir() | ||
src = [] | ||
if GetDepend("RT_USING_SMP"): | ||
src += Glob('*.c') | ||
CPPPATH = [cwd] | ||
group = DefineGroup('smp', src, depend = [''], CPPPATH = CPPPATH) | ||
|
||
Return('group') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
/* | ||
* Copyright (c) 2006-2024 RT-Thread Development Team | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Change Logs: | ||
* Date Author Notes | ||
* 2024/9/12 zhujiale the first version | ||
*/ | ||
|
||
#include "smp.h" | ||
|
||
#define DBG_TAG "SMP" | ||
#define DBG_LVL DBG_INFO | ||
#include <rtdbg.h> | ||
|
||
static struct rt_smp_call rt_smp_work[RT_CPUS_NR]; | ||
static rt_atomic_t rt_smp_wait; | ||
|
||
static rt_err_t smp_call_handler(struct rt_smp_event *event) | ||
{ | ||
switch (event->event_id) | ||
{ | ||
case SMP_CALL_EVENT_FUNC: | ||
event->func(event->data); | ||
rt_atomic_add(&rt_smp_wait, 1); | ||
break; | ||
default: | ||
LOG_E("error event id\n"); | ||
return -RT_ERROR; | ||
} | ||
return RT_EOK; | ||
} | ||
void rt_smp_call_ipi_handler(int vector, void *param) | ||
{ | ||
int err; | ||
int cur_cpu = rt_hw_cpu_id(); | ||
rt_spin_lock(&rt_smp_work[cur_cpu].lock); | ||
|
||
if (rt_smp_work[cur_cpu].event.event_id) | ||
{ | ||
err = smp_call_handler(&rt_smp_work[cur_cpu].event); | ||
if (err) | ||
{ | ||
LOG_E("Have no event\n"); | ||
rt_memset(&rt_smp_work[cur_cpu].event, 0, sizeof(struct rt_smp_event)); | ||
rt_spin_unlock(&rt_smp_work[cur_cpu].lock); | ||
} | ||
rt_memset(&rt_smp_work[cur_cpu].event, 0, sizeof(struct rt_smp_event)); | ||
} | ||
rt_spin_unlock(&rt_smp_work[cur_cpu].lock); | ||
} | ||
|
||
/** | ||
* @brief call function on specified CPU , | ||
* | ||
* @param cpu_mask cpu mask for call | ||
* @param func the function pointer | ||
* @param data the data pointer | ||
* @param flag call flag if you set SMP_CALL_WAIT_ALL | ||
* then it will wait all cpu call finish and return | ||
* else it will call function on specified CPU and return immediately | ||
* @param cond the condition function pointer,if you set it then it will call function only when cond return true | ||
*/ | ||
void rt_smp_call_func_cond(int cpu_mask, rt_smp_call_func_back func, void *data, rt_uint8_t flag, rt_smp_cond cond) | ||
{ | ||
RT_DEBUG_NOT_IN_INTERRUPT; | ||
struct rt_smp_event event; | ||
rt_bool_t need_call = RT_TRUE, need_wait = RT_FALSE; | ||
int cur_cpu = rt_hw_cpu_id(); | ||
int cpuid = 1 << cur_cpu; | ||
int tmp_id = 0, cpu_nr = 0; | ||
int tmp_mask; | ||
int irq_flag; | ||
|
||
if (flag == SMP_CALL_WAIT_ALL) | ||
{ | ||
need_wait = RT_TRUE; | ||
rt_atomic_store(&rt_smp_wait, 0); | ||
} | ||
|
||
if (cpuid & cpu_mask) | ||
{ | ||
func(data); | ||
cpu_mask = cpu_mask & (~cpuid); | ||
} | ||
|
||
if (!cpu_mask) | ||
need_call = RT_FALSE; | ||
|
||
tmp_mask = cpu_mask; | ||
if (need_call) | ||
{ | ||
while (tmp_mask) | ||
{ | ||
if ((tmp_mask & 1) && (tmp_id < RT_CPUS_NR)) | ||
{ | ||
if (cond && !cond(tmp_id, data)) | ||
continue; | ||
cpu_nr++; | ||
event.event_id = SMP_CALL_EVENT_FUNC; | ||
event.func = func; | ||
event.data = data; | ||
event.cpu_mask = cpu_mask; | ||
irq_flag = rt_spin_lock_irqsave(&rt_smp_work[tmp_id].lock); | ||
rt_smp_work[tmp_id].event = event; | ||
rt_spin_unlock_irqrestore(&rt_smp_work[tmp_id].lock,irq_flag); | ||
} | ||
tmp_id++; | ||
tmp_mask = tmp_mask >> 1; | ||
} | ||
rt_hw_ipi_send(RT_FUNC_IPI, cpu_mask); | ||
} | ||
|
||
if (need_wait) | ||
{ | ||
while (rt_atomic_load(&rt_smp_wait) != cpu_nr); | ||
} | ||
} | ||
|
||
void rt_smp_call_each_cpu(rt_smp_call_func_back func, void *data, rt_uint8_t flag) | ||
{ | ||
rt_smp_call_func_cond(RT_ALL_CPU, func, data, flag, RT_NULL); | ||
} | ||
|
||
void rt_smp_call_each_cpu_cond(rt_smp_call_func_back func, void *data, rt_uint8_t flag, rt_smp_cond cond_func) | ||
{ | ||
rt_smp_call_func_cond(RT_ALL_CPU, func, data, flag, cond_func); | ||
} | ||
void rt_smp_call_any_cpu(int cpu_mask, rt_smp_call_func_back func, void *data, rt_uint8_t flag) | ||
{ | ||
rt_smp_call_func_cond(cpu_mask, func, data, flag, RT_NULL); | ||
} | ||
|
||
void rt_smp_call_any_cpu_cond(int cpu_mask, rt_smp_call_func_back func, void *data, rt_uint8_t flag, rt_smp_cond cond_func) | ||
{ | ||
rt_smp_call_func_cond(cpu_mask, func, data, flag, cond_func); | ||
} | ||
|
||
void rt_smp_init(void) | ||
{ | ||
for (int i = 0; i < RT_CPUS_NR; i++) | ||
{ | ||
rt_memset(&rt_smp_work[i], 0, sizeof(struct rt_smp_call)); | ||
rt_spin_lock_init(&rt_smp_work[i].lock); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
#ifndef __SMP_IPI_H__ | ||
#define __SMP_IPI_H__ | ||
#include <rtthread.h> | ||
typedef void (*rt_smp_call_func_back)(void *data); | ||
typedef rt_bool_t (*rt_smp_cond)(int cpu, void *info); | ||
|
||
#define SMP_CALL_EVENT_FUNC 0x1 | ||
|
||
#define SMP_CALL_WAIT_ALL (1 << 0) | ||
#define SMP_CALL_NO_WAIT (1 << 1) | ||
|
||
#define RT_ALL_CPU ((1 << RT_CPUS_NR) - 1) | ||
struct rt_smp_event | ||
{ | ||
int cpu_mask; | ||
int event_id; | ||
void *data; | ||
rt_smp_call_func_back func; | ||
}; | ||
struct rt_smp_call | ||
{ | ||
struct rt_spinlock lock; | ||
struct rt_smp_event event; | ||
}; | ||
|
||
|
||
void rt_smp_call_ipi_handler(int vector, void *param); | ||
void rt_smp_call_each_cpu(rt_smp_call_func_back func, void *data, rt_uint8_t flag); | ||
void rt_smp_call_each_cpu_cond(rt_smp_call_func_back func, void *data, rt_uint8_t flag, rt_smp_cond cond_func); | ||
void rt_smp_call_any_cpu(int cpu_mask, rt_smp_call_func_back func, void *data, rt_uint8_t flag); | ||
void rt_smp_call_any_cpu_cond(int cpu_mask, rt_smp_call_func_back func, void *data, rt_uint8_t flag, rt_smp_cond cond_func); | ||
void rt_smp_init(void); | ||
|
||
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
menu "SMP Testcase" | ||
|
||
config UTEST_SMP_CALL_FUNC | ||
bool "Call random cpu to run func" | ||
default n | ||
endmenu |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Import('rtconfig') | ||
from building import * | ||
|
||
cwd = GetCurrentDir() | ||
src = [] | ||
CPPPATH = [cwd] | ||
|
||
if GetDepend(['RT_USING_SMP','UTEST_SMP_CALL_FUNC']): | ||
src += ['smp.c'] | ||
|
||
group = DefineGroup('utestcases', src, depend = ['RT_USING_UTESTCASES'], CPPPATH = CPPPATH) | ||
|
||
Return('group') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#include <rtdevice.h> | ||
#include "utest.h" | ||
#include "utest_assert.h" | ||
#include "smp.h" | ||
static int pass_count = 0; | ||
static int pass = 1000; | ||
static struct rt_spinlock lock; | ||
|
||
static void test_call(void *data) | ||
{ | ||
rt_spin_lock(&lock); | ||
int *i = (int *)data; | ||
int id = rt_hw_cpu_id(); | ||
*i &= ~(1 << id); | ||
if (*i == 0) | ||
pass_count++; | ||
rt_spin_unlock(&lock); | ||
} | ||
|
||
|
||
static void test1() | ||
{ | ||
int cpu_mask = 0xf; | ||
for (int i = 0; i < 1000; i++) | ||
{ | ||
cpu_mask = rand() % 0xf; | ||
if (cpu_mask == 0) | ||
pass--; | ||
rt_smp_call_any_cpu(cpu_mask,test_call, &cpu_mask, SMP_CALL_WAIT_ALL); | ||
if (i % 20 == 0) | ||
rt_kprintf("#"); | ||
} | ||
rt_kprintf("\n"); | ||
uassert_true(pass_count == pass); | ||
} | ||
|
||
static void test_call2(void *data) | ||
{ | ||
rt_spin_lock(&lock); | ||
int a = 100000; | ||
while (a--); | ||
int *i = (int *)data; | ||
(*i)++; | ||
rt_spin_unlock(&lock); | ||
} | ||
static void test2(void) | ||
{ | ||
int data = 0; | ||
rt_smp_call_each_cpu(test_call2, &data, SMP_CALL_WAIT_ALL); | ||
uassert_true(data == RT_CPUS_NR); | ||
rt_thread_mdelay(10); | ||
data = 0; | ||
rt_smp_call_each_cpu(test_call2, &data, SMP_CALL_NO_WAIT); | ||
uassert_true(data != RT_CPUS_NR); | ||
} | ||
|
||
static rt_err_t utest_tc_init(void) | ||
{ | ||
pass_count = 0; | ||
pass = 1000; | ||
rt_spin_lock_init(&lock); | ||
return RT_EOK; | ||
} | ||
|
||
static rt_err_t utest_tc_cleanup(void) | ||
{ | ||
return RT_EOK; | ||
} | ||
static void testcase(void) | ||
{ | ||
UTEST_UNIT_RUN(test1); | ||
UTEST_UNIT_RUN(test2); | ||
} | ||
|
||
UTEST_TC_EXPORT(testcase, "testcase.smp.smp", utest_tc_init, utest_tc_cleanup, 10); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.