• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  * conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  * of conditions and the following disclaimer in the documentation and/or other materials
13  * provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  * to endorse or promote products derived from this software without specific prior written
17  * permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 #include "it_pthread_test.h"
32 
33 static volatile int g_count = 0;
34 static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
35 static int g_testAtforkCount = 0;
36 static int g_testAtforkPrepare = 0;
37 static int g_testAtforkParent = 0;
38 static int g_testAtforkChild = 0;
39 static const int SLEEP_TIME = 2;
40 
Prepare()41 static void Prepare()
42 {
43     int err;
44     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount);
45     err = pthread_mutex_lock(&g_lock);
46     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err);
47     g_testAtforkPrepare++;
48 }
49 
Parent()50 static void Parent()
51 {
52     int err;
53     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount);
54 
55     err = pthread_mutex_unlock(&g_lock);
56     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err);
57     g_testAtforkParent++;
58 }
59 
child()60 static void child()
61 {
62     int err;
63     ICUNIT_ASSERT_EQUAL_VOID(g_testAtforkCount, 1, g_testAtforkCount);
64 
65     err = pthread_mutex_unlock(&g_lock);
66     ICUNIT_ASSERT_EQUAL_VOID(err, 0, err);
67     g_testAtforkChild++;
68 }
69 
ThreadProc(void * arg)70 static void *ThreadProc(void *arg)
71 {
72     int err;
73 
74     while (g_count < 5) { // 5, wait until g_count == 5.
75         err = pthread_mutex_lock(&g_lock);
76         ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
77         g_count++;
78         SLEEP_AND_YIELD(SLEEP_TIME);
79         err = pthread_mutex_unlock(&g_lock);
80         ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
81         SLEEP_AND_YIELD(SLEEP_TIME);
82     }
83 
84 EXIT:
85     return NULL;
86 }
87 
PthreadAtforkTest(void * arg)88 static void *PthreadAtforkTest(void *arg)
89 {
90     int err;
91     pid_t pid;
92     pthread_t tid;
93     int status = 0;
94 
95     g_count = 0;
96     g_testAtforkCount = 0;
97     g_testAtforkPrepare = 0;
98     g_testAtforkParent = 0;
99     g_testAtforkChild = 0;
100 
101     err = pthread_create(&tid, NULL, ThreadProc, NULL);
102     ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
103     err = pthread_atfork(Prepare, Parent, child);
104     ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
105 
106     g_testAtforkCount++;
107 
108     SLEEP_AND_YIELD(SLEEP_TIME);
109 
110     pid = fork();
111     ICUNIT_GOTO_WITHIN_EQUAL(pid, 0, 100000, pid, EXIT); // 100000, The pid will never exceed 100000.
112     ICUNIT_GOTO_EQUAL(g_testAtforkPrepare, 1, g_testAtforkPrepare, EXIT);
113 
114     if (pid == 0) {
115         ICUNIT_GOTO_EQUAL(g_testAtforkChild, 1, g_testAtforkChild, EXIT);
116         int status;
117         while (g_count < 5) { // 5, wait until g_count == 5.
118             err = pthread_mutex_lock(&g_lock);
119             ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
120             g_count++;
121             SLEEP_AND_YIELD(SLEEP_TIME);
122             err = pthread_mutex_unlock(&g_lock);
123             ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
124             SLEEP_AND_YIELD(SLEEP_TIME);
125         }
126         exit(15); // 15, set exit status
127     }
128 
129     ICUNIT_GOTO_EQUAL(g_testAtforkParent, 1, g_testAtforkParent, EXIT_WAIT);
130     err = pthread_join(tid, NULL);
131     ICUNIT_GOTO_EQUAL(err, 0, err, EXIT_WAIT);
132 
133     err = waitpid(pid, &status, 0);
134     status = WEXITSTATUS(status);
135     ICUNIT_GOTO_EQUAL(err, pid, err, EXIT);
136     ICUNIT_GOTO_EQUAL(status, 15, status, EXIT); // 15, get exit status.
137 
138 EXIT:
139     return NULL;
140 
141 EXIT_WAIT:
142     (void)waitpid(pid, &status, 0);
143     return NULL;
144 }
145 
Testcase()146 static int Testcase()
147 {
148     int ret;
149     pthread_t newPthread;
150     int curThreadPri, curThreadPolicy;
151     pthread_attr_t a = { 0 };
152     struct sched_param param = { 0 };
153 
154     ret = pthread_getschedparam(pthread_self(), &curThreadPolicy, &param);
155     ICUNIT_ASSERT_EQUAL(ret, 0, -ret);
156 
157     curThreadPri = param.sched_priority;
158 
159     ret = pthread_attr_init(&a);
160     pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED);
161     param.sched_priority = curThreadPri + 2; // 2, adjust the priority.
162     pthread_attr_setschedparam(&a, &param);
163     ret = pthread_create(&newPthread, &a, PthreadAtforkTest, 0);
164     ICUNIT_ASSERT_EQUAL(ret, 0, ret);
165 
166     ret = pthread_join(newPthread, NULL);
167     ICUNIT_ASSERT_EQUAL(ret, 0, ret);
168 
169     return 0;
170 }
171 
ItTestPthreadAtfork001(void)172 void ItTestPthreadAtfork001(void)
173 {
174     TEST_ADD_CASE("IT_PTHREAD_ATFORK_001", Testcase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION);
175 }
176