RT-Thread / RT-Thread/rt-thread

[Bug] 多线程情况下触发用户态代码段的缺页异常处理失败

Open
#9,854 6 comments 0 reactions 0 assignees View on GitHub

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

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 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.