1#include <malloc.h>
2#include <time.h>
3#include <sched.h>
4#include <errno.h>
5#include <string.h>
6#include <pthread.h>
7#include "test.h"
8
9#define THREAD_MAX_N 8
10#define SIZE_ALIGN (4 * sizeof(size_t))
11#define MMAP_THRESHOLD 131052
12#define FREE_CYCLE 16
13#define THRESHOLD (MMAP_THRESHOLD / 16)
14#define ITER_TIME 80
15#define NANOSEC_PER_SEC 1e9
16#define MALLOC_TIME (ITER_TIME * (THRESHOLD / (SIZE_ALIGN + 1)))
17
18void free_all(void **ptr)
19{
20	for (int j = 0; j < FREE_CYCLE; j++) {
21		free(ptr[j]);
22	}
23}
24
25void *func(void *arg)
26{
27	int *val = (int *)arg;
28	cpu_set_t mask;
29	struct timespec ts[2];
30	int num = 0;
31	void *ptr[FREE_CYCLE];
32
33	CPU_ZERO(&mask);
34	CPU_SET(0, &mask);
35	if (sched_setaffinity(0, sizeof(mask), &mask) < 0) {
36		t_error("Set CPU affinity of thread %d failure, ERROR:%s\n", *val, strerror(errno));
37		return NULL;
38	}
39
40	for (int i = 0; i < ITER_TIME; ++i) {
41		for (size_t size = 0; size < THRESHOLD; size += SIZE_ALIGN + 1) {
42			if (num == FREE_CYCLE) {
43				free_all(ptr);
44				num = 0;
45			}
46			ptr[num] = malloc(size);
47			if (!ptr[num]) {
48				t_error("Thread %d malloc failed for size %u\n", *val, size);
49				*val = errno;
50				return NULL;
51			}
52			num++;
53		}
54	}
55
56	*val = 0;
57	return NULL;
58}
59
60int main(int argc, char *argv[])
61{
62	struct timespec ts[2];
63	pthread_attr_t attr;
64	pthread_t tids[THREAD_MAX_N];
65	int t_result[THREAD_MAX_N] = {0};
66	int flag = 0;
67	int ret;
68	int i;
69
70	ret = pthread_attr_init(&attr);
71	if (ret < 0) {
72		t_error("Init pthread attribute failed: %s\n", strerror(errno));
73		return -1;
74	}
75
76	clock_gettime(CLOCK_REALTIME, ts);
77	for (i = 0; i < THREAD_MAX_N; ++i) {
78		t_result[i] = i;
79		ret = pthread_create(&tids[i], &attr, func, &t_result[i]);
80		if (ret < 0) {
81			t_error("Create pthread %u failed: %s\n", i, strerror(errno));
82			flag = -1;
83			break;
84		}
85	}
86
87	for (i = 0; i < THREAD_MAX_N; ++i) {
88		ret = pthread_join(tids[i], NULL);
89		if (ret < 0) {
90			t_error("Join thread %u failed: %s\n", i, strerror(errno));
91		}
92	}
93	clock_gettime(CLOCK_REALTIME, ts + 1);
94
95	(void)pthread_attr_destroy(&attr);
96
97	double cost = (ts[1].tv_sec - ts[0].tv_sec) * NANOSEC_PER_SEC +
98		(ts[1].tv_nsec - ts[0].tv_nsec);
99
100	if (!flag) {
101		t_printf("Malloc and free %d threads %d times cost %lf s\n", THREAD_MAX_N, MALLOC_TIME, cost / NANOSEC_PER_SEC);
102		t_status = 0;
103	}
104
105	return t_status;
106}
107