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