• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 <fcntl.h>
17 #include <pthread.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
22 #include <sys/mman.h>
23 #include <sys/stat.h>
24 #include <sys/syscall.h>
25 #include <sys/types.h>
26 
27 #include <unistd.h>
28 #ifdef HOOK_ENABLE
29 #include "memory_trace.h"
30 #endif
31 #include "securec.h"
32 #pragma clang optimize off
33 
34 #define PAGE_SIZE 4096
35 #define SLEEP_TIME_SEC 1
36 #define RESPONSE_SPEED 300
37 #define DATA_SIZE 50
38 #define ALLOC_FLAG (1 << 0)
39 #define MMAP_FLAG (1 << 1)
40 
41 const int DEFAULT_REALLOC_SIZE = 100;
42 const int TEST_BRANCH_NUM = 3;
43 const int STATIC_DEPTH = 5;
44 
45 typedef struct {
46     int data[DATA_SIZE];
47 } StaticSpace;
48 
49 static double g_mallocDuration = 0;
50 static double g_callocDuration = 0;
51 static double g_reallocDuration = 0;
52 static double g_freeDuration = 0;
53 
54 static int g_fd = -1;
55 static int g_runing = 1;
56 static int g_threadNum = 1;
57 static int g_mallocSize = 1;
58 static char* g_fileName = "./mmapTest";
59 static unsigned int g_hookFlag = 0;
60 
DepthMalloc(int depth,int mallocSize)61 char* DepthMalloc(int depth, int mallocSize)
62 {
63     if (mallocSize <= 0) {
64         return NULL;
65     }
66     StaticSpace staticeData;
67     if (depth == 0) {
68         staticeData.data[0] = 1;
69         return (char*)malloc(mallocSize);
70     }
71     return (DepthMalloc(depth - 1, mallocSize));
72 }
73 
DepthCalloc(int depth,int callocSize)74 char* DepthCalloc(int depth, int callocSize)
75 {
76     StaticSpace staticeData;
77     if (depth == 0) {
78         staticeData.data[0] = 1;
79         return (char*)calloc(sizeof(char), callocSize);
80     }
81     return (DepthCalloc(depth - 1, callocSize));
82 }
83 
DepthRealloc(int depth,void * p,int reallocSize)84 char* DepthRealloc(int depth, void* p, int reallocSize)
85 {
86     StaticSpace staticeData;
87     if (depth == 0) {
88         staticeData.data[0] = 1;
89         return (char*)realloc(p, reallocSize);
90     }
91     return (DepthRealloc(depth - 1, p, reallocSize));
92 }
93 
DepthFree(int depth,void * p)94 void DepthFree(int depth, void* p)
95 {
96     StaticSpace staticeData;
97     if (depth == 0) {
98         staticeData.data[0] = 1;
99         free(p);
100         return;
101     }
102     return (DepthFree(depth - 1, p));
103 }
104 
ApplyForMalloc(int mallocSize)105 void ApplyForMalloc(int mallocSize)
106 {
107     printf("\nstart malloc apply (size = %d)\n", mallocSize);
108     clock_t timerStart = 0;
109     clock_t timerStop = 0;
110     double duration = 0;
111     timerStart = clock();
112     char* p = DepthMalloc(STATIC_DEPTH, mallocSize);
113     timerStop = clock();
114     if (!p) {
115         printf("malloc failure\n");
116         return;
117     }
118     duration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
119     g_mallocDuration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
120     printf("malloc success, malloc (%d) time is %f\n", mallocSize, duration);
121     printf("\nReady for free -- ");
122     timerStart = clock();
123     DepthFree(STATIC_DEPTH, p);
124     timerStop = clock();
125     duration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
126     g_freeDuration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
127     printf("free success, free time is %f\n", (double)(timerStop - timerStart) / CLOCKS_PER_SEC);
128     printf("malloc apply success, total time is %f\n", duration);
129 }
130 
ApplyForCalloc(int mallocSize)131 void ApplyForCalloc(int mallocSize)
132 {
133     int callocSize = mallocSize / sizeof(char);
134     printf("\nstart calloc apply (size = %d)\n", callocSize);
135     clock_t timerStart = 0;
136     clock_t timerStop = 0;
137     double duration = 0;
138     timerStart = clock();
139     char* p = DepthCalloc(STATIC_DEPTH, callocSize);
140     timerStop = clock();
141     if (!p) {
142         printf("calloc failure\n");
143         return;
144     }
145     duration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
146     g_callocDuration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
147     printf("calloc success, calloc (%d) time is %f\n", callocSize, duration);
148     printf("\nReady for free -- ");
149     timerStart = clock();
150     DepthFree(STATIC_DEPTH, p);
151     timerStop = clock();
152     duration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
153     g_freeDuration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
154     printf("free success, free time is %f\n", (double)(timerStop - timerStart) / CLOCKS_PER_SEC);
155     printf("calloc apply success, total time is %f\n", duration);
156 }
157 
ApplyForRealloc(int mallocSize)158 void ApplyForRealloc(int mallocSize)
159 {
160     int reallocSize = mallocSize * DEFAULT_REALLOC_SIZE;
161     printf("\nstart realloc apply (size = %d)\n", reallocSize);
162     if (mallocSize <= 0) {
163         printf("Invalid mallocSize.\n");
164         return;
165     }
166     clock_t timerStart = 0;
167     clock_t timerStop = 0;
168     double duration = 0;
169     char* p = (char*)malloc(mallocSize);
170     if (!p) {
171         printf("malloc failure\n");
172         return;
173     }
174     timerStart = clock();
175     char* np = DepthRealloc(STATIC_DEPTH, p, reallocSize);
176     timerStop = clock();
177     if (!np) {
178         free(p);
179         printf("realloc failure\n");
180         return;
181     }
182     duration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
183     g_reallocDuration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
184     printf("realloc success, realloc (%d) time is %f\n", reallocSize, duration);
185     printf("\nReady for free -- ");
186     timerStart = clock();
187     DepthFree(STATIC_DEPTH, np);
188     timerStop = clock();
189     duration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
190     g_freeDuration += (double)(timerStop - timerStart) / CLOCKS_PER_SEC;
191     printf("free success, free time is %f\n", (double)(timerStop - timerStart) / CLOCKS_PER_SEC);
192     printf("realloc apply success, total time is %f\n", duration);
193 }
194 
ThreadFuncC(void * param)195 void* ThreadFuncC(void* param)
196 {
197     int mallocCount = 0;
198     int callocCount = 0;
199     int reallocCount = 0;
200     int freeCount = 0;
201     int randNum = 0;
202     int tid = syscall(SYS_gettid);
203     int mallocSize = *(int*)param;
204     printf("start thread %d\n", tid);
205     time_t tv = time(NULL);
206     if (tv == -1) {
207         tv = 1;
208     }
209     unsigned int seed = (unsigned int)tv;
210     while (g_runing) {
211         randNum = rand_r(&seed) % TEST_BRANCH_NUM;
212         if (randNum == 0) {
213             ApplyForMalloc(mallocSize);
214             mallocCount++;
215         } else if (randNum == 1) {
216             ApplyForCalloc(mallocSize);
217             callocCount++;
218         } else {
219             ApplyForRealloc(mallocSize);
220             reallocCount++;
221         }
222         freeCount++;
223         sleep(SLEEP_TIME_SEC);
224     }
225 
226     printf("thread %d  malloc count[%d] totalTime[%f] meanTime[%f].\n", tid,
227         mallocCount, g_mallocDuration, g_mallocDuration / mallocCount);
228     printf("thread %d  calloc count[%d] totalTime[%f] meanTime[%f].\n", tid,
229         callocCount, g_callocDuration, g_callocDuration / callocCount);
230     printf("thread %d realloc count[%d] totalTime[%f] meanTime[%f].\n", tid,
231         reallocCount, g_reallocDuration, g_reallocDuration / reallocCount);
232     printf("thread %d    free count[%d] totalTime[%f] meanTime[%f].\n", tid,
233         freeCount, g_freeDuration, g_freeDuration / freeCount);
234     printf("finish thread %d\n", tid);
235 
236     return NULL;
237 }
238 
239 // 打开文件到内存中
OpenFile(const char * fileName)240 int OpenFile(const char* fileName)
241 {
242     int fd = open(fileName, O_RDWR | O_CREAT, (mode_t)0644); // 0644 rw-r--r--
243     if (fd == -1) {
244         printf("can not open the file\n");
245         return -1;
246     }
247     return fd;
248 }
249 
250 // 关闭文件
CloseFile(void)251 void CloseFile(void)
252 {
253     if (g_fd > 0) {
254         close(g_fd);
255         g_fd = -1;
256     }
257 }
258 
259 // 给文件建立内存映射
CreateMmap(void)260 char* CreateMmap(void)
261 {
262     if (g_fd == -1) {
263         return NULL;
264     }
265     int size = PAGE_SIZE;
266     lseek(g_fd, size + 1, SEEK_SET);
267     write(g_fd, "", 1);
268 
269     char* pMap = (char*)mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, g_fd, 0);
270 #ifdef HOOK_ENABLE
271     char *tag = "memtesttag";
272     memtrace(pMap, PAGE_SIZE, tag, true);
273 #endif
274     if (pMap == MAP_FAILED) {
275         printf("mmap fail\n");
276         CloseFile();
277     }
278     return pMap;
279 }
280 
281 // 关闭文件内存映射
RemoveMmap(char * pMap)282 void RemoveMmap(char* pMap)
283 {
284     munmap(pMap, PAGE_SIZE);
285 }
286 
287 // 给文件映射中写入
MmapWriteFile(char * pMap,int length,char * data)288 void MmapWriteFile(char* pMap, int length, char* data)
289 {
290     if (memcpy_s(pMap, length, data, length) != EOK) {
291         printf("memcpy_s type fail\n");
292         return;
293     }
294     msync(pMap, length, MS_SYNC);
295 }
296 
297 // 从文件映射中读取
MmapReadFile(char * pMap,int length)298 char* MmapReadFile(char* pMap, int length)
299 {
300     if (length <= 0) {
301         printf("fail:malloc %d memory", length);
302         return NULL;
303     }
304     char* data = (char*)malloc(length + 1);
305     if (data != NULL) {
306         if (memcpy_s(data, length+1, pMap, length) != EOK) {
307             printf("memcpy_s type fail\n");
308             free(data);
309             return NULL;
310         }
311         data[length] = '\0';
312     }
313     return data;
314 }
315 
RandSrand(void)316 static void RandSrand(void)
317 {
318     (void)srand((unsigned)time(NULL));
319 }
320 
321 // 10 ~ 4096
RandInt(int maxVal,int minVal)322 int RandInt(int maxVal, int minVal)
323 {
324     int value = (rand() % (maxVal - minVal)) + minVal;
325     return value;
326 }
327 
328 // 生成一个随机字符 (0x20 ~ 0x7E)
RandChar(void)329 char RandChar(void)
330 {
331     // 可显示字符的范围
332     int section = '~' - ' ';
333     int randSection = RandInt(0, section);
334     char randChar = (char)('~' + (unsigned int)randSection);
335     return randChar;
336 }
337 
338 // 获取随机长度的字符串
RandString(int maxLength)339 char* RandString(int maxLength)
340 {
341     int strLength = RandInt(10, maxLength);
342     if (strLength <= 0) {
343         printf("fail:malloc %d memory", strLength);
344         return NULL;
345     }
346     char* data = (char*)malloc(strLength + 1);
347     if (data != NULL) {
348         for (int i = 0; i < strLength; i++) {
349             data[i] = RandChar();
350         }
351     data[strLength] = '\0';
352     }
353     return data;
354 }
355 
356 // 初始化函数
MmapInit(void)357 void MmapInit(void)
358 {
359     // 设置随机种子
360     RandSrand();
361     // 设置全局映射的目标文件
362     g_fd = OpenFile(g_fileName);
363 }
364 
365 // 写映射
WriteMmap(char * data)366 void WriteMmap(char* data)
367 {
368     // 建立映射
369     char* pMap = CreateMmap();
370     // 写入
371     MmapWriteFile(pMap, strlen(data), data);
372 
373     // 关闭映射
374     RemoveMmap(pMap);
375 }
376 
377 // 读映射
ReadMmap(int length)378 char* ReadMmap(int length)
379 {
380     // 建立映射
381     char* pMap = CreateMmap();
382 
383     // 写入
384     char* outTestchar = MmapReadFile(pMap, length);
385 
386     // 关闭映射
387     RemoveMmap(pMap);
388 
389     return outTestchar;
390 }
391 
ThreadMmap(void * param)392 void* ThreadMmap(void* param)
393 {
394     while (g_runing) {
395         // 获取随机字符
396         char* randString = RandString(PAGE_SIZE);
397         // 写入映射
398         WriteMmap(randString);
399         // 从映射中读取
400         char* outchar = ReadMmap(strlen(randString));
401         printf("thread %ld : Mmap test OK! \n", syscall(SYS_gettid));
402         free(randString);
403         free(outchar);
404         sleep(SLEEP_TIME_SEC);
405     }
406     return NULL;
407 }
408 
409 // 维护hook test类型管理
BitMapNum(unsigned int data)410 int BitMapNum(unsigned int data)
411 {
412     unsigned int tmp = data;
413     int num = 0;
414     while (tmp) {
415         if (tmp & 1) {
416             num++;
417         }
418         tmp >>= 1;
419     }
420     return num;
421 }
422 
423 // 参数解析
CommandParse(int argc,char ** argv)424 int CommandParse(int argc, char** argv)
425 {
426     int result;
427     opterr = 0;
428     while ((result = getopt(argc, argv, "t:s:n:o:h:")) != -1) {
429         switch (result) {
430             case 't':
431                 // hook test的类型
432                 if (!strcmp("mmap", optarg)) {
433                     printf("Type: %s \n", optarg);
434                     g_hookFlag |= MMAP_FLAG;
435                 } else if (!strcmp("alloc", optarg)) {
436                     printf("Type: %s \n", optarg);
437                     g_hookFlag |= ALLOC_FLAG;
438                 } else if (!strcmp("all", optarg)) {
439                     printf("Type: %s \n", optarg);
440                     g_hookFlag |= ALLOC_FLAG;
441                     g_hookFlag |= MMAP_FLAG;
442                 }
443                 break;
444             case 's':
445                 // 栈大小
446                 g_mallocSize = atoi(optarg);
447                 if (g_mallocSize <= 0) {
448                     printf("Invalid mallocSize\n");
449                     return -1;
450                 }
451                 break;
452             case 'n':
453                 // 线程数
454                 g_threadNum = atoi(optarg);
455                 if (g_threadNum <= 0) {
456                     printf("Invalid threadNum.\n");
457                     return -1;
458                 }
459                 break;
460             case 'o':
461                 g_fileName = optarg;
462                 break;
463             case 'h':
464             default:
465                 printf("%s -t <alloc/mmap>\n", argv[0]);
466                 printf("\talloc : -s [alloc mallocSize] -n [thread Num]\n");
467                 printf("\t mmap : -o [mmap datafile]\n");
468                 return -1;
469         }
470     }
471     return opterr;
472 }
473 
main(int argc,char * argv[])474 int main(int argc, char* argv[])
475 {
476     // 参数解析
477     int ret = CommandParse(argc, argv);
478     if (ret == -1) {
479         return 0;
480     }
481     int typeNum = BitMapNum(g_hookFlag);
482     printf(" g_hookFlag =  [%x] \n", g_hookFlag);
483     if (typeNum == 0) {
484         // 未设置type时默认启动alloc
485         g_hookFlag |= ALLOC_FLAG;
486         typeNum++;
487     }
488 
489     pthread_t** thrArrayList = (pthread_t**)malloc(sizeof(pthread_t*) * typeNum);
490     if (thrArrayList == NULL) {
491         printf("malloc thrArrayList fail\n");
492         return 0;
493     }
494     int type = 0;
495     if (g_hookFlag & ALLOC_FLAG) {
496         int threadNum = g_threadNum;
497         int mallocSize = g_mallocSize;
498 
499         pid_t pid = getpid();
500         printf("Process pid %d, Test start %d thread, malloc %d size\n", pid, threadNum, mallocSize);
501 
502         thrArrayList[type] = (pthread_t*)malloc(sizeof(pthread_t) * threadNum);
503         // pthread_t* thrArray
504         if (thrArrayList[type] == NULL) {
505             printf("new thread failed.\n");
506             if (thrArrayList != NULL) {
507                 free(thrArrayList);
508                 thrArrayList = NULL;
509             }
510             return 0;
511         }
512         int idx;
513         for (idx = 0; idx < threadNum; ++idx) {
514             if (pthread_create((thrArrayList[type]) + idx, NULL, ThreadFuncC, (void*)(&mallocSize))) {
515                 printf("Creating thread failed.\n");
516             }
517         }
518         type++;
519     }
520 
521     if (g_hookFlag & MMAP_FLAG) {
522         int threadNum = g_threadNum;
523         // 初始化
524         MmapInit();
525 
526         thrArrayList[type] = (pthread_t*)malloc(sizeof(pthread_t) * threadNum);
527         if (thrArrayList[type] == NULL) {
528             printf("new thread failed.\n");
529             if (thrArrayList != NULL) {
530                 free(thrArrayList);
531                 thrArrayList = NULL;
532             }
533             CloseFile();
534             return 0;
535         }
536 
537         int idx;
538         for (idx = 0; idx < threadNum; ++idx) {
539             if (pthread_create((thrArrayList[type]) + idx, NULL, ThreadMmap, NULL)) {
540                 printf("Creating thread failed.\n");
541             }
542         }
543     }
544 
545     while (getchar() != '\n') {
546         usleep(RESPONSE_SPEED);
547     };
548     g_runing = 0;
549     int idx;
550     for (type = 0; type < typeNum; type++) {
551         for (idx = 0; idx < g_threadNum; ++idx) {
552             pthread_join((thrArrayList[type])[idx], NULL);
553         }
554         if (thrArrayList[type] != NULL) {
555             free(thrArrayList[type]);
556             thrArrayList[type] = NULL;
557         }
558     }
559     if (thrArrayList != NULL) {
560         free(thrArrayList);
561         thrArrayList = NULL;
562     }
563     CloseFile();
564     return 0;
565 }
566 
567 #pragma clang optimize on
568