RT-Thread / RT-Thread/rt-thread
[Bug] 多线程情况下触发用户态代码段的缺页异常处理失败
Open
Nobody has claimed this yet.
bug
- Dominant language
- C
- Stars
- 12.2k
- Forks
- 5.4k
- Avg merge
- 4d 12h
- Merged PRs (30d)
- 40
Description
RT-Thread Version
master
Hardware Type/Architectures
qemu-virt64-riscv/k230
Develop Toolchain
GCC
Describe the bug
触发问题的代码
#include <atomic>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <thread>
#include <unistd.h>
#include <vector>
using namespace std;
atomic_flag lock_stream = ATOMIC_FLAG_INIT;
void append_number_unlock(int x)
{
int num;
cout << "https://www";
for (int i = 0; i < 1000000; i++)
num++;
cout << ".rt-";
for (int i = 0; i < 1000000; i++)
num++;
cout << "thread";
for (int i = 0; i < 1000000; i++)
num++;
cout << ".org/";
for (int i = 0; i < 1000000; i++)
num++;
cout << setw(3) << setfill('0') << x << endl;
}
void append_number_lock(int x)
{
while (lock_stream.test_and_set()) {
}
int num;
cout << "https://www";
for (int i = 0; i < 1000000; i++)
num++;
cout << ".rt-";
for (int i = 0; i < 1000000; i++)
num++;
cout << "thread";
for (int i = 0; i < 1000000; i++)
num++;
cout << ".org/";
for (int i = 0; i < 1000000; i++)
num++;
cout << setw(3) << setfill('0') << x << endl;
lock_stream.clear();
}
void string_split(const string &str, const char split, vector<string> &res)
{
if (str == "")
return;
// 在字符串末尾也加入分隔符,方便截取最后一段
string strs = str + split;
size_t pos = strs.find(split);
// 若找不到内容则字符串搜索函数返回 npos
while (pos != strs.npos) {
string temp = strs.substr(0, pos);
res.push_back(temp);
// 去掉已分割的字符串,在剩下的字符串中进行分割
strs = strs.substr(pos + 1, strs.size());
pos = strs.find(split);
}
}
int main()
{
cout << "un_lock" << endl;
vector<thread> threads_unlock;
for (int i = 1; i <= 20; ++i)
threads_unlock.push_back(thread(append_number_unlock, i));
for (auto &th : threads_unlock)
th.join();
cout << "lock" << endl;
stringstream ss;
streambuf *buffer = cout.rdbuf();
cout.rdbuf(ss.rdbuf());
vector<thread> threads_lock;
for (int i = 1; i <= 20; ++i)
threads_lock.push_back(thread(append_number_lock, i));
for (auto &th : threads_lock)
th.join();
cout.rdbuf(buffer);
string s(ss.str());
cout << s << endl;
vector<string> str_list;
string_split(s, '\n', str_list);
bool b = true;
for (auto str : str_list) {
cout << str.length() << " ";
if (str != "")
if (str.length() != 29) {
b = false;
}
}
if (b)
printf("{Test PASS}.\n");
else
printf("{Test FAIL}.\n");
return 0;
}
编译器
针对k230带V指令的gcc13(通用编译器gcc10无法触发)
- 编译参数: -static
现象描述
当两个线程同时触发同一指令地址的缺页异常时,一个线程成功映射页,另一个线程处理这个异常时被判定为权限问题导致异常处理失败
Other additional context
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the case on qemu-virt64-riscv/k230 with GCC 13 and the provided multithreaded C++ program, then trace the user-mode page-fault handling path for simultaneous faults at one instruction address. Done means both threads resolve the fault successfully when one thread has already mapped the page, without the second fault being misclassified as a permission error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- embedded-iot, operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100