1 /*
2  * Copyright (c) 2006-2024 RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024/9/12      zhujiale     the first version
9  * 2024/10/24     Shell        added non-blocking IPI calling method
10  */
11 
12 #ifndef __SMP_IPI_H__
13 #define __SMP_IPI_H__
14 #include <rtthread.h>
15 
16 #ifdef RT_USING_SMP
17 
18 /* callback of smp call */
19 typedef void (*rt_smp_call_cb_t)(void *data);
20 typedef rt_bool_t (*rt_smp_cond_t)(int cpu, void *info);
21 
22 #define SMP_CALL_EVENT_GLOB_ASYNC 0x1
23 #define SMP_CALL_EVENT_GLOB_SYNC  0x2
24 #define SMP_CALL_EVENT_REQUEST    0x4
25 
26 #define SMP_CALL_WAIT_ALL (1ul << 0)
27 #define SMP_CALL_NO_LOCAL (1ul << 1)
28 #define SMP_CALL_SIGNAL   (1ul << 2)
29 
30 #define RT_ALL_CPU ((1 << RT_CPUS_NR) - 1)
31 struct rt_smp_event
32 {
33     int                   event_id;
34     void                 *data;
35     rt_smp_call_cb_t      func;
36 
37     union
38     {
39         rt_atomic_t      *calling_cpu_mask;
40         rt_atomic_t       usage_tracer;
41     } typed;
42 };
43 
44 struct rt_smp_call_req
45 {
46     /* handle the busy status synchronization */
47     rt_hw_spinlock_t    freed_lock;
48     struct rt_smp_event event;
49     rt_ll_slist_t       slist_node;
50 };
51 
52 void rt_smp_call_ipi_handler(int vector, void *param);
53 void rt_smp_call_each_cpu(rt_smp_call_cb_t func, void *data, rt_uint8_t flags);
54 void rt_smp_call_each_cpu_cond(rt_smp_call_cb_t func, void *data, rt_uint8_t flag, rt_smp_cond_t cond_func);
55 void rt_smp_call_cpu_mask(rt_ubase_t cpu_mask, rt_smp_call_cb_t func, void *data, rt_uint8_t flags);
56 void rt_smp_call_cpu_mask_cond(rt_ubase_t cpu_mask, rt_smp_call_cb_t func, void *data, rt_uint8_t flag, rt_smp_cond_t cond_func);
57 void rt_smp_call_init(void);
58 
59 rt_err_t rt_smp_call_request(int callcpu, rt_uint8_t flags, struct rt_smp_call_req *call_req);
60 void rt_smp_call_req_init(struct rt_smp_call_req *call_req,
61                           rt_smp_call_cb_t func, void *data);
62 void rt_smp_request_wait_freed(struct rt_smp_call_req *req);
63 
64 #define rt_smp_for_each_cpu(_iter) for (_iter = 0; (_iter) < RT_CPUS_NR; (_iter)++)
rt_smp_get_next_remote(size_t iter,size_t cpuid)65 rt_inline size_t rt_smp_get_next_remote(size_t iter, size_t cpuid)
66 {
67     iter++;
68     return iter == cpuid ? iter + 1 : iter;
69 }
70 #define rt_smp_for_each_remote_cpu(_iter, _cpuid) for (_iter = rt_smp_get_next_remote(-1, _cpuid); (_iter) < RT_CPUS_NR; _iter=rt_smp_get_next_remote(_iter, _cpuid))
71 
72 #endif // RT_USING_SMP
73 
74 #endif // __SMP_IPI_H__
75