|
|
|
@ -29,66 +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; // 用于检查fork前的准备阶段
|
|
|
|
|
static int g_testAtforkParent = 0; // 用于标记父进程执行的步骤
|
|
|
|
|
static int g_testAtforkChild = 0; // 用于标记子进程执行的步骤
|
|
|
|
|
static const int SLEEP_TIME = 2; // 睡眠时间,单位秒
|
|
|
|
|
|
|
|
|
|
// 准备函数,fork之前执行
|
|
|
|
|
// 全局变量
|
|
|
|
|
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); // 确保g_testAtforkCount为1
|
|
|
|
|
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); // 确保g_testAtforkCount为1
|
|
|
|
|
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); // 确保g_testAtforkCount为1
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
// 当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
|
|
|
|
|
// 当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的函数
|
|
|
|
|
// 测试pthread_atfork的函数
|
|
|
|
|
static void *PthreadAtforkTest(void *arg)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
@ -96,63 +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); // 注册fork前后要执行的函数
|
|
|
|
|
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); // 睡眠并让出CPU
|
|
|
|
|
SLEEP_AND_YIELD(SLEEP_TIME); // 睡眠并让出CPU
|
|
|
|
|
|
|
|
|
|
// 创建子进程
|
|
|
|
|
// 创建子进程
|
|
|
|
|
pid = fork();
|
|
|
|
|
ICUNIT_GOTO_WITHIN_EQUAL(pid, 0, 100000, pid, EXIT); // 确保pid合理,子进程的pid不会超过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); // 确保子进程阶段已执行
|
|
|
|
|
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
|
|
|
|
|
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
|
|
|
|
|
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); // 确保waitpid成功
|
|
|
|
|
ICUNIT_GOTO_EQUAL(status, 15, status, EXIT); // 确保子进程的退出状态为15
|
|
|
|
|
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;
|
|
|
|
@ -161,28 +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; // 提高线程优先级
|
|
|
|
|
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);
|
|
|
|
|