Skip to content

Commit 3a29bf4

Browse files
authored
Merge pull request #4843 from fenghuijie/master
添加dcache invalidate/dcache clean&invalidate接口
2 parents d7d22e0 + 3dfebe3 commit 3a29bf4

File tree

6 files changed

+215
-42
lines changed

6 files changed

+215
-42
lines changed

include/rtthread.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ void rt_thread_idle_init(void);
168168
rt_err_t rt_thread_idle_sethook(void (*hook)(void));
169169
rt_err_t rt_thread_idle_delhook(void (*hook)(void));
170170
#endif
171-
void rt_thread_idle_excute(void);
172171
rt_thread_t rt_thread_idle_gethandler(void);
173172

174173
/*
@@ -396,6 +395,10 @@ rt_err_t rt_mq_recv(rt_mq_t mq,
396395
rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg);
397396
#endif
398397

398+
/* defunct */
399+
void rt_thread_defunct_enqueue(rt_thread_t thread);
400+
rt_thread_t rt_thread_defunct_dequeue(void);
401+
399402
/*
400403
* spinlock
401404
*/

libcpu/arm/cortex-a/cache.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,37 @@ void rt_hw_cpu_dcache_invalidate(void *addr, int size)
5858
asm volatile ("dsb":::"memory");
5959
}
6060

61+
void rt_hw_cpu_dcache_inv_range(void *addr, int size)
62+
{
63+
rt_uint32_t line_size = rt_cpu_dcache_line_size();
64+
rt_uint32_t start_addr = (rt_uint32_t)addr;
65+
rt_uint32_t end_addr = (rt_uint32_t)addr + size;
66+
67+
asm volatile ("dmb":::"memory");
68+
69+
if ((start_addr & (line_size - 1)) != 0)
70+
{
71+
start_addr &= ~(line_size - 1);
72+
asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(start_addr));
73+
start_addr += line_size;
74+
asm volatile ("dsb":::"memory");
75+
}
76+
77+
if ((end_addr & (line_size - 1)) != 0)
78+
{
79+
end_addr &= ~(line_size - 1);
80+
asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(end_addr));
81+
asm volatile ("dsb":::"memory");
82+
}
83+
84+
while (start_addr < end_addr)
85+
{
86+
asm volatile ("mcr p15, 0, %0, c7, c6, 1" :: "r"(start_addr)); /* dcimvac */
87+
start_addr += line_size;
88+
}
89+
asm volatile ("dsb":::"memory");
90+
}
91+
6192
void rt_hw_cpu_dcache_clean(void *addr, int size)
6293
{
6394
rt_uint32_t line_size = rt_cpu_dcache_line_size();
@@ -75,6 +106,23 @@ void rt_hw_cpu_dcache_clean(void *addr, int size)
75106
asm volatile ("dsb":::"memory");
76107
}
77108

109+
void rt_hw_cpu_dcache_clean_inv(void *addr, int size)
110+
{
111+
rt_uint32_t line_size = rt_cpu_dcache_line_size();
112+
rt_uint32_t start_addr = (rt_uint32_t)addr;
113+
rt_uint32_t end_addr = (rt_uint32_t) addr + size + line_size - 1;
114+
115+
asm volatile ("dmb":::"memory");
116+
start_addr &= ~(line_size-1);
117+
end_addr &= ~(line_size-1);
118+
while (start_addr < end_addr)
119+
{
120+
asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(start_addr));
121+
start_addr += line_size;
122+
}
123+
asm volatile ("dsb":::"memory");
124+
}
125+
78126
void rt_hw_cpu_icache_ops(int ops, void *addr, int size)
79127
{
80128
if (ops == RT_HW_CACHE_INVALIDATE)

src/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ config IDLE_THREAD_STACK_SIZE
9898
int "The stack size of idle thread"
9999
default 256
100100

101+
config SYSTEM_THREAD_STACK_SIZE
102+
int "The stack size of system thread (for defunct etc.)"
103+
depends on RT_USING_SMP
104+
default IDLE_THREAD_STACK_SIZE
105+
101106
config RT_USING_TIMER_SOFT
102107
bool "Enable software timer with a timer thread"
103108
default y

src/idle.c

Lines changed: 133 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,22 @@
4444
#define _CPUS_NR 1
4545
#endif /* RT_USING_SMP */
4646

47-
extern rt_list_t rt_thread_defunct;
47+
static rt_list_t _rt_thread_defunct = RT_LIST_OBJECT_INIT(_rt_thread_defunct);;
4848

4949
static struct rt_thread idle[_CPUS_NR];
5050
ALIGN(RT_ALIGN_SIZE)
5151
static rt_uint8_t rt_thread_stack[_CPUS_NR][IDLE_THREAD_STACK_SIZE];
5252

53+
#ifdef RT_USING_SMP
54+
#ifndef SYSTEM_THREAD_STACK_SIZE
55+
#define SYSTEM_THREAD_STACK_SIZE IDLE_THREAD_STACK_SIZE
56+
#endif
57+
static struct rt_thread rt_system_thread;
58+
ALIGN(RT_ALIGN_SIZE)
59+
static rt_uint8_t rt_system_stack[SYSTEM_THREAD_STACK_SIZE];
60+
static struct rt_semaphore system_sem;
61+
#endif
62+
5363
#ifdef RT_USING_IDLE_HOOK
5464
#ifndef RT_IDLE_HOOK_LIST_SIZE
5565
#define RT_IDLE_HOOK_LIST_SIZE 4
@@ -127,62 +137,132 @@ rt_err_t rt_thread_idle_delhook(void (*hook)(void))
127137

128138
#endif /* RT_USING_IDLE_HOOK */
129139

130-
#ifdef RT_USING_HEAP
140+
#ifdef RT_USING_MODULE
131141
/* Return whether there is defunctional thread to be deleted. */
132142
rt_inline int _has_defunct_thread(void)
133143
{
134144
/* The rt_list_isempty has prototype of "int rt_list_isempty(const rt_list_t *l)".
135-
* So the compiler has a good reason that the rt_thread_defunct list does
136-
* not change within rt_thread_idle_excute thus optimize the "while" loop
145+
* So the compiler has a good reason that the _rt_thread_defunct list does
146+
* not change within rt_thread_defunct_exceute thus optimize the "while" loop
137147
* into a "if".
138148
*
139149
* So add the volatile qualifier here. */
140-
const volatile rt_list_t *l = (const volatile rt_list_t *)&rt_thread_defunct;
150+
const volatile rt_list_t *l = (const volatile rt_list_t *)&_rt_thread_defunct;
141151

142152
return l->next != l;
143153
}
144-
#endif /* RT_USING_HEAP */
154+
#endif /* RT_USING_MODULE */
155+
156+
/* enqueue a thread to defunct queue
157+
* it must be called between rt_hw_interrupt_disable and rt_hw_interrupt_enable
158+
*/
159+
void rt_thread_defunct_enqueue(rt_thread_t thread)
160+
{
161+
rt_list_insert_after(&_rt_thread_defunct, &thread->tlist);
162+
#ifdef RT_USING_SMP
163+
rt_sem_release(&system_sem);
164+
#endif
165+
}
166+
167+
/* dequeue a thread from defunct queue
168+
* it must be called between rt_hw_interrupt_disable and rt_hw_interrupt_enable
169+
*/
170+
rt_thread_t rt_thread_defunct_dequeue(void)
171+
{
172+
rt_thread_t thread = RT_NULL;
173+
rt_list_t *l = &_rt_thread_defunct;
174+
175+
if (l->next != l)
176+
{
177+
thread = rt_list_entry(l->next,
178+
struct rt_thread,
179+
tlist);
180+
rt_list_remove(&(thread->tlist));
181+
}
182+
return thread;
183+
}
145184

146185
/**
147186
* @ingroup Thread
148187
*
149188
* This function will perform system background job when system idle.
150189
*/
151-
void rt_thread_idle_excute(void)
190+
static void rt_defunct_execute(void)
152191
{
153-
/* Loop until there is no dead thread. So one call to rt_thread_idle_excute
192+
/* Loop until there is no dead thread. So one call to rt_defunct_execute
154193
* will do all the cleanups. */
155-
/* disable interrupt */
156-
157-
RT_DEBUG_NOT_IN_INTERRUPT;
158-
159-
#ifdef RT_USING_HEAP
160194
while (1)
161195
{
162196
rt_base_t lock;
163197
rt_thread_t thread;
198+
void (*cleanup)(struct rt_thread *tid);
164199

200+
#ifdef RT_USING_MODULE
201+
struct rt_dlmodule *module = RT_NULL;
202+
#endif
203+
RT_DEBUG_NOT_IN_INTERRUPT;
204+
205+
/* disable interrupt */
165206
lock = rt_hw_interrupt_disable();
166207

208+
#ifdef RT_USING_MODULE
167209
/* check whether list is empty */
168210
if (!_has_defunct_thread())
169211
{
170212
rt_hw_interrupt_enable(lock);
171213
break;
172214
}
173215
/* get defunct thread */
174-
thread = rt_list_entry(rt_thread_defunct.next,
216+
thread = rt_list_entry(_rt_thread_defunct.next,
175217
struct rt_thread,
176218
tlist);
219+
module = (struct rt_dlmodule*)thread->module_id;
220+
if (module)
221+
{
222+
dlmodule_destroy(module);
223+
}
177224
/* remove defunct thread */
178225
rt_list_remove(&(thread->tlist));
179-
/* release thread's stack */
180-
RT_KERNEL_FREE(thread->stack_addr);
181-
/* delete thread object */
182-
rt_object_delete((rt_object_t)thread);
183-
rt_hw_interrupt_enable(lock);
226+
#else
227+
thread = rt_thread_defunct_dequeue();
228+
if (!thread)
229+
{
230+
rt_hw_interrupt_enable(lock);
231+
break;
232+
}
233+
#endif
234+
/* invoke thread cleanup */
235+
cleanup = thread->cleanup;
236+
if (cleanup != RT_NULL)
237+
{
238+
rt_hw_interrupt_enable(lock);
239+
cleanup(thread);
240+
lock = rt_hw_interrupt_disable();
241+
}
242+
243+
#ifdef RT_USING_SIGNALS
244+
rt_thread_free_sig(thread);
245+
#endif
246+
247+
/* if it's a system object, not delete it */
248+
if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
249+
{
250+
/* detach this object */
251+
rt_object_detach((rt_object_t)thread);
252+
/* enable interrupt */
253+
rt_hw_interrupt_enable(lock);
254+
}
255+
else
256+
{
257+
rt_hw_interrupt_enable(lock);
258+
#ifdef RT_USING_HEAP
259+
/* release thread's stack */
260+
RT_KERNEL_FREE(thread->stack_addr);
261+
/* delete thread object */
262+
rt_object_delete((rt_object_t)thread);
263+
#endif
264+
}
184265
}
185-
#endif /* RT_USING_HEAP */
186266
}
187267

188268
extern void rt_system_power_manager(void);
@@ -214,13 +294,27 @@ static void rt_thread_idle_entry(void *parameter)
214294
}
215295
#endif /* RT_USING_IDLE_HOOK */
216296

217-
rt_thread_idle_excute();
297+
#ifndef RT_USING_SMP
298+
rt_defunct_execute();
299+
#endif /* RT_USING_SMP */
300+
218301
#ifdef RT_USING_PM
219302
rt_system_power_manager();
220303
#endif /* RT_USING_PM */
221304
}
222305
}
223306

307+
#ifdef RT_USING_SMP
308+
static void rt_thread_system_entry(void *parameter)
309+
{
310+
while (1)
311+
{
312+
rt_sem_take(&system_sem, RT_WAITING_FOREVER);
313+
rt_defunct_execute();
314+
}
315+
}
316+
#endif
317+
224318
/**
225319
* @ingroup SystemInit
226320
*
@@ -250,6 +344,24 @@ void rt_thread_idle_init(void)
250344
/* startup */
251345
rt_thread_startup(&idle[i]);
252346
}
347+
348+
#ifdef RT_USING_SMP
349+
RT_ASSERT(RT_THREAD_PRIORITY_MAX > 2);
350+
351+
rt_sem_init(&system_sem, "defunct", 1, RT_IPC_FLAG_FIFO);
352+
353+
/* create defunct thread */
354+
rt_thread_init(&rt_system_thread,
355+
"tsystem",
356+
rt_thread_system_entry,
357+
RT_NULL,
358+
rt_system_stack,
359+
sizeof(rt_system_stack),
360+
RT_THREAD_PRIORITY_MAX - 2,
361+
32);
362+
/* startup */
363+
rt_thread_startup(&rt_system_thread);
364+
#endif
253365
}
254366

255367
/**

src/scheduler.c

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ struct rt_thread *rt_current_thread = RT_NULL;
4747
rt_uint8_t rt_current_priority;
4848
#endif /* RT_USING_SMP */
4949

50-
rt_list_t rt_thread_defunct;
51-
5250
#ifdef RT_USING_HOOK
5351
static void (*rt_scheduler_hook)(struct rt_thread *from, struct rt_thread *to);
5452

@@ -224,9 +222,6 @@ void rt_system_scheduler_init(void)
224222
/* initialize ready table */
225223
rt_memset(rt_thread_ready_table, 0, sizeof(rt_thread_ready_table));
226224
#endif /* RT_THREAD_PRIORITY_MAX > 32 */
227-
228-
/* initialize thread defunct */
229-
rt_list_init(&rt_thread_defunct);
230225
}
231226

232227
/**

0 commit comments

Comments
 (0)