rt-thread
rt-thread copied to clipboard
[Bug] rt-smart 定制的riscv64gc工具链存在问题,__syscall_cp不支持取消点检测
RT-Thread Version
8a71f41
Hardware Type/Architectures
riscv64
Develop Toolchain
GCC
Describe the bug
1.问题复现
下面程序在linux上运行,线程终止且不会打印任何数据,但是在qemu-riscv64上运行 rt-smart,线程会一直循环打印“should not reach here“
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
int main(int argc, char **argv)
{
pthread_cancel(pthread_self());
usleep(100);
while(1){
printf("should not reach here\n");
}
return 0;
}
- 问题定位
由于找不到riscv64gc-unknown-smart-musl 的源码,只能从userapps下载预编译不带调试信息的工具链,静态链接工具链的库,将上面的代码编译成elf文件,再将elf文件反汇编成汇编代码,结合gdb 调试应用。
由于posix标准是默认使用延迟机制取消线程的, pthread_cancel并未直接终止线程,只是设置了一个标记,真正的线程终止一般会延迟到调用可能会阻塞的系统调用前,在进入这类系统调用前通过函数__syscall_cp检测当前线程是否已经取消,并根据情况终止线程。
但是在riscv64gc-unknown-smart-musl 的__syscall_cp实现中我并没有找到相关的用户态取消点检测代码,而是直接就陷入内核,这会导致该线程始终无法终止。
如果手动添加取消点检测,则可以正常终止线程:
#include <stdlib.h>
#include <stdint.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
int main(int argc, char **argv)
{
pthread_cancel(pthread_self());
__testcancel();
usleep(100);
while(1){
printf("should not reach here\n");
}
return 0;
}
Other additional context
这里列出 从riscv64gc-unknown-smart-musl 工具链中反汇编得到的 __syscall_cp相关实现,使用gdb单步调试也是在ecall陷入内核前没有任何取消点的检测。
riscv64gc-unknown-smart-musl:
0000000000015656 <__syscall_cp>:
15656: e6bff06f j 154c0 <__syscall>
00000000000154c0 <__syscall>:
154c0: 8deff06f j 1459e <___syscall>
000000000001459e <___syscall>:
1459e: 19000e13 li t3,400
145a2: 8eae mv t4,a1
145a4: 832a mv t1,a0
145a6: 85b2 mv a1,a2
145a8: 8636 mv a2,a3
145aa: 86ba mv a3,a4
145ac: 873e mv a4,a5
145ae: 87c2 mv a5,a6
145b0: 8846 mv a6,a7
145b2: 02ae7463 bgeu t3,a0,145da <___syscall+0x3c>
145b6: 000f08b7 lui a7,0xf0
145ba: 0895 add a7,a7,5 # f0005 <__BSS_END__+0xd67f5>
145bc: 4501 li a0,0
145be: 01131d63 bne t1,a7,145d8 <___syscall+0x3a>
145c2: ffffd897 auipc a7,0xffffd
145c6: f7a88893 add a7,a7,-134 # 1153c <syscall_set_thread_area>
145ca: 1141 add sp,sp,-16
145cc: e406 sd ra,8(sp)
145ce: 8576 mv a0,t4
145d0: 9882 jalr a7
145d2: 60a2 ld ra,8(sp)
145d4: 0141 add sp,sp,16
145d6: 8082 ret
145d8: 8082 ret
145da: 00351313 sll t1,a0,0x3
145de: 00002517 auipc a0,0x2
145e2: 26a50513 add a0,a0,618 # 16848 <syscall_table>
145e6: 932a add t1,t1,a0
145e8: 00033883 ld a7,0(t1)
145ec: fc089fe3 bnez a7,145ca <___syscall+0x2c>
145f0: 4501 li a0,0
145f2: 8082 ret
好问题,应该是smart对于pthread cancel还不支持