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" },
......
}