2
* $Id: t-test1.c,v 1.1.1.1 2003/07/02 16:32:09 matthias.urban Exp $
3
* by Wolfram Gloger 1996-1999
4
* A multi-thread test for malloc performance, maintaining one pool of
5
* allocated bins per thread.
10
#if USE_PTHREADS /* Posix threads */
14
pthread_cond_t finish_cond = PTHREAD_COND_INITIALIZER;
15
pthread_mutex_t finish_mutex = PTHREAD_MUTEX_INITIALIZER;
19
#if (defined __STDC__ && __STDC__) || defined __cplusplus
24
#include <sys/types.h>
26
#include <sys/resource.h>
43
#define N_TOTAL_PRINT 50
45
#define STACKSIZE 32768
47
#define MEMORY 8000000l
51
#define ACTIONS_MAX 30
53
#define RANDOM(d,s) (lran2(d) % (s))
57
unsigned long size, bins;
63
bin_test(struct bin_info *p)
67
for(b=0; b<p->bins; b++) {
68
if(mem_check(p->m[b].ptr, p->m[b].size)) {
69
printf("memory corrupt!\n");
85
#if USE_PTHREADS || USE_THR || defined NO_THREADS
87
malloc_test(void *ptr)
90
malloc_test(void *ptr, size_t stack_len)
93
struct thread_st *st = ptr;
94
int b, i, j, actions, pid = 1;
96
struct lran2_st ld; /* data for random number generator */
98
lran2_init(&ld, st->seed);
100
if(RANDOM(&ld, TEST_FORK) == 0) {
106
printf("waiting for %d...\n", pid);
107
waitpid(pid, &status, 0);
108
if(!WIFEXITED(status)) {
109
printf("child term with signal %d\n", WTERMSIG(status));
115
p.m = (struct bin *)malloc(st->bins*sizeof(*p.m));
118
for(b=0; b<p.bins; b++) {
121
if(RANDOM(&ld, 2) == 0)
122
bin_alloc(&p.m[b], RANDOM(&ld, p.size) + 1, lran2(&ld));
124
for(i=0; i<=st->max;) {
128
actions = RANDOM(&ld, ACTIONS_MAX);
129
#if USE_MALLOC && MALLOC_DEBUG
130
if(actions < 2) { mallinfo(); }
132
for(j=0; j<actions; j++) {
133
b = RANDOM(&ld, p.bins);
137
actions = RANDOM(&ld, ACTIONS_MAX);
138
for(j=0; j<actions; j++) {
139
b = RANDOM(&ld, p.bins);
140
bin_alloc(&p.m[b], RANDOM(&ld, p.size) + 1, lran2(&ld));
145
#if 0 /* Test illegal free()s while setting MALLOC_CHECK_ */
147
b = RANDOM(&ld, p.bins);
149
int offset = (RANDOM(&ld, 11) - 5)*8;
150
char *rogue = (char*)(p.m[b].ptr) + offset;
151
/*printf("p=%p rogue=%p\n", p.m[b].ptr, rogue);*/
158
for(b=0; b<p.bins; b++) bin_free(&p.m[b]);
165
pthread_mutex_lock(&finish_mutex);
167
pthread_mutex_unlock(&finish_mutex);
168
pthread_cond_signal(&finish_cond);
179
my_start_thread(struct thread_st *st)
182
pthread_create(&st->id, NULL, malloc_test, st);
185
st->sp = malloc(STACKSIZE);
186
if(!st->sp) return -1;
187
thr_create(st->sp, STACKSIZE, malloc_test, st, THR_NEW_LWP, &st->id);
190
st->sp = malloc(STACKSIZE);
191
if(!st->sp) return -1;
192
st->id = sprocsp(malloc_test, PR_SALL, st, st->sp+STACKSIZE, STACKSIZE);
196
#else /* NO_THREADS */
203
int n_total=0, n_total_max=N_TOTAL, n_running;
206
my_end_thread(struct thread_st *st)
208
/* Thread st has finished. Start a new one. */
210
printf("Thread %lx terminated.\n", (long)st->id);
212
if(n_total >= n_total_max) {
214
} else if(st->seed++, my_start_thread(st)) {
215
printf("Creating thread #%d failed.\n", n_total);
218
if(n_total%N_TOTAL_PRINT == 0)
219
printf("n_total = %d\n", n_total);
225
main(int argc, char *argv[])
230
unsigned long size=SIZE;
231
struct thread_st *st;
233
#if USE_MALLOC && !defined(MALLOC_HOOKS) && !defined(__GLIBC__)
236
if(argc > 1) n_total_max = atoi(argv[1]);
237
if(n_total_max < 1) n_thr = 1;
238
if(argc > 2) n_thr = atoi(argv[2]);
239
if(n_thr < 1) n_thr = 1;
240
if(n_thr > 100) n_thr = 100;
241
if(argc > 3) i_max = atoi(argv[3]);
243
if(argc > 4) size = atol(argv[4]);
244
if(size < 2) size = 2;
246
bins = MEMORY/(size*n_thr);
247
if(argc > 5) bins = atoi(argv[5]);
248
if(bins < 4) bins = 4;
251
printf("Using posix threads.\n");
252
pthread_cond_init(&finish_cond, NULL);
253
pthread_mutex_init(&finish_mutex, NULL);
255
printf("Using Solaris threads.\n");
257
printf("Using sproc() threads.\n");
259
printf("No threads.\n");
261
printf("total=%d threads=%d i_max=%d size=%ld bins=%d\n",
262
n_total_max, n_thr, i_max, size, bins);
264
st = (struct thread_st *)malloc(n_thr*sizeof(*st));
267
#if !defined NO_THREADS && defined __sun__
268
/* I know of no other way to achieve proper concurrency with Solaris. */
269
thr_setconcurrency(n_thr);
272
/* Start all n_thr threads. */
273
for(i=0; i<n_thr; i++) {
279
st[i].seed = ((long)i_max*size + i) ^ bins;
280
if(my_start_thread(&st[i])) {
281
printf("Creating thread #%d failed.\n", i);
285
printf("Created thread %lx.\n", (long)st[i].id);
288
for(n_running=n_total=n_thr; n_running>0;) {
289
#if USE_SPROC || USE_THR
293
/* Wait for subthreads to finish. */
295
pthread_mutex_lock(&finish_mutex);
296
pthread_cond_wait(&finish_cond, &finish_mutex);
297
for(i=0; i<n_thr; i++) if(st[i].flags) {
298
pthread_join(st[i].id, NULL);
300
my_end_thread(&st[i]);
302
pthread_mutex_unlock(&finish_mutex);
304
thr_join(0, &id, NULL);
305
for(i=0; i<n_thr; i++)
307
my_end_thread(&st[i]);
315
if(WIFSIGNALED(status))
316
printf("thread %id terminated by signal %d\n",
317
id, WTERMSIG(status));
319
printf("thread %id exited with status %d\n",
320
id, WEXITSTATUS(status));
322
for(i=0; i<n_thr; i++)
324
my_end_thread(&st[i]);
328
#else /* NO_THREADS */
329
for(i=0; i<n_thr; i++)
330
my_end_thread(&st[i]);
334
for(i=0; i<n_thr; i++) {