OpenGauss线程管理-主线程-Postmaster(2)

OpenGauss线程管理-主线程-Postmaster(2)

在对PostmasterMain函数的代码进行了大致的了解后,现在来看一看它是如何进行线程的创建及启动的,即如何对线程进行初始化。

线程的初始化

initialize_thread函数是用来进行线程的启动,并且后台线程的启动函数initialize_util_thread和工作线程的启动函数initialize_worker_thread都是调用initialize_thread函数来完成线程的启动。下面附上相关函数的代码
路径:openGauss-server\src\gausskernel\process\postmaster\postmaster.cpp
函数流程图

initialize_thread函数

initialize_thread函数中调用gs_thread_create来创建线程,还有InternalThreadFunc函数来处理线程

ThreadId initialize_thread(ThreadArg* thr_argv)
{

    gs_thread_t thread;
    //调用gs_thread_create函数创建线程
    int error_code = gs_thread_create(&thread, InternalThreadFunc, 1, (void*)thr_argv);
    if (error_code != 0) {
        ereport(LOG,
            (errmsg("can not fork thread[%s], errcode:%d, %m",
             GetThreadName(thr_argv->m_thd_arg.role), error_code)));
        gs_thread_release_args_slot(thr_argv);
        return InvalidTid;
    }

    return gs_thread_id(thread);
}

initialize_util_thread函数

用于后台线程的启动,该函数启动STARTUP线程,如果是第一次启动数据库,则会使用 initialize_util_thread函数来启动其他的后台线程。

ThreadId initialize_util_thread(knl_thread_role role, void* payload)
{
    ThreadArg* thr_argv = gs_thread_get_args_slot();
    if (thr_argv == NULL) {
        return 0;
    }
    thr_argv->m_thd_arg.role = role;
    thr_argv->m_thd_arg.payload = payload;
    Port port;
    ThreadId pid;
    errno_t rc;
    /* 此入口点传递 Port 变量的虚拟值 */
    rc = memset_s(&port, sizeof(port), 0, sizeof(port));
    securec_check(rc, "", "");
    port.sock = PGINVALID_SOCKET;
    port.SessionVersionNum = pg_atomic_read_u32(&WorkingGrandVersionNum);

    if (!save_backend_variables((BackendParameters*)(thr_argv->m_thd_arg.save_para), &port)) {
        gs_thread_release_args_slot(thr_argv);
        return 0; /* save_backend_variables制作的日志 */
    }

    if (role == SYSLOGGER) {
        if (t_thrd.logger.syslogFile != NULL)
            thr_argv->m_thd_arg.extra_payload.log_thread.syslog_handle = fileno(t_thrd.logger.syslogFile);
        else
            thr_argv->m_thd_arg.extra_payload.log_thread.syslog_handle = -1;
    }

    pid = initialize_thread(thr_argv);//调用initialize_thread函数来进行线程的启动

    if (pid == InvalidTid) {
        /*
         * 在启动期间,分叉故障是致命的,但如果启动其他子类型失败,则无需立即窒息。
         */
        if (role == STARTUP)
            ExitPostmaster(1);
        return 0;
    }
    return pid;
}

initialize_worker_thread函数

工作线程的启动

ThreadId initialize_worker_thread(knl_thread_role role, Port* port, void* payload)
{
    ThreadArg* thr_argv = gs_thread_get_args_slot();
    if (thr_argv == NULL) {
        return InvalidTid;
    }

    thr_argv->m_thd_arg.role = role;
    thr_argv->m_thd_arg.payload = payload;

    /*
     * 我们将后端版本初始化为与postmaster相同,这在大多数时候都应该如此。
     */
    port->SessionVersionNum = pg_atomic_read_u32(&WorkingGrandVersionNum);

    if (!save_backend_variables((BackendParameters*)(thr_argv->m_thd_arg.save_para), port)) {
        gs_thread_release_args_slot(thr_argv);
        return InvalidTid; /* save_backend_variables制作的日志 */
    }

    return initialize_thread(thr_argv);//调用initialize_thread函数
}

InternalThreadFunc函数

处理线程函数,将对应角色的线程进行初始化等一系列操作。
调用GetThreadEntry函数返回GaussdbThreadEntryGate数组对应的元素,这些元素是用来处理具体任务的回调函数指针,其指向GaussDbThreadMain函数。
GaussDbThreadMain函数用来初始化线程基本信息,上下文和信号处理函数,然后根据角色的不同来进入不同线程的主函数

static void* InternalThreadFunc(void* args)
{
    knl_thread_arg* thr_argv = (knl_thread_arg*)args;
	//根据角色来调用GetThreadEntry函数
    gs_thread_exit((GetThreadEntry(thr_argv->role))(thr_argv));
    return (void*)NULL;
}

GetThreadEntry函数

该函数以角色为下标,返回GaussdbThreadEntryGate数组对应的元素。

GaussdbThreadEntry GetThreadEntry(knl_thread_role role)
{
    Assert(role > MASTER_THREAD && role < THREAD_ENTRY_BOUND);
    Assert(GaussdbThreadGate[static_cast<int>(role)].role == role);

    return GaussdbThreadGate[static_cast<int>(role)].func;
}

GaussdbThreadGate[]数组

该数组的元素是处理具体任务的回调函数指针,指针指向的函数为GaussDbThreadMain。

static ThreadMetaData GaussdbThreadGate[] = {
    { GaussDbThreadMain<MASTER_THREAD>, MASTER_THREAD, "main", "main thread" },
    { GaussDbThreadMain<WORKER>, WORKER, "worker", "woker thread" },
    { GaussDbThreadMain<THREADPOOL_WORKER>, THREADPOOL_WORKER, "TPLworker", "thread pool worker" },
    { GaussDbThreadMain<THREADPOOL_LISTENER>, THREADPOOL_LISTENER, "TPLlistener", "thread pool listner" },
    { GaussDbThreadMain<THREADPOOL_SCHEDULER>, THREADPOOL_SCHEDULER, "TPLscheduler", "thread pool scheduler" },
    { GaussDbThreadMain<THREADPOOL_STREAM>, THREADPOOL_STREAM, "TPLstream", "thread pool stream" },
    { GaussDbThreadMain<STREAM_WORKER>, STREAM_WORKER, "streamworker", "stream worker" },
    ......
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值