From 68dad2ccc9856dc2c1ac112bc8f30a703c1af5d9 Mon Sep 17 00:00:00 2001 From: zhushengle Date: Wed, 20 Oct 2021 15:41:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81pthread=5Fcondattr=5F?= =?UTF-8?q?setclock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close #I4ETLN Signed-off-by: zhushengle Change-Id: I0b3ddbb0d99000c67f9b41944ab0ab4878094a8b --- kal/posix/src/pthread_cond.c | 50 +++- .../src/pthread/pthread_cond_func_test.c | 240 +++++++++++++++++- 2 files changed, 279 insertions(+), 11 deletions(-) diff --git a/kal/posix/src/pthread_cond.c b/kal/posix/src/pthread_cond.c index 9f8cec9a..1ce795c0 100644 --- a/kal/posix/src/pthread_cond.c +++ b/kal/posix/src/pthread_cond.c @@ -60,6 +60,7 @@ int pthread_condattr_destroy(pthread_condattr_t *attr) return EINVAL; } + (VOID)memset_s(attr, sizeof(pthread_condattr_t), 0, sizeof(pthread_condattr_t)); return 0; } @@ -69,6 +70,22 @@ int pthread_condattr_init(pthread_condattr_t *attr) return EINVAL; } + attr->clock = CLOCK_REALTIME; + return 0; +} + +int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clk) +{ + if ((attr == NULL) || (clk < 0)) { + return EINVAL; + } + + if ((clk != CLOCK_REALTIME) && (clk != CLOCK_MONOTONIC) && + (clk != CLOCK_PROCESS_CPUTIME_ID) && (clk != CLOCK_THREAD_CPUTIME_ID)) { + return EINVAL; + } + + attr->clock = clk; return 0; } @@ -84,11 +101,17 @@ STATIC INLINE INT32 CondInitCheck(const pthread_cond_t *cond) int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) { int ret = ENOERR; + pthread_condattr_t condAttr; if (cond == NULL) { return EINVAL; } - (VOID)attr; + + if (attr == NULL) { + pthread_condattr_init(&condAttr); + attr = &condAttr; + } + (VOID)LOS_EventInit(&(cond->event)); cond->mutex = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t)); @@ -101,6 +124,7 @@ int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr) cond->value = 0; (VOID)pthread_mutex_lock(cond->mutex); cond->count = 0; + cond->clock = attr->clock; (VOID)pthread_mutex_unlock(cond->mutex); return ret; @@ -202,12 +226,16 @@ STATIC INT32 ProcessReturnVal(pthread_cond_t *cond, INT32 val) } int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, - const struct timespec *absTime) + const struct timespec *ts) { - UINT32 absTicks; INT32 ret; + UINT32 absTicks; + const UINT32 nsPerTick = OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND; + struct timespec tp; + UINT64 nseconds; + UINT64 currTime; - if ((cond == NULL) || (mutex == NULL) || (absTime == NULL)) { + if ((cond == NULL) || (mutex == NULL) || (ts == NULL)) { return EINVAL; } @@ -222,15 +250,21 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, cond->count++; (VOID)pthread_mutex_unlock(cond->mutex); - if ((absTime->tv_sec == 0) && (absTime->tv_nsec == 0)) { - return ETIMEDOUT; + if (!ValidTimeSpec(ts)) { + return EINVAL; } - if (!ValidTimeSpec(absTime)) { + clock_gettime(cond->clock, &tp); + currTime = (UINT64)tp.tv_sec * OS_SYS_NS_PER_SECOND + tp.tv_nsec; + nseconds = (UINT64)ts->tv_sec * OS_SYS_NS_PER_SECOND + ts->tv_nsec; + if (currTime >= nseconds) { + return ETIMEDOUT; + } + absTicks = ((nseconds - currTime) + nsPerTick - 1) / nsPerTick + 1; + if (absTicks >= UINT32_MAX) { return EINVAL; } - absTicks = OsTimeSpec2Tick(absTime); if (pthread_mutex_unlock(mutex) != ENOERR) { PRINT_ERR("%s: %d failed\n", __FUNCTION__, __LINE__); } diff --git a/testsuits/unittest/posix/src/pthread/pthread_cond_func_test.c b/testsuits/unittest/posix/src/pthread/pthread_cond_func_test.c index 5093d3ec..fc382e8f 100644 --- a/testsuits/unittest/posix/src/pthread/pthread_cond_func_test.c +++ b/testsuits/unittest/posix/src/pthread/pthread_cond_func_test.c @@ -159,9 +159,10 @@ LITE_TEST_CASE(PthreadFuncTestSuite, testPthread002, Function | MediumTest | Lev static VOID *pthread_join_f03(void *argument) { int ret = pthread_detach(pthread_self()); - ICUNIT_ASSERT_EQUAL(ret, ESRCH, ret); + ICUNIT_GOTO_EQUAL(ret, ESRCH, ret, EXIT); g_testCount++; +EXIT: return NULL; } @@ -205,9 +206,10 @@ LITE_TEST_CASE(PthreadFuncTestSuite, testPthread003, Function | MediumTest | Lev static VOID *pthread_join_f04(void *argument) { int ret = pthread_detach(pthread_self()); - ICUNIT_ASSERT_EQUAL(ret, 0, ret); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); g_testCount++; +EXIT: return NULL; } @@ -252,9 +254,10 @@ LITE_TEST_CASE(PthreadFuncTestSuite, testPthread004, Function | MediumTest | Lev static VOID *pthread_join_f05(void *argument) { int ret = pthread_detach(pthread_self()); - ICUNIT_ASSERT_EQUAL(ret, EINVAL, ret); + ICUNIT_GOTO_EQUAL(ret, EINVAL, ret, EXIT); usleep(100000); /* 100000: sleep 100 ms */ +EXIT: return NULL; } @@ -295,4 +298,235 @@ LITE_TEST_CASE(PthreadFuncTestSuite, testPthread005, Function | MediumTest | Lev return LOS_OK; }; +static pthread_cond_t g_pthread_cond; +static pthread_mutex_t g_pthread_mutex; +#define TEST_THREAD_COUNT 5 +static void *pthread_cond_func001(void *arg) +{ + int ret; + struct timespec ts; + + g_testCount++; + + ret = pthread_mutex_lock(&g_pthread_mutex); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 60; /* 60: wait 1 minute */ + + ret = pthread_cond_timedwait(&g_pthread_cond, &g_pthread_mutex, &ts); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + ret = pthread_mutex_unlock(&g_pthread_mutex); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + g_testCount++; +EXIT: + return NULL; +} + +static VOID *pthread_f06(void *argument) +{ + int policy; + int ret; + int i; + pthread_attr_t attr; + struct sched_param schedParam = { 0 }; + pthread_t thread[TEST_THREAD_COUNT]; + + g_testCount = 0; + + ret = pthread_attr_init(&attr); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + ret = pthread_attr_setstacksize(&attr, OS_TSK_TEST_STACK_SIZE); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + ret = pthread_getschedparam(pthread_self(), &policy, &schedParam); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + schedParam.sched_priority -= 1; + ret = pthread_attr_setschedparam(&attr, &schedParam); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + for (i = 0; i < TEST_THREAD_COUNT; i++) { + ret = pthread_create(&thread[i], &attr, pthread_cond_func001, NULL); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + } + + ICUNIT_GOTO_EQUAL(g_testCount, 5, g_testCount, EXIT); /* 5: Five threads */ + + ret = pthread_mutex_lock(&g_pthread_mutex); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + ret = pthread_cond_broadcast(&g_pthread_cond); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + ret = pthread_mutex_unlock(&g_pthread_mutex); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + ICUNIT_GOTO_EQUAL(g_testCount, 10, g_testCount, EXIT); /* 10: Twice per thread */ + + for (i = 0; i < TEST_THREAD_COUNT; i++) { + ret = pthread_join(thread[i], NULL); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + } + +EXIT: + return NULL; +} + +/** + * @tc.number : SUB_KERNEL_PTHREAD_OPERATION_006 + * @tc.name : event operation for deatch + * @tc.desc : [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PthreadFuncTestSuite, testPthread006, Function | MediumTest | Level1) +{ + pthread_attr_t attr; + pthread_t newTh; + struct sched_param schedParam = { 0 }; + UINT32 ret; + + ret = pthread_mutex_init(&g_pthread_mutex, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_cond_init(&g_pthread_cond, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_init(&attr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setstacksize(&attr, OS_TSK_TEST_STACK_SIZE); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + schedParam.sched_priority = TASK_PRIO_TEST - 1; + ret = pthread_attr_setschedparam(&attr, &schedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_create(&newTh, &attr, pthread_f06, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_join(newTh, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + return LOS_OK; +}; + +static void *pthread_cond_func002(void *arg) +{ + int ret; + struct timespec ts; + + g_testCount++; + + ret = pthread_mutex_lock(&g_pthread_mutex); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 60; /* 60: wait 1 minute */ + + ret = pthread_cond_timedwait(&g_pthread_cond, &g_pthread_mutex, &ts); + ICUNIT_GOTO_EQUAL(ret, ETIMEDOUT, ret, EXIT); + + ret = pthread_mutex_unlock(&g_pthread_mutex); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + g_testCount++; + +EXIT: + return NULL; +} + +static VOID *pthread_f07(void *argument) +{ + int policy; + int ret; + int i; + pthread_attr_t attr; + struct sched_param schedParam = { 0 }; + pthread_t thread[TEST_THREAD_COUNT]; + + g_testCount = 0; + + ret = pthread_attr_init(&attr); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + ret = pthread_attr_setstacksize(&attr, OS_TSK_TEST_STACK_SIZE); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + ret = pthread_getschedparam(pthread_self(), &policy, &schedParam); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + schedParam.sched_priority -= 1; + ret = pthread_attr_setschedparam(&attr, &schedParam); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + + for (i = 0; i < TEST_THREAD_COUNT; i++) { + ret = pthread_create(&thread[i], &attr, pthread_cond_func002, NULL); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + } + + ICUNIT_GOTO_EQUAL(g_testCount, 5, g_testCount, EXIT); /* 5: Five threads */ + + for (i = 0; i < TEST_THREAD_COUNT; i++) { + ret = pthread_join(thread[i], NULL); + ICUNIT_GOTO_EQUAL(ret, 0, ret, EXIT); + } + + ICUNIT_GOTO_EQUAL(g_testCount, 10, g_testCount, EXIT); /* 10: Twice per thread */ + +EXIT: + return NULL; +} + +/** + * @tc.number : SUB_KERNEL_PTHREAD_OPERATION_007 + * @tc.name : event operation for deatch + * @tc.desc : [C- SOFTWARE -0200] + */ +LITE_TEST_CASE(PthreadFuncTestSuite, testPthread007, Function | MediumTest | Level1) +{ + pthread_attr_t attr; + pthread_t newTh; + struct sched_param schedParam = { 0 }; + UINT32 ret; + + ret = pthread_mutex_init(&g_pthread_mutex, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_cond_init(&g_pthread_cond, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_init(&attr); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setstacksize(&attr, OS_TSK_TEST_STACK_SIZE); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + schedParam.sched_priority = TASK_PRIO_TEST - 1; + ret = pthread_attr_setschedparam(&attr, &schedParam); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_create(&newTh, &attr, pthread_f07, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + ret = pthread_join(newTh, NULL); + ICUNIT_ASSERT_EQUAL(ret, 0, ret); + + return LOS_OK; +}; + RUN_TEST_SUITE(PthreadFuncTestSuite); -- Gitee