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