• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <cstdio>
17 #include <cstring>
18 #include <memory>
19 #include <sys/mman.h>
20 #include <sys/ioctl.h>
21 #include <thread>
22 #include <unistd.h>
23 
24 #include <linux/ashmem.h>
25 
26 #include "gtest/gtest.h"
27 #include "ashmem.h"
28 #include "purgeable_ashmem.h"
29 #include "securec.h"
30 
31 namespace OHOS {
32 namespace PurgeableMem {
33 using namespace testing;
34 using namespace testing::ext;
35 
36 static constexpr int PRINT_INTERVAL_SECONDS = 1;
37 static constexpr int RECLAIM_INTERVAL_SECONDS = 1;
38 static constexpr int MODIFY_INTERVAL_SECONDS = 2;
39 void LoopPrintAlphabet(PurgeableAshMem *pdata, unsigned int loopCount);
40 bool ReclaimPurgeable(void);
41 void LoopReclaimPurgeable(unsigned int loopCount);
42 void ModifyPurgMemByBuilder(PurgeableAshMem *pdata, std::unique_ptr<PurgeableMemBuilder> mod);
43 
44 class TestDataBuilder : public PurgeableMemBuilder {
45 public:
TestDataBuilder(char start,char end)46     TestDataBuilder(char start, char end)
47     {
48         this->start_ = start;
49         this->end_ = end;
50     }
51 
Build(void * data,size_t size)52     bool Build(void *data, size_t size)
53     {
54         if (size <= 0) {
55             return true;
56         }
57         char *str = static_cast<char *>(data);
58         size_t len = 0;
59         for (char ch = start_; ch <= end_ && len < size; ch++) {
60             str[len++] = ch;
61         }
62         str[size - 1] = 0;
63         std::cout << "rebuild addr("<< (unsigned long long)str <<") " <<
64             start_ << "~" << end_ << ", data=[" << str << "]" << std::endl;
65         return true;
66     }
67 
~TestDataBuilder()68     ~TestDataBuilder()
69     {
70         std::cout << "~TestDataBuilder" << std::endl;
71     }
72 
73 private:
74     char start_;
75     char end_;
76 };
77 
78 class TestDataModifier : public PurgeableMemBuilder {
79 public:
TestDataModifier(char from,char to)80     TestDataModifier(char from, char to)
81     {
82         this->from_ = from;
83         this->to_ = to;
84     }
85 
Build(void * data,size_t size)86     bool Build(void *data, size_t size)
87     {
88         char *str = static_cast<char *>(data);
89         for (size_t i = 0; i < size && str[i]; i++) {
90             if (str[i] == from_) {
91                 str[i] = to_;
92             }
93         }
94         return true;
95     }
96 
~TestDataModifier()97     ~TestDataModifier()
98     {
99         std::cout << "~TestDataModifier" << std::endl;
100     }
101 
102 private:
103     char from_;
104     char to_;
105 };
106 
107 class TestBigDataBuilder : public PurgeableMemBuilder {
108 public:
TestBigDataBuilder(char target)109     explicit TestBigDataBuilder(char target)
110     {
111         this->target_ = target;
112     }
113 
Build(void * data,size_t size)114     bool Build(void *data, size_t size)
115     {
116         if (size <= 0) {
117             return true;
118         }
119         char *str = static_cast<char *>(data);
120         size_t len = 0;
121         for (char ch = target_; len < size;) {
122             str[len++] = ch;
123         }
124         str[size - 1] = 0;
125         return true;
126     }
127 
~TestBigDataBuilder()128     ~TestBigDataBuilder()
129     {
130         std::cout << "~TestBigDataBuilder" << std::endl;
131     }
132 
133 private:
134     char target_;
135 };
136 
137 class PurgeableAshmemTest : public testing::Test {
138 public:
139     static void SetUpTestCase();
140     static void TearDownTestCase();
141     void SetUp();
142     void TearDown();
143 };
144 
SetUpTestCase()145 void PurgeableAshmemTest::SetUpTestCase()
146 {
147 }
148 
TearDownTestCase()149 void PurgeableAshmemTest::TearDownTestCase()
150 {
151 }
152 
SetUp()153 void PurgeableAshmemTest::SetUp()
154 {
155 }
156 
TearDown()157 void PurgeableAshmemTest::TearDown()
158 {
159 }
160 
161 HWTEST_F(PurgeableAshmemTest, KernelInterfaceTest, TestSize.Level1)
162 {
163     size_t size = 4096 * 100;
164     int fd = AshmemCreate("Purgeable Ashmem", size);
165     ASSERT_GT(fd, 0);
166     if (AshmemSetProt(fd, PROT_READ | PROT_WRITE) < 0) {
167         close(fd);
168         return;
169     }
170     void *dataPtr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
171     if (dataPtr == MAP_FAILED) {
172         dataPtr = nullptr;
173         close(fd);
174         return;
175     }
176     char *str = static_cast<char *>(dataPtr);
177     for (size_t i = 0; i < size; i++) {
178         str[i] = 'a';
179     }
180     str[size - 1] = '\0';
181     ashmem_pin pin_ = { static_cast<uint32_t>(0), static_cast<uint32_t>(0) };
182     EXPECT_EQ(ioctl(fd, ASHMEM_GET_PURGEABLE), -1);
183     EXPECT_EQ(ioctl(fd, ASHMEM_SET_PURGEABLE), 0);
184     EXPECT_EQ(ioctl(fd, ASHMEM_GET_PURGEABLE), 1);
185     EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 1);
186     ioctl(fd, ASHMEM_PIN, &pin_);
187     EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 2);
188     ioctl(fd, ASHMEM_PIN, &pin_);
189     EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 3);
190     ioctl(fd, ASHMEM_UNPIN, &pin_);
191     EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 2);
192     ioctl(fd, ASHMEM_UNPIN, &pin_);
193     EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 1);
194     EXPECT_EQ(ioctl(fd, ASHMEM_PURGE_ALL_CACHES), 0);
195     EXPECT_EQ(ioctl(fd, PURGEABLE_ASHMEM_IS_PURGED), 0);
196     ioctl(fd, ASHMEM_UNPIN, &pin_);
197     EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 0);
198     EXPECT_EQ(ioctl(fd, PURGEABLE_ASHMEM_IS_PURGED), 0);
199     ioctl(fd, ASHMEM_PURGE_ALL_CACHES);
200     EXPECT_EQ(ioctl(fd, PURGEABLE_ASHMEM_IS_PURGED), 1);
201     ioctl(fd, ASHMEM_PIN, &pin_);
202     EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 1);
203     EXPECT_EQ(ioctl(fd, PURGEABLE_ASHMEM_IS_PURGED), 1);
204     ioctl(fd, ASHMEM_UNPIN, &pin_);
205     EXPECT_EQ(ioctl(fd, ASHMEM_GET_PIN_STATUS, &pin_), 0);
206     ioctl(fd, PURGEABLE_ASHMEM_REBUILD_SUCCESS);
207     EXPECT_EQ(ioctl(fd, PURGEABLE_ASHMEM_IS_PURGED), 0);
208 }
209 
210 HWTEST_F(PurgeableAshmemTest, MultiObjCreateTest, TestSize.Level1)
211 {
212     const char alphabetFinal[] = "BBCDEFGHIJKLMNOPQRSTUVWXYZ\0";
213     std::unique_ptr<PurgeableMemBuilder> builder1 = std::make_unique<TestDataBuilder>('A', 'Z');
214     std::unique_ptr<PurgeableMemBuilder> builder2 = std::make_unique<TestDataBuilder>('A', 'Z');
215     std::unique_ptr<PurgeableMemBuilder> mod1 = std::make_unique<TestDataModifier>('A', 'B');
216     std::unique_ptr<PurgeableMemBuilder> mod2 = std::make_unique<TestDataModifier>('A', 'B');
217 
218     PurgeableAshMem pobj1(27, std::move(builder1));
219     LoopPrintAlphabet(&pobj1, 1);
220     ModifyPurgMemByBuilder(&pobj1, std::move(mod1));
221     LoopPrintAlphabet(&pobj1, 1);
222     LoopReclaimPurgeable(1);
223 
224     PurgeableAshMem pobj2(27, std::move(builder2));
225     LoopPrintAlphabet(&pobj2, 1);
226     ModifyPurgMemByBuilder(&pobj2, std::move(mod2));
227     LoopPrintAlphabet(&pobj2, 1);
228     LoopReclaimPurgeable(1);
229 
230     int ret1 = 1;
231     int ret2 = 1;
232     int times1 = 0;
233     int times2 = 0;
234     while (times1++ < 10) {
235         if (pobj1.BeginRead()) {
236             ret1 = strncmp(alphabetFinal, static_cast<char *>(pobj1.GetContent()), 26);
237             pobj1.EndRead();
238             break;
239         } else {
240             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
241         }
242     }
243 
244     while (times2++ < 10) {
245         if (pobj2.BeginRead()) {
246             ret2 = strncmp(alphabetFinal, static_cast<char *>(pobj2.GetContent()), 26);
247             pobj2.EndRead();
248             break;
249         } else {
250             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
251         }
252     }
253 
254     EXPECT_EQ(ret1, 0);
255     EXPECT_EQ(ret2, 0);
256 }
257 
258 HWTEST_F(PurgeableAshmemTest, ReadTest, TestSize.Level1)
259 {
260     const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\0";
261     std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestDataBuilder>('A', 'Z');
262     PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(27, std::move(builder));
263     ASSERT_NE(pobj, nullptr);
264     LoopReclaimPurgeable(1);
265 
266     int times = 0;
267     int ret = 1;
268     while (times++ < 10) {
269         if (pobj->BeginRead()) {
270             ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 26);
271             pobj->EndRead();
272             break;
273         } else {
274             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
275         }
276     }
277     delete pobj;
278     pobj = nullptr;
279     EXPECT_EQ(ret, 0);
280 }
281 
282 HWTEST_F(PurgeableAshmemTest, WriteTest, TestSize.Level1)
283 {
284     const char alphabet[] = "CCCDEFGHIJKLMNOPQRSTUVWXYZ\0";
285     std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestDataBuilder>('A', 'Z');
286     PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(27, std::move(builder));
287     ASSERT_NE(pobj, nullptr);
288     LoopReclaimPurgeable(1);
289 
290     std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
291     std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
292     ModifyPurgMemByBuilder(pobj, std::move(modA2B));
293     ModifyPurgMemByBuilder(pobj, std::move(modB2C));
294 
295     int times = 0;
296     int ret = 1;
297     while (times++ < 10) {
298         if (pobj->BeginRead()) {
299             ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 26);
300             pobj->EndRead();
301             break;
302         } else {
303             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
304         }
305     }
306     delete pobj;
307     pobj = nullptr;
308     EXPECT_EQ(ret, 0);
309 }
310 
311 HWTEST_F(PurgeableAshmemTest, ReadWriteTest, TestSize.Level1)
312 {
313     const char alphabet[] = "DDDDEFGHIJKLMNOPQRSTUVWXYZ\0";
314     std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestDataBuilder>('A', 'Z');
315     PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(27, std::move(builder));
316     ASSERT_NE(pobj, nullptr);
317 
318     LoopReclaimPurgeable(1);
319     LoopPrintAlphabet(pobj, 1);
320 
321     std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
322     std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
323     std::unique_ptr<PurgeableMemBuilder> modC2D = std::make_unique<TestDataModifier>('C', 'D');
324     ModifyPurgMemByBuilder(pobj, std::move(modA2B));
325     ModifyPurgMemByBuilder(pobj, std::move(modB2C));
326     ModifyPurgMemByBuilder(pobj, std::move(modC2D));
327 
328     int times = 0;
329     int ret = 1;
330     while (times++ < 10) {
331         if (pobj->BeginRead()) {
332             ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 26);
333             pobj->EndRead();
334             break;
335         } else {
336             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
337         }
338     }
339     delete pobj;
340     pobj = nullptr;
341     EXPECT_EQ(ret, 0);
342 }
343 
344 HWTEST_F(PurgeableAshmemTest, MutiPageReadTest, TestSize.Level1)
345 {
346     char alphabet[4098];
347     size_t len = 0;
348     for (char ch = 'A'; len < 4098;) {
349         alphabet[len++] = ch;
350     }
351     alphabet[4097] = 0;
352     std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestBigDataBuilder>('A');
353     PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(4098, std::move(builder));
354     ASSERT_NE(pobj, nullptr);
355 
356     LoopReclaimPurgeable(1);
357 
358     int times = 0;
359     int ret = 1;
360     while (times++ < 10) {
361         if (pobj->BeginRead()) {
362             ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 4097);
363             pobj->EndRead();
364             break;
365         } else {
366             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
367         }
368     }
369     delete pobj;
370     pobj = nullptr;
371     EXPECT_EQ(ret, 0);
372 }
373 
374 HWTEST_F(PurgeableAshmemTest, MutiPageWriteTest, TestSize.Level1)
375 {
376     char alphabet[4098];
377     size_t len = 0;
378     for (char ch = 'C'; len < 4098;) {
379         alphabet[len++] = ch;
380     }
381     alphabet[4097] = 0;
382     std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestBigDataBuilder>('A');
383     PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(4098, std::move(builder));
384     ASSERT_NE(pobj, nullptr);
385 
386     LoopReclaimPurgeable(1);
387 
388     std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
389     std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
390     ModifyPurgMemByBuilder(pobj, std::move(modA2B));
391     ModifyPurgMemByBuilder(pobj, std::move(modB2C));
392 
393     int times = 0;
394     int ret = 1;
395     while (times++ < 10) {
396         if (pobj->BeginRead()) {
397             ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 4097);
398             pobj->EndRead();
399             break;
400         } else {
401             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
402         }
403     }
404     delete pobj;
405     pobj = nullptr;
406     EXPECT_EQ(ret, 0);
407 }
408 
409 HWTEST_F(PurgeableAshmemTest, MutiPageReadWriteTest, TestSize.Level1)
410 {
411     char alphabet[4098];
412     size_t len = 0;
413     for (char ch = 'D'; len < 4098;) {
414         alphabet[len++] = ch;
415     }
416     alphabet[4097] = 0;
417     std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestBigDataBuilder>('A');
418     PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(4098, std::move(builder));
419     ASSERT_NE(pobj, nullptr);
420     LoopReclaimPurgeable(1);
421     LoopPrintAlphabet(pobj, 1);
422 
423     std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
424     std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
425     std::unique_ptr<PurgeableMemBuilder> modC2D = std::make_unique<TestDataModifier>('C', 'D');
426     ModifyPurgMemByBuilder(pobj, std::move(modA2B));
427     ModifyPurgMemByBuilder(pobj, std::move(modB2C));
428     ModifyPurgMemByBuilder(pobj, std::move(modC2D));
429 
430     int times = 0;
431     int ret = 1;
432     while (times++ < 10) {
433         if (pobj->BeginRead()) {
434             ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), 4097);
435             pobj->EndRead();
436             break;
437         } else {
438             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
439         }
440     }
441     delete pobj;
442     pobj = nullptr;
443     EXPECT_EQ(ret, 0);
444 }
445 
446 HWTEST_F(PurgeableAshmemTest, MutiMorePageReadWriteTest, TestSize.Level1)
447 {
448     size_t size = 5 * 1024 * 1024;
449     char *alphabet = (char *)malloc(size);
450     size_t len = 0;
451     for (char ch = 'D'; len < size;) {
452         alphabet[len++] = ch;
453     }
454     alphabet[size - 1] = 0;
455     std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestBigDataBuilder>('A');
456     PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(size, std::move(builder));
457     ASSERT_NE(pobj, nullptr);
458 
459     LoopReclaimPurgeable(1);
460     LoopPrintAlphabet(pobj, 1);
461 
462     std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
463     std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
464     std::unique_ptr<PurgeableMemBuilder> modC2D = std::make_unique<TestDataModifier>('C', 'D');
465     ModifyPurgMemByBuilder(pobj, std::move(modA2B));
466     ModifyPurgMemByBuilder(pobj, std::move(modB2C));
467     ModifyPurgMemByBuilder(pobj, std::move(modC2D));
468 
469     int times = 0;
470     int ret = 1;
471     while (times++ < 10) {
472         if (pobj->BeginRead()) {
473             ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), size - 1);
474             pobj->EndRead();
475             break;
476         } else {
477             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
478         }
479     }
480     delete pobj;
481     pobj = nullptr;
482     free(alphabet);
483     alphabet = nullptr;
484     EXPECT_EQ(ret, 0);
485 }
486 
487 HWTEST_F(PurgeableAshmemTest, StableMutiMorePageReadWriteTest, TestSize.Level1)
488 {
489     size_t size = 5 * 1024 * 1024;
490     char *alphabet = (char *)malloc(size);
491     size_t len = 0;
492     for (char ch = 'D'; len < size;) {
493         alphabet[len++] = ch;
494     }
495     alphabet[size - 1] = 0;
496     std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestBigDataBuilder>('A');
497     PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(size, std::move(builder));
498     ASSERT_NE(pobj, nullptr);
499 
500     std::thread reclaimThread(LoopReclaimPurgeable, 10);
501     std::thread readThread(LoopPrintAlphabet, pobj, 10);
502 
503     std::unique_ptr<PurgeableMemBuilder> modA2B = std::make_unique<TestDataModifier>('A', 'B');
504     std::unique_ptr<PurgeableMemBuilder> modB2C = std::make_unique<TestDataModifier>('B', 'C');
505     std::unique_ptr<PurgeableMemBuilder> modC2D = std::make_unique<TestDataModifier>('C', 'D');
506     ModifyPurgMemByBuilder(pobj, std::move(modA2B));
507     ModifyPurgMemByBuilder(pobj, std::move(modB2C));
508     ModifyPurgMemByBuilder(pobj, std::move(modC2D));
509 
510     int times = 0;
511     int ret = 1;
512     while (times++ < 10) {
513         if (pobj->BeginRead()) {
514             ret = strncmp(alphabet, static_cast<char *>(pobj->GetContent()), size - 1);
515             pobj->EndRead();
516             break;
517         } else {
518             std::cout << __func__ << ": ERROR! BeginRead failed." << std::endl;
519         }
520     }
521     reclaimThread.join();
522     readThread.join();
523     delete pobj;
524     pobj = nullptr;
525     free(alphabet);
526     alphabet = nullptr;
527     EXPECT_EQ(ret, 0);
528 }
529 
530 HWTEST_F(PurgeableAshmemTest, InvalidInputSizeTest, TestSize.Level1)
531 {
532     std::unique_ptr<PurgeableMemBuilder> builder = std::make_unique<TestDataBuilder>('A', 'Z');
533     PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(0, std::move(builder));
534     ASSERT_NE(pobj, nullptr);
535     bool ret = pobj->BeginRead();
536     if (ret) {
537         pobj->EndRead();
538     }
539     delete pobj;
540     pobj = nullptr;
541     EXPECT_EQ(ret, false);
542 }
543 
544 HWTEST_F(PurgeableAshmemTest, InvalidInputBuilderTest, TestSize.Level1)
545 {
546     PurgeableAshMem *pobj = new (std::nothrow) PurgeableAshMem(27, nullptr);
547     ASSERT_NE(pobj, nullptr);
548     bool ret = pobj->BeginRead();
549     if (ret) {
550         pobj->EndRead();
551     }
552     delete pobj;
553     pobj = nullptr;
554     EXPECT_EQ(ret, false);
555 }
556 
LoopPrintAlphabet(PurgeableAshMem * pdata,unsigned int loopCount)557 void LoopPrintAlphabet(PurgeableAshMem *pdata, unsigned int loopCount)
558 {
559     std::cout << "inter " << __func__ << std::endl;
560     for (unsigned int i = 0; i < loopCount; i++) {
561         if (!pdata->BeginRead()) {
562             std::cout << __func__ << ": " << i << ". ERROR! BeginRead failed." << std::endl;
563             break;
564         }
565         pdata->EndRead();
566         std::this_thread::sleep_for(std::chrono::seconds(PRINT_INTERVAL_SECONDS));
567     }
568     std::cout << "quit " << __func__ << std::endl;
569 }
570 
ReclaimPurgeable(void)571 bool ReclaimPurgeable(void)
572 {
573     FILE *f = fopen("/proc/sys/vm/drop_caches", "w");
574     if (!f) {
575         std::cout << __func__ << ": kernel not support" << std::endl;
576         return false;
577     }
578     bool succ = true;
579     if (fputs("3", f) == EOF) {
580         succ = false;
581     }
582 
583     if (fclose(f) == EOF) {
584         std::cout << __func__ << ": close file failed" << std::endl;
585     }
586 
587     return succ;
588 }
589 
LoopReclaimPurgeable(unsigned int loopCount)590 void LoopReclaimPurgeable(unsigned int loopCount)
591 {
592     bool ret = false;
593     std::cout << "inter " << __func__ << std::endl;
594     for (unsigned int i = 0; i < loopCount; i++) {
595         ret = ReclaimPurgeable();
596         std::cout << __func__ << ": " << i << ". Reclaim result=" << (ret ? "succ" : "fail") << std::endl;
597         std::this_thread::sleep_for(std::chrono::seconds(RECLAIM_INTERVAL_SECONDS)); /* wait reclaim finish */
598     }
599     std::cout << "quit " << __func__ << std::endl;
600 }
601 
ModifyPurgMemByBuilder(PurgeableAshMem * pdata,std::unique_ptr<PurgeableMemBuilder> mod)602 void ModifyPurgMemByBuilder(PurgeableAshMem *pdata, std::unique_ptr<PurgeableMemBuilder> mod)
603 {
604     if (!pdata->BeginWrite()) {
605         std::cout << __func__ << ": ERROR! BeginWrite failed." << std::endl;
606         return;
607     }
608     std::this_thread::sleep_for(std::chrono::seconds(MODIFY_INTERVAL_SECONDS));
609     pdata->ModifyContentByBuilder(std::move(mod));
610     pdata->EndWrite();
611 }
612 } /* namespace PurgeableAshMem */
613 } /* namespace OHOS */
614