yyzybb537 / libgo

Go-style concurrency in C++11
MIT License
3.22k stars 757 forks source link

after work steal,errno is not switch to new thread #256

Open luyang177 opened 3 years ago

luyang177 commented 3 years ago

after work steal,errno is not switch to new thread compiler O1 will see this issue, however, O0 debug will not My OS is centos 7, gcc 4.8

test code: see log, find although thread id is different, errno address is same, that is the problem, since errno should be thread-local.


#include <chrono>
#include <iostream>
#include <atomic>
#include "coroutine.h"
#include "win_exit.h"
#include <inttypes.h>
#include <sys/syscall.h>

using namespace std;
using namespace std::chrono;

const int nWork = 100;

// 大计算量的函数
int c = 0;
std::atomic<int> done{0};
void foo(int work_id)
{
    int v = (int)rand();
    for (int i = 1; i < 20000000; ++i) {
        if (i == 1000)
        {
            int t1 = syscall(SYS_gettid);
            fprintf(stdout, "1- work id: [%d]- errno addr: [%p], thread id: [%d]\n", work_id, &errno, t1);

            co_yield;

            int t2 = syscall(SYS_gettid);
            fprintf(stdout, "2- work id: [%d]- errno addr: [%p], thread id: [%d]\n", work_id, &errno, t2);
        }
        v *= i;
    }
    c += v;

    if (++done == nWork * 2)
        co_sched.Stop();
}

int main()
{
    // 编写cpu密集型程序时, 可以延长协程执行的超时判断阈值, 避免频繁的worksteal产生
    co_opt.cycle_timeout_us = 1 * 1000;

    // 普通的for循环做法
    auto start = system_clock::now();
    // for (int i = 0; i < nWork; ++i)
    //     foo();
    auto end = system_clock::now();
    cout << "for-loop, cost ";
    cout << duration_cast<milliseconds>(end - start).count() << "ms" << endl;

    // 使用libgo做并行计算
    start = system_clock::now();
    for (int i = 0; i < nWork; ++i)
        go [i] { foo(i); };

    // 创建8个线程去并行执行所有协程 (由worksteal算法自动做负载均衡)
    co_sched.Start(8);

    end = system_clock::now();
    cout << "go with coroutine, cost ";
    cout << duration_cast<milliseconds>(end - start).count() << "ms" << endl;
    cout << "result zero:" << c * 0 << endl;
    return 0;
}