GPDB中Latch等待与唤醒实现机制

简介: GPDB中Latch等待与唤醒实现机制

GPDB中Latch等待与唤醒实现机制GreenPlum/PostgreSQL中有很多Latch以帮助多进程以及主线程与从线程之间协作。那么Latch是如何实现的呢?Latch可以在多进程之间以及主线程和从线程之间实现等待与唤醒,WaitEventSet是实现这项功能的关键结构。本文我们聊聊WaitEventSet的实现以及一个用法。


1、WaitEventSet的结构


1WaitEventSet用于管理注册的事件,nevens表示注册的事件个数,nevents_space表示该Set最多可以管理事件个数,比如WaitLatchOrSocket函数中这个变量值为3,仅可以管理事件WL_LATCH_SETWL_POSTMASTER_DEATHWL_EXIT_ON_PM_DEATH。可以设置的事件包括以下几种:

  • WL_LATCH_SET:等待latchset
  • WL_POSTMASTER_DEATH:等待postmaster die
  • WL_SOCKET_READABLE:等待socket可读
  • WL_SOCKET_WRITEABLE:等待socket可写
  • WL_EXIT_ON_PM_DEATHpostmaster死了后立即退出。AddWaitEventToSet函数中可以看到若事件WL_EXIT_ON_PM_DEATH则立即改成WL_POSTMASTER_DEATH,也就是说在postmaster进程挂了后可以探测到,并退出。

epoll_fdepoll实例的文件描述符。latch:如果事件有WL_LATCH_SET,则该latch为需要等待latch。通过is_set来实现等待。epoll_ret_event[]数组:epoll_wait将发生的事件集合从内核复制到该数组中。2WaitEvent表示注册的事件,pos表示该事件位于events[]数组的第几个;fd为事件相关的socket fd,也就是监听这个fd上的事件;events即为需要监听的事件。3WaitEvent使用的函数顺序为:

  • CreateWaitEventSet
  • AddWaitEventToSet
  • WaitEventSetWait
  • FreeWaitEventSet

下面依次介绍下这几个函数是干什么的。


2、CreateWaitEventSet


WaitEventSet使用前当然需要先创建,这件事就由函数CreateWaitEventSet来完成。该函数在当前内存上下文中为n个事件(个数为函数入参)申请内存空间,并进行初始化。GPDB中使用epoll来实现事件的等待与唤醒,该函数也会调用epoll_create来打开一个epoll文件描述符,创建一个epoll实例。


3、AddWaitEventToSet


添加事件到WaitEventSet中。并调用epoll_ctl函数将想要监听的文件描述符添加到epoll实例中。

4、WaitEventSetWait


等待注册的事件发生。调用epoll_wait函数来监听epoll上注册的事件。如果没有任何IO事件,则一直被阻塞,直到有IO事件发生。


5、FreeWaitEventSet


关闭epoll文件描述符,释放WaitEventSet


6、以master motion接收端receiveChunksUDPIFC为例


epoll如何与管道协作,来实现WaitEventSet的等待与唤醒呢?


1fork出一个子进程时,子进程会将父进程继承的管道关闭掉。然后自己重新创建一个管道。得到2fdpipefd[0]用于读取写入管道的内容,pipefd[1]用于向管道写入。通过全局变量selfpipe_readfdselfpipe_writefd分别表示读和写fd。当然,这是用于同一个进程不同线程之间进行管道通信。2)将管道的selfpipe_readfdepollEPOLLIN事件注册到epoll实例中,当主进程进入epoll_wait等待时,一旦监听到管道的selfpipe_readfd端可读,也就是管道中被写入了东西,就唤醒,退出等待。3receiveChunksUDPIFC用于接收segment发来的数据,当然这是UDPIFC模式下使用。若连接上没有数据,则将WL_LATCH_SETWL_TIMEOUT注册到epoll实例中4WaitLatchOrSocket用于创建epoll实例并注册监听事件。(1)首先调用Create_WaitEventSet->epoll_create创建一个epoll实例(2)WL_TIMEOUT时,timeoutMAIN_THREAD_COND_TIMEOUT_MS250ms,也就是epoll_wait的超时时间是250ms。若无指定WL_TIMEOUTtimeout值为-1,表示epoll_wait阻塞等待,一直等到被唤醒。(3)指定WL_LATCH_SET时,WaitEventSet.latch被设置成ic_control_info.latch,并通过epoll_ctl监听数据的到来(4)本案例中,共注册3WaitEvent,这里关注第一个,也就是selfpipe_readfd管道上的EPOLLERREPOLLHUPEPOLLIN33个事件。接收数据的线程rxTreadFunc接收到数据后会向管道写1个字节数据,从而被epoll监听到,以退出epoll_wait。这样完成没数据到来时等待,有数据到来时就唤醒的功能:

目录
相关文章
|
4月前
|
Java 调度
【多线程和高并发】一:线程实现和synchronize
【多线程和高并发】一:线程实现和synchronize
|
4月前
|
Linux
Linux线程同步(try锁和读写锁)
Linux线程同步(try锁和读写锁)
33 0
|
9月前
|
安全 程序员 编译器
线程互斥、同步(一)
线程互斥、同步
60 1
|
9月前
|
安全 数据安全/隐私保护
线程互斥、同步(二)
线程互斥、同步
38 1
|
Linux API
【Linux线程同步专题】二、读写锁
【Linux线程同步专题】二、读写锁
156 0
C#多线程系列(2):多 线程锁lock和Monitor
C#多线程系列(2):多 线程锁lock和Monitor
356 0