好,看我解决这个大bug!
91 # Number of threads
92 CFG_NUM_THREADS ?= 2
这次要放大招了 !
bug实在是影响情绪,TMD!
/*
Thread的状态切换(Free->Active).
从threads[CFG_NUM_THREADS] 数组中获取一个thread,
更改该Thread 的状态,设定入口函数,
然后调用 thread_resume() ,该Thread 就跑起来了
它的领导梯队
LOCAL_FUNC vector_std_smc_entry
bl thread_handle_std_smc std smc的处理者
thread_handle_std_smc(...)
{
...
else
thread_alloc_and_run(args);
}
一个很重要的概念是 一个核上同时只会有一个Thread在运行
且该Thread独占该CPU核,除非该Thread 自己主动挂起、intr从normal world 过来
*/
static void thread_alloc_and_run(struct thread_smc_args *args)
{
/*
threads[]的下标
*/
size_t n;
/*
获取CPU核的信息, 这这个函数引起的的信息量好大!
好,扒开看看
*/
struct thread_core_local *l = thread_get_core_local();
{
uint32_t cpu_id = get_core_pos(); // cpu编号
/*
你必须关闭外部中断,这里用到的是 must be .
如果中断环境被enable了, 这里assert 就会明显的提示你,
那么 什么操作会导致 该intr被enable了呢 ?
thread suspend 、resume ? Rpc ?
知否? 知否 ? Bug 依旧!
*/
assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR);
/*
不能大于cpu核心数.
*/
assert(cpu_id < CFG_TEE_CORE_NB_CORE);
/*
返回该cpu核的信息吧.
*/
return &thread_core_local[cpu_id];
}
/* Threads[] 数组中有没有Free的Thread */
bool found_thread = false;
/*
当前cpu核上运行的线程ID 设置为 -1
表示当前cpu核上没有线程在运行
这个curr_thread 以后会变不断的++ -- =-1之间变换
其实质就是Thread在 Free Active resume suspend之间的切换
*/
assert(l->curr_thread == -1);
/*
spinlock.
*/
lock_global();
/*
找吧,不用担心??比例失调而找不到. 嘿嘿?
*/
for (n = 0; n < CFG_NUM_THREADS; n++) {
if (threads[n].state == THREAD_STATE_FREE) {
threads[n].state = THREAD_STATE_ACTIVE;
found_thread = true;
break;
}
}
/*
unspinlock.
*/
unlock_global();
/*
防止找不到. 找不到,你就return走人吧.
*/
if (!found_thread) {
args->a0 = OPTEE_SMC_RETURN_ETHREAD_LIMIT;
return;
}
/*
找到了那个Thread, 赋值给Thread ID
*/
l->curr_thread = n;
/*
清空flags
这个flags 在thread_resume_rpc()中 会有分支处理,
这里是初始状态.
*/
threads[n].flags = 0;
/*
该函数中有下面一条语句, 设置入口地址
在下面thread_resume() 该Thread run起来之后,就会从这个函数开始执行
该函数正是来处理std smc的,看清,不是fast smc,fast smc有在系统启动阶段被调用
thread->regs.pc = (uint32_t)thread_std_smc_entry;
当然了,该函数还有寄存器的赋值,在这里不一一列举,与本bug无关.
*/
init_regs(threads + n, args);
/*
最近在研究中....
*/
threads[n].hyp_clnt_id = args->a7;
/*
runing 吧,像鸟儿一样的自由
*/
thread_resume(&threads[n].regs);
}
void tee_ta_put_session(struct tee_ta_session *s)
{
/*
它是一把锁,是吧,Linux中的锁实质是系统调用,好我们看看
他们之间有什么区别
*/
mutex_lock(&tee_ta_mutex);
{
/*
忽略 %rsi %rdi, 关注%rdi.
*/
__mutex_lock(m, fname, lineno);
{
assert_have_no_spinlock();
{
assert(!have_spinlock());
{
bool have_spinlock(void)
{
/*
表示cpu core 的信息
*/
struct thread_core_local *l;
/*
判断外部中断是否被屏蔽
foreign intr 必须disabled, 否则会切换到另外一个cpu core上
*/
if (!thread_foreign_intr_disabled()) {
return false;
}
/*
返回thread_core_local[]中的元素
该数组是cpu core 共享的,
*/
l = thread_get_core_local();
{
// 获取 cpu id
uint32_t cpu_id = get_core_pos();
// foreign intr 是否disableld
assert(thread_get_exceptions() & THREAD_EXCP_FOREIGN_INTR);
// cpu core的数量
assert(cpu_id < CFG_TEE_CORE_NB_CORE)
// 返回其中的一个 cpu croe
return &thread_core_local[cpu_id];
}
/*
返回持有的自旋锁的数量
看互斥锁实现的第一步就是检查cpu core持有的 spinlock的数量
一山不容二虎,想使用mutex 必须放弃spinlock.
*/
return !!l->locked_count;
}
}
}
}
assert(thread_get_id_may_fail() != -1);
{
/*
register rflags 屏蔽intr
为什么要屏蔽intr,你看下面一句是谁来了 ?
*/
uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
// 获取cpu core
struct thread_core_local *l = thread_get_core_local();
/*
cpu core上运行的Thread ID
不说了,被这个Thread Id 坑惨了 , 捂脸大哭 ??
*/
int ct = l->curr_thread;
// enable intr
thread_unmask_exceptions(exceptions);
/*
返回吧.
那么这个函数的意思就直白的写在纸上了,
cpu core上不能没有Thread 先运行 .
所以: 到了这里
1 : 不允许你持有spinlock
2 :不允许所有的Thread suspend 或 Free.
好吧 你要什么 我满足你. 看下面的log A-1
*/
return ct;
}
/*
这里涉及到了线程的模式了,好,下面详细说
*/
assert(thread_is_in_normal_mode());
{
/*
cpsr & (000011111) arm的模式位 != 10011
判断cpu 是否是处于 SVC模式 .
Linux Kernel 中发生中断的时候,ARM首先切换到的是SVC模式然后瞬间
过渡到 IRQ模式,
这里来判断ARM是否处于SVC模式,难道用内嵌汇编不好吗?! 不能省几行
指令吗?! 省去几行指令不就是加快了速度了吗?!
*/
return (read_cpsr() & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_SVC;
}
mutex_lock_check(m);
{
// 获取CPU id.
int thread = thread_get_id();
uint32_t exceptions = 0;
/*
1 : 屏蔽外部中断
2 : 将cpu core维护的spinlock 数量增加1
3 : spinlock的数量必须是非0, 否则 panic()
*/
exceptions = cpu_spin_lock_xsave(&graph_lock);
/*
在研究. 与本Bug 无关,暂先略去.
*/
lockdep_lock_acquire(&graph, &owned[thread], (uintptr_t)m);
/*
!同理
*/
cpu_spin_unlock_xrestore(&graph_lock, exceptions);
}
/*
deadloop 来也!
*/
while (true) {
/*
该cpu core上维护的spinlock的数量.
*/
uint32_t old_itr_status;
/*
传入的参数.
-1: write, 0: unlocked, > 0: readers
*/
bool can_lock;
/*
等待队列项.
*/
struct wait_queue_elem wqe;
}
}
}
这是在 mutex_lock()前加上了 cpu_spin_lock_xsave()函数.
D/TC:? 0 tee_ta_init_session_with_context:483 Re-open TA d96a5b40-c3e5-21e3-8794-1002a5d5c61b
*D/TC:? 1 create_ta:364 create entry point for pseudo TA "invoke_tests.pta"
D/TC:? 0 open_session:377 open entry point for pseudo ta "invoke_tests.pta"
*D/TC:? 1 open_session:377 open entry point for pseudo ta "invoke_tests.pta"
E/TC:1 0 assertion '!have_spinlock()' failed at core/arch/arm/include/kernel/spinlock.h:25 <assert_have_no_spinlock>
E/TC:1 0 Panic at core/kernel/assert.c:28 <_assert_break>
D/TC:? 1 tee_ta_init_pseudo_ta_session:280 Lookup pseudo TA d96a5b40-c3e5-21e3-8794-1002a5d5c61b
D/TC:? 1 tee_ta_init_pseudo_ta_session:293 Open invoke_tests.pta
D/TC:? 1 tee_ta_init_pseudo_ta_session:307 invoke_tests.pta : d96a5b40-c3e5-21e3-8794-1002a5d5c61b
D/TC:? 1 create_ta:364 create entry point for pseudo TA "invoke_tests.pta"
D/TC:? 1 open_session:377 open entry point for pseudo ta "invoke_tests.pta"
E/TC:1 1 assertion 'threads[ct].state == THREAD_STATE_ACTIVE' failed at core/arch/arm/kernel/thread.c:777 <thread_state_suspend>
E/TC:1 1 Panic at core/kernel/assert.c:28 <_assert_break>
E/TC:1 1 Call stack:
E/TC:1 1 0x0e119041
好,现在来看2个thread 在一个 cpu core上是怎么执行的,会发生什么错误, 该如何解决