RT-Thread / RT-Thread/rt-thread

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

Open
#10,492 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Arch: RISC-V
Dominant language
C
Stars
12.2k
Forks
5.4k
Avg merge
4d 12h
Merged PRs (30d)
40

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the example under qemu-riscv64 with rt-smart and inspect the riscv64gc-unknown-smart-musl implementations of __syscall_cp, __syscall, and ___syscall using the described disassembly and GDB steps. Compare the syscall path with the reported pthread cancellation behavior; done means pthread_cancel followed by usleep terminates the thread instead of reaching the loop.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
embedded-iot, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.