|  |  |  | @ -29,62 +29,66 @@ | 
			
		
	
		
			
				
					|  |  |  |  |  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
			
		
	
		
			
				
					|  |  |  |  |  */ | 
			
		
	
		
			
				
					|  |  |  |  | #include "it_pthread_test.h"  | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static volatile int g_count = 0; | 
			
		
	
		
			
				
					|  |  |  |  | static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkCount = 0; | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkPrepare = 0; | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkParent = 0; | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkChild = 0; | 
			
		
	
		
			
				
					|  |  |  |  | static const int SLEEP_TIME = 2; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 全局变量
 | 
			
		
	
		
			
				
					|  |  |  |  | static volatile int g_count = 0; // 计数器,控制线程的执行
 | 
			
		
	
		
			
				
					|  |  |  |  | static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER; // 互斥锁,用于同步
 | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkCount = 0; // 测试计数器,用于检查不同阶段
 | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkPrepare = 0; // 用于检查fork前的准备阶段
 | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkParent = 0; // 用于标记父进程执行的步骤
 | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkChild = 0; // 用于标记子进程执行的步骤
 | 
			
		
	
		
			
				
					|  |  |  |  | static const int SLEEP_TIME = 2; // 睡眠时间,单位秒
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 准备函数,fork之前执行
 | 
			
		
	
		
			
				
					|  |  |  |  | static void Prepare() | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int err; | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount); | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_mutex_lock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err); | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkPrepare++; | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount); // 确保g_testAtforkCount为1
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_mutex_lock(&g_lock); // 加锁
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err); // 确保加锁成功
 | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkPrepare++; // 标记准备阶段已执行
 | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 父进程执行的函数
 | 
			
		
	
		
			
				
					|  |  |  |  | static void Parent() | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int err; | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_mutex_unlock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err); | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkParent++; | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount); // 确保g_testAtforkCount为1
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_mutex_unlock(&g_lock); // 解锁
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err); // 确保解锁成功
 | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkParent++; // 标记父进程阶段已执行
 | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 子进程执行的函数
 | 
			
		
	
		
			
				
					|  |  |  |  | static void child() | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int err; | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_mutex_unlock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err); | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkChild++; | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount); // 确保g_testAtforkCount为1
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_mutex_unlock(&g_lock); // 解锁
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err); // 确保解锁成功
 | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkChild++; // 标记子进程阶段已执行
 | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 线程执行的函数
 | 
			
		
	
		
			
				
					|  |  |  |  | static void *ThreadProc(void *arg) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int err; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     while (g_count < 5) { // 5, wait until g_count == 5.
 | 
			
		
	
		
			
				
					|  |  |  |  |         err = pthread_mutex_lock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |         ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |         g_count++; | 
			
		
	
		
			
				
					|  |  |  |  |         SLEEP_AND_YIELD(SLEEP_TIME); | 
			
		
	
		
			
				
					|  |  |  |  |         err = pthread_mutex_unlock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |         ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |         SLEEP_AND_YIELD(SLEEP_TIME); | 
			
		
	
		
			
				
					|  |  |  |  |     // 当g_count小于5时,线程继续执行
 | 
			
		
	
		
			
				
					|  |  |  |  |     while (g_count < 5) { // 5, 等待直到g_count == 5
 | 
			
		
	
		
			
				
					|  |  |  |  |         err = pthread_mutex_lock(&g_lock); // 加锁
 | 
			
		
	
		
			
				
					|  |  |  |  |         ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); // 确保加锁成功
 | 
			
		
	
		
			
				
					|  |  |  |  |         g_count++; // 增加计数
 | 
			
		
	
		
			
				
					|  |  |  |  |         SLEEP_AND_YIELD(SLEEP_TIME); // 睡眠并让出CPU
 | 
			
		
	
		
			
				
					|  |  |  |  |         err = pthread_mutex_unlock(&g_lock); // 解锁
 | 
			
		
	
		
			
				
					|  |  |  |  |         ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); // 确保解锁成功
 | 
			
		
	
		
			
				
					|  |  |  |  |         SLEEP_AND_YIELD(SLEEP_TIME); // 睡眠并让出CPU
 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | EXIT: | 
			
		
	
		
			
				
					|  |  |  |  |     return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 测试pthread_atfork的函数
 | 
			
		
	
		
			
				
					|  |  |  |  | static void *PthreadAtforkTest(void *arg) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int err; | 
			
		
	
	
		
			
				
					|  |  |  | @ -92,57 +96,63 @@ static void *PthreadAtforkTest(void *arg) | 
			
		
	
		
			
				
					|  |  |  |  |     pthread_t tid; | 
			
		
	
		
			
				
					|  |  |  |  |     int status = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 初始化全局变量
 | 
			
		
	
		
			
				
					|  |  |  |  |     g_count = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkCount = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkPrepare = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkParent = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkChild = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 创建新线程
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_create(&tid, NULL, ThreadProc, NULL); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_atfork(Prepare, Parent, child); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); // 确保线程创建成功
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_atfork(Prepare, Parent, child); // 注册fork前后要执行的函数
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); // 确保注册成功
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkCount++; | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkCount++; // 标记已执行测试的计数
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     SLEEP_AND_YIELD(SLEEP_TIME); | 
			
		
	
		
			
				
					|  |  |  |  |     SLEEP_AND_YIELD(SLEEP_TIME); // 睡眠并让出CPU
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 创建子进程
 | 
			
		
	
		
			
				
					|  |  |  |  |     pid = fork(); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_WITHIN_EQUAL(pid, 0, 100000, pid, EXIT); // 100000, The pid will never exceed 100000.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(g_testAtforkPrepare, 1, g_testAtforkPrepare, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_WITHIN_EQUAL(pid, 0, 100000, pid, EXIT); // 确保pid合理,子进程的pid不会超过100000
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(g_testAtforkPrepare, 1, g_testAtforkPrepare, EXIT); // 确保准备阶段已执行
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 子进程执行的代码
 | 
			
		
	
		
			
				
					|  |  |  |  |     if (pid == 0) { | 
			
		
	
		
			
				
					|  |  |  |  |         ICUNIT_GOTO_EQUAL(g_testAtforkChild, 1, g_testAtforkChild, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |         int status; | 
			
		
	
		
			
				
					|  |  |  |  |         while (g_count < 5) { // 5, wait until g_count == 5.
 | 
			
		
	
		
			
				
					|  |  |  |  |             err = pthread_mutex_lock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |             ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |             g_count++; | 
			
		
	
		
			
				
					|  |  |  |  |             SLEEP_AND_YIELD(SLEEP_TIME); | 
			
		
	
		
			
				
					|  |  |  |  |             err = pthread_mutex_unlock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |             ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |             SLEEP_AND_YIELD(SLEEP_TIME); | 
			
		
	
		
			
				
					|  |  |  |  |         ICUNIT_GOTO_EQUAL(g_testAtforkChild, 1, g_testAtforkChild, EXIT); // 确保子进程阶段已执行
 | 
			
		
	
		
			
				
					|  |  |  |  |         while (g_count < 5) { // 等待直到g_count == 5
 | 
			
		
	
		
			
				
					|  |  |  |  |             err = pthread_mutex_lock(&g_lock); // 加锁
 | 
			
		
	
		
			
				
					|  |  |  |  |             ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); // 确保加锁成功
 | 
			
		
	
		
			
				
					|  |  |  |  |             g_count++; // 增加计数
 | 
			
		
	
		
			
				
					|  |  |  |  |             SLEEP_AND_YIELD(SLEEP_TIME); // 睡眠并让出CPU
 | 
			
		
	
		
			
				
					|  |  |  |  |             err = pthread_mutex_unlock(&g_lock); // 解锁
 | 
			
		
	
		
			
				
					|  |  |  |  |             ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); // 确保解锁成功
 | 
			
		
	
		
			
				
					|  |  |  |  |             SLEEP_AND_YIELD(SLEEP_TIME); // 睡眠并让出CPU
 | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         exit(15); // 15, set exit status
 | 
			
		
	
		
			
				
					|  |  |  |  |         exit(15); // 退出并设置状态为15
 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 父进程的验证
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(g_testAtforkParent, 1, g_testAtforkParent, EXIT_WAIT); | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_join(tid, NULL); | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_join(tid, NULL); // 等待线程结束
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(err, 0, err, EXIT_WAIT); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 父进程等待子进程结束并验证退出状态
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = waitpid(pid, &status, 0); | 
			
		
	
		
			
				
					|  |  |  |  |     status = WEXITSTATUS(status); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(err, pid, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(status, 15, status, EXIT); // 15, get exit status.
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(err, pid, err, EXIT); // 确保waitpid成功
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(status, 15, status, EXIT); // 确保子进程的退出状态为15
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | EXIT: | 
			
		
	
		
			
				
					|  |  |  |  |     return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | EXIT_WAIT: | 
			
		
	
		
			
				
					|  |  |  |  |     (void)waitpid(pid, &status, 0); | 
			
		
	
		
			
				
					|  |  |  |  |     (void)waitpid(pid, &status, 0); // 等待子进程结束
 | 
			
		
	
		
			
				
					|  |  |  |  |     return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 测试主程序
 | 
			
		
	
		
			
				
					|  |  |  |  | static int Testcase() | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int ret; | 
			
		
	
	
		
			
				
					|  |  |  | @ -151,24 +161,28 @@ static int Testcase() | 
			
		
	
		
			
				
					|  |  |  |  |     pthread_attr_t a = { 0 }; | 
			
		
	
		
			
				
					|  |  |  |  |     struct sched_param param = { 0 }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 获取当前线程的调度参数
 | 
			
		
	
		
			
				
					|  |  |  |  |     ret = pthread_getschedparam(pthread_self(), &curThreadPolicy, ¶m); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL(ret, 0, -ret); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     curThreadPri = param.sched_priority; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 设置新的线程属性并创建新线程
 | 
			
		
	
		
			
				
					|  |  |  |  |     ret = pthread_attr_init(&a); | 
			
		
	
		
			
				
					|  |  |  |  |     pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED); | 
			
		
	
		
			
				
					|  |  |  |  |     param.sched_priority = curThreadPri + 2; // 2, adjust the priority.
 | 
			
		
	
		
			
				
					|  |  |  |  |     param.sched_priority = curThreadPri + 2; // 提高线程优先级
 | 
			
		
	
		
			
				
					|  |  |  |  |     pthread_attr_setschedparam(&a, ¶m); | 
			
		
	
		
			
				
					|  |  |  |  |     ret = pthread_create(&newPthread, &a, PthreadAtforkTest, 0); | 
			
		
	
		
			
				
					|  |  |  |  |     ret = pthread_create(&newPthread, &a, PthreadAtforkTest, 0); // 创建新线程
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL(ret, 0, ret); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 等待新线程结束
 | 
			
		
	
		
			
				
					|  |  |  |  |     ret = pthread_join(newPthread, NULL); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL(ret, 0, ret); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     return 0; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 测试用例的入口函数
 | 
			
		
	
		
			
				
					|  |  |  |  | void ItTestPthreadAtfork001(void) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     TEST_ADD_CASE("IT_PTHREAD_ATFORK_001", Testcase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION); | 
			
		
	
	
		
			
				
					|  |  |  | 
 |