rt-thread icon indicating copy to clipboard operation
rt-thread copied to clipboard

[Bug] rt-smart 定制的riscv64gc工具链存在问题,__syscall_cp不支持取消点检测

Open eatvector opened this issue 5 months ago • 1 comments

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;
}
  1. 问题定位

由于找不到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

eatvector avatar Jul 10 '25 12:07 eatvector

好问题,应该是smart对于pthread cancel还不支持

BernardXiong avatar Jul 11 '25 06:07 BernardXiong