|  |  |  | @ -1,3 +1,4 @@ | 
			
		
	
		
			
				
					|  |  |  |  | // 版权声明
 | 
			
		
	
		
			
				
					|  |  |  |  | /*
 | 
			
		
	
		
			
				
					|  |  |  |  |  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved. | 
			
		
	
		
			
				
					|  |  |  |  |  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved. | 
			
		
	
	
		
			
				
					|  |  |  | @ -28,56 +29,77 @@ | 
			
		
	
		
			
				
					|  |  |  |  |  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 
			
		
	
		
			
				
					|  |  |  |  |  * 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; // 用于跟踪fork调用次数
 | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkPrepare = 0; // 用于跟踪Prepare函数调用次数
 | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkParent = 0; // 用于跟踪Parent函数调用次数
 | 
			
		
	
		
			
				
					|  |  |  |  | static int g_testAtforkChild = 0; // 用于跟踪child函数调用次数
 | 
			
		
	
		
			
				
					|  |  |  |  | static const int SLEEP_TIME = 2; // 休眠时间常量
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // Prepare函数,fork之前调用
 | 
			
		
	
		
			
				
					|  |  |  |  | static void Prepare() | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int err; | 
			
		
	
		
			
				
					|  |  |  |  |     // 断言g_testAtforkCount等于1
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount); | 
			
		
	
		
			
				
					|  |  |  |  |     // 加锁
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_mutex_lock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err); | 
			
		
	
		
			
				
					|  |  |  |  |     // 增加Prepare函数调用次数
 | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkPrepare++; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // Parent函数,fork之后在父进程中调用
 | 
			
		
	
		
			
				
					|  |  |  |  | static void Parent() | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int err; | 
			
		
	
		
			
				
					|  |  |  |  |     // 断言g_testAtforkCount等于1
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 解锁
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_mutex_unlock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err); | 
			
		
	
		
			
				
					|  |  |  |  |     // 增加Parent函数调用次数
 | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkParent++; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // child函数,fork之后在子进程中调用
 | 
			
		
	
		
			
				
					|  |  |  |  | static void child() | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int err; | 
			
		
	
		
			
				
					|  |  |  |  |     // 断言g_testAtforkCount等于1
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 解锁
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_mutex_unlock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err); | 
			
		
	
		
			
				
					|  |  |  |  |     // 增加child函数调用次数
 | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkChild++; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 线程函数
 | 
			
		
	
		
			
				
					|  |  |  |  | static void *ThreadProc(void *arg) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int err; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     while (g_count < 5) { // 5, wait until g_count == 5.
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 循环直到g_count等于5
 | 
			
		
	
		
			
				
					|  |  |  |  |     while (g_count < 5) {  | 
			
		
	
		
			
				
					|  |  |  |  |         // 加锁
 | 
			
		
	
		
			
				
					|  |  |  |  |         err = pthread_mutex_lock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |         ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |         // 增加计数
 | 
			
		
	
		
			
				
					|  |  |  |  |         g_count++; | 
			
		
	
		
			
				
					|  |  |  |  |         // 休眠并让出CPU
 | 
			
		
	
		
			
				
					|  |  |  |  |         SLEEP_AND_YIELD(SLEEP_TIME); | 
			
		
	
		
			
				
					|  |  |  |  |         // 解锁
 | 
			
		
	
		
			
				
					|  |  |  |  |         err = pthread_mutex_unlock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |         ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |         // 休眠并让出CPU
 | 
			
		
	
		
			
				
					|  |  |  |  |         SLEEP_AND_YIELD(SLEEP_TIME); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -85,6 +107,7 @@ EXIT: | 
			
		
	
		
			
				
					|  |  |  |  |     return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 测试pthread_atfork的函数
 | 
			
		
	
		
			
				
					|  |  |  |  | static void *PthreadAtforkTest(void *arg) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int err; | 
			
		
	
	
		
			
				
					|  |  |  | @ -92,44 +115,60 @@ 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); | 
			
		
	
		
			
				
					|  |  |  |  |     // 设置pthread_atfork
 | 
			
		
	
		
			
				
					|  |  |  |  |     err = pthread_atfork(Prepare, Parent, child); | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 增加fork调用次数
 | 
			
		
	
		
			
				
					|  |  |  |  |     g_testAtforkCount++; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 休眠并让出CPU
 | 
			
		
	
		
			
				
					|  |  |  |  |     SLEEP_AND_YIELD(SLEEP_TIME); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // fork进程
 | 
			
		
	
		
			
				
					|  |  |  |  |     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); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 子进程中执行
 | 
			
		
	
		
			
				
					|  |  |  |  |     if (pid == 0) { | 
			
		
	
		
			
				
					|  |  |  |  |         ICUNIT_GOTO_EQUAL(g_testAtforkChild, 1, g_testAtforkChild, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |         int status; | 
			
		
	
		
			
				
					|  |  |  |  |         while (g_count < 5) { // 5, wait until g_count == 5.
 | 
			
		
	
		
			
				
					|  |  |  |  |         // 循环直到g_count等于5
 | 
			
		
	
		
			
				
					|  |  |  |  |         while (g_count < 5) {  | 
			
		
	
		
			
				
					|  |  |  |  |             // 加锁
 | 
			
		
	
		
			
				
					|  |  |  |  |             err = pthread_mutex_lock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |             ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |             // 增加计数
 | 
			
		
	
		
			
				
					|  |  |  |  |             g_count++; | 
			
		
	
		
			
				
					|  |  |  |  |             // 休眠并让出CPU
 | 
			
		
	
		
			
				
					|  |  |  |  |             SLEEP_AND_YIELD(SLEEP_TIME); | 
			
		
	
		
			
				
					|  |  |  |  |             // 解锁
 | 
			
		
	
		
			
				
					|  |  |  |  |             err = pthread_mutex_unlock(&g_lock); | 
			
		
	
		
			
				
					|  |  |  |  |             ICUNIT_GOTO_EQUAL(err, 0, err, EXIT); | 
			
		
	
		
			
				
					|  |  |  |  |             // 休眠并让出CPU
 | 
			
		
	
		
			
				
					|  |  |  |  |             SLEEP_AND_YIELD(SLEEP_TIME); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         exit(15); // 15, set exit status
 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 父进程中执行
 | 
			
		
	
		
			
				
					|  |  |  |  |     ICUNIT_GOTO_EQUAL(g_testAtforkParent, 1, g_testAtforkParent, EXIT_WAIT); | 
			
		
	
		
			
				
					|  |  |  |  |     // 等待线程结束
 | 
			
		
	
		
			
				
					|  |  |  |  |     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); | 
			
		
	
	
		
			
				
					|  |  |  | @ -143,6 +182,7 @@ EXIT_WAIT: | 
			
		
	
		
			
				
					|  |  |  |  |     return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 测试用例函数
 | 
			
		
	
		
			
				
					|  |  |  |  | static int Testcase() | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |     int ret; | 
			
		
	
	
		
			
				
					|  |  |  | @ -151,25 +191,34 @@ 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.
 | 
			
		
	
		
			
				
					|  |  |  |  |     pthread_attr_setschedparam(&a, ¶m); | 
			
		
	
		
			
				
					|  |  |  |  |     // 创建线程
 | 
			
		
	
		
			
				
					|  |  |  |  |     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); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | } |