线程模块
Tor报错模块位于src/lib/thread/
文件夹
Tor 本身运行于一个主线程以及多个工作进程,目前有很多密码学部分被移入了工作线程以提高并行性
其中,互斥锁在src/lib/lock/
中定义,线程池、工作队列在src/lib/evloop/
中定义,而这里是为跨平台多线程提供的二次封装,输出了跨平台的条件变量和线程
子系统结构
const subsys_fns_t sys_threads = { .name = "threads", .supported = true, /* Threads is used by logging, which is a diagnostic feature, we want it to * init right after low-level error handling and approx time. */ .level = -95, .initialize = subsys_threads_initialize, };
初始化子系统
根据系统不同,会执行两套不同的流程
在模块文件夹下有include.am
文件,这是 m4 的配置文件,在执行./configure
时运行,用于选择要编译的文件,在这里会判断系统环境
如果是 Windows ,会引入src/lib/thread/compat_winthreads.c
,否则则会使用 src/lib/thread/compat_winthreads.c
(这里实际的逻辑是判断是否为 Windows 环境、是否可以使用 pthread,因此如果在未安装 pthread 的平台,则会出错,不过一般而言 pthread 已经是大部分环境的标配。同时,在compat_winthreads.c
中,仍然使用宏定义再次判断了系统环境,这里应该是没必要的)
noinst_LIBRARIES += src/lib/libtor-thread.a if UNITTESTS_ENABLED noinst_LIBRARIES += src/lib/libtor-thread-testing.a endif if THREADS_PTHREADS threads_impl_source=src/lib/thread/compat_pthreads.c endif if THREADS_WIN32 threads_impl_source=src/lib/thread/compat_winthreads.c endif # ADD_C_FILE: INSERT SOURCES HERE. src_lib_libtor_thread_a_SOURCES = \ src/lib/thread/compat_threads.c \ src/lib/thread/numcpus.c \ $(threads_impl_source) src_lib_libtor_thread_testing_a_SOURCES = \ $(src_lib_libtor_thread_a_SOURCES) src_lib_libtor_thread_testing_a_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) src_lib_libtor_thread_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) # ADD_C_FILE: INSERT HEADERS HERE. noinst_HEADERS += \ src/lib/thread/numcpus.h \ src/lib/thread/thread_sys.h \ src/lib/thread/threads.h
在 Windows 上,线程没有额外配置,单纯将当前线程设置为主线程
而在其他平台上,除去将当前线程设置为主线程外,会先初始化互斥锁,接着则是初始化 pthread 线程类型
由于 tor 主线程会无限处于主循环中,因此主线程不需要等待子线程,所以初始化的会是 detached 线程模型1
条件变量
同时,由于条件变量2在不同平台也存在差异,因此这里也封装了条件变量tor_cond_t
以供使用
- 封装后的条件变量类型:
tor_cond_t
- 初始化条件变量:
int tor_cond_init(tor_cond_t*)
- 阻塞线程:
int tor_cond_wait(tor_cond_t *, tor_mutex_t *, const struct timeval *)
- 发送信号(单个):
int tor_cond_signal_one(tor_cond_t *);
- 发送信号(广播):
int tor_cond_signal_all(tor_cond_t *);
typedef struct tor_cond_t { #ifdef USE_PTHREADS pthread_cond_t cond; #elif defined(USE_WIN32_THREADS) HANDLE event; CRITICAL_SECTION lock; int n_waiting; int n_to_wake; int generation; #else #error no known condition implementation. #endif /* defined(USE_PTHREADS) || ... */ } tor_cond_t; tor_cond_t *tor_cond_new(void); void tor_cond_free_(tor_cond_t *cond); #define tor_cond_free(c) FREE_AND_NULL(tor_cond_t, tor_cond_free_, (c)) int tor_cond_init(tor_cond_t *cond); void tor_cond_uninit(tor_cond_t *cond); int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex, const struct timeval *tv); void tor_cond_signal_one(tor_cond_t *cond); void tor_cond_signal_all(tor_cond_t *cond);
线程
连条件变量都需要针对平台编译,线程本身自然也需要封装
在使用tor_threadlocal_init()
初始化线程后,需要使用tor_threadlocal_set()
为线程设置要运行的函数
typedef struct tor_threadlocal_t { #ifdef _WIN32 DWORD index; #else pthread_key_t key; #endif } tor_threadlocal_t; int tor_threadlocal_init(tor_threadlocal_t *threadlocal); void tor_threadlocal_destroy(tor_threadlocal_t *threadlocal); void *tor_threadlocal_get(tor_threadlocal_t *threadlocal); void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value);