📄 t-test1.c
字号:
/* * $Id:t-test1.c $ * by Wolfram Gloger 1996-1999 * A multi-thread test for malloc performance, maintaining one pool of * allocated bins per thread. */#include "thread-m.h"#if USE_PTHREADS /* Posix threads */#include <pthread.h>pthread_cond_t finish_cond = PTHREAD_COND_INITIALIZER;pthread_mutex_t finish_mutex = PTHREAD_MUTEX_INITIALIZER;#endif#if (defined __STDC__ && __STDC__) || defined __cplusplus# include <stdlib.h>#endif#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/wait.h>#if !USE_MALLOC#include <malloc.h>#else#include "ptmalloc.h"#endif#include "lran2.h"#include "t-test.h"#define N_TOTAL 10#ifndef N_THREADS#define N_THREADS 2#endif#ifndef N_TOTAL_PRINT#define N_TOTAL_PRINT 50#endif#define STACKSIZE 32768#ifndef MEMORY#define MEMORY 8000000l#endif#define SIZE 10000#define I_MAX 10000#define ACTIONS_MAX 30#define RANDOM(d,s) (lran2(d) % (s))struct bin_info { struct bin *m; unsigned long size, bins;};#if TEST > 0voidbin_test(struct bin_info *p){ int b; for(b=0; b<p->bins; b++) { if(mem_check(p->m[b].ptr, p->m[b].size)) { printf("memory corrupt!\n"); exit(1); } }}#endifstruct thread_st { int bins, max, flags; unsigned long size; thread_id id; char *sp; long seed;};#if USE_PTHREADS || USE_THR || defined NO_THREADSvoid *malloc_test(void *ptr)#elsevoidmalloc_test(void *ptr, size_t stack_len)#endif{ struct thread_st *st = ptr; int b, i, j, actions, pid = 1; struct bin_info p; struct lran2_st ld; /* data for random number generator */ lran2_init(&ld, st->seed);#ifdef TEST_FORK if(RANDOM(&ld, TEST_FORK) == 0) { int status; printf("forking\n"); pid = fork(); if(pid > 0) { printf("waiting for %d...\n", pid); waitpid(pid, &status, 0); if(!WIFEXITED(status)) { printf("child term with signal %d\n", WTERMSIG(status)); } goto end; } }#endif p.m = (struct bin *)malloc(st->bins*sizeof(*p.m)); p.bins = st->bins; p.size = st->size; for(b=0; b<p.bins; b++) { p.m[b].size = 0; p.m[b].ptr = NULL; if(RANDOM(&ld, 2) == 0) bin_alloc(&p.m[b], RANDOM(&ld, p.size) + 1, lran2(&ld)); } for(i=0; i<=st->max;) {#if TEST > 1 bin_test(&p);#endif actions = RANDOM(&ld, ACTIONS_MAX);#if USE_MALLOC && MALLOC_DEBUG if(actions < 2) { mallinfo(); }#endif for(j=0; j<actions; j++) { b = RANDOM(&ld, p.bins); bin_free(&p.m[b]); } i += actions; actions = RANDOM(&ld, ACTIONS_MAX); for(j=0; j<actions; j++) { b = RANDOM(&ld, p.bins); bin_alloc(&p.m[b], RANDOM(&ld, p.size) + 1, lran2(&ld));#if TEST > 2 bin_test(&p);#endif }#if 0 /* Test illegal free()s while setting MALLOC_CHECK_ */ for(j=0; j<8; j++) { b = RANDOM(&ld, p.bins); if(p.m[b].ptr) { int offset = (RANDOM(&ld, 11) - 5)*8; char *rogue = (char*)(p.m[b].ptr) + offset; /*printf("p=%p rogue=%p\n", p.m[b].ptr, rogue);*/ free(rogue); } }#endif i += actions; } for(b=0; b<p.bins; b++) bin_free(&p.m[b]); free(p.m);#ifdef TEST_FORKend:#endif#if USE_PTHREADS if(pid > 0) { pthread_mutex_lock(&finish_mutex); st->flags = 1; pthread_mutex_unlock(&finish_mutex); pthread_cond_signal(&finish_cond); } return NULL;#elif USE_SPROC return;#else return NULL;#endif}intmy_start_thread(struct thread_st *st){#if USE_PTHREADS pthread_create(&st->id, NULL, malloc_test, st);#elif USE_THR if(!st->sp) st->sp = malloc(STACKSIZE); if(!st->sp) return -1; thr_create(st->sp, STACKSIZE, malloc_test, st, THR_NEW_LWP, &st->id);#elif USE_SPROC if(!st->sp) st->sp = malloc(STACKSIZE); if(!st->sp) return -1; st->id = sprocsp(malloc_test, PR_SALL, st, st->sp+STACKSIZE, STACKSIZE); if(st->id < 0) { return -1; }#else /* NO_THREADS */ st->id = 1; malloc_test(st);#endif return 0;}int n_total=0, n_total_max=N_TOTAL, n_running;intmy_end_thread(struct thread_st *st){ /* Thread st has finished. Start a new one. */#if 0 printf("Thread %lx terminated.\n", (long)st->id);#endif if(n_total >= n_total_max) { n_running--; } else if(st->seed++, my_start_thread(st)) { printf("Creating thread #%d failed.\n", n_total); } else { n_total++; if(n_total%N_TOTAL_PRINT == 0) printf("n_total = %d\n", n_total); } return 0;}intmain(int argc, char *argv[]){ int i, bins; int n_thr=N_THREADS; int i_max=I_MAX; unsigned long size=SIZE; struct thread_st *st;#if USE_MALLOC && !defined(MALLOC_HOOKS) && !defined(__GLIBC__) ptmalloc_init();#endif if(argc > 1) n_total_max = atoi(argv[1]); if(n_total_max < 1) n_thr = 1; if(argc > 2) n_thr = atoi(argv[2]); if(n_thr < 1) n_thr = 1; if(n_thr > 100) n_thr = 100; if(argc > 3) i_max = atoi(argv[3]); if(argc > 4) size = atol(argv[4]); if(size < 2) size = 2; bins = MEMORY/(size*n_thr); if(argc > 5) bins = atoi(argv[5]); if(bins < 4) bins = 4;#if USE_PTHREADS printf("Using posix threads.\n"); pthread_cond_init(&finish_cond, NULL); pthread_mutex_init(&finish_mutex, NULL);#elif USE_THR printf("Using Solaris threads.\n");#elif USE_SPROC printf("Using sproc() threads.\n");#else printf("No threads.\n");#endif printf("total=%d threads=%d i_max=%d size=%ld bins=%d\n", n_total_max, n_thr, i_max, size, bins); st = (struct thread_st *)malloc(n_thr*sizeof(*st)); if(!st) exit(-1);#if !defined NO_THREADS && defined __sun__ /* I know of no other way to achieve proper concurrency with Solaris. */ thr_setconcurrency(n_thr);#endif /* Start all n_thr threads. */ for(i=0; i<n_thr; i++) { st[i].bins = bins; st[i].max = i_max; st[i].size = size; st[i].flags = 0; st[i].sp = 0; st[i].seed = ((long)i_max*size + i) ^ bins; if(my_start_thread(&st[i])) { printf("Creating thread #%d failed.\n", i); n_thr = i; break; } printf("Created thread %lx.\n", (long)st[i].id); } for(n_running=n_total=n_thr; n_running>0;) {#if USE_SPROC || USE_THR thread_id id;#endif /* Wait for subthreads to finish. */#if USE_PTHREADS pthread_mutex_lock(&finish_mutex); pthread_cond_wait(&finish_cond, &finish_mutex); for(i=0; i<n_thr; i++) if(st[i].flags) { pthread_join(st[i].id, NULL); st[i].flags = 0; my_end_thread(&st[i]); } pthread_mutex_unlock(&finish_mutex);#elif USE_THR thr_join(0, &id, NULL); for(i=0; i<n_thr; i++) if(id == st[i].id) { my_end_thread(&st[i]); break; }#elif USE_SPROC { int status = 0; id = wait(&status); if(status != 0) { if(WIFSIGNALED(status)) printf("thread %id terminated by signal %d\n", id, WTERMSIG(status)); else printf("thread %id exited with status %d\n", id, WEXITSTATUS(status)); } for(i=0; i<n_thr; i++) if(id == st[i].id) { my_end_thread(&st[i]); break; } }#else /* NO_THREADS */ for(i=0; i<n_thr; i++) my_end_thread(&st[i]); break;#endif } for(i=0; i<n_thr; i++) { if(st[i].sp) free(st[i].sp); } free(st);#if USE_MALLOC malloc_stats();#endif printf("Done.\n"); return 0;}/* * Local variables: * tab-width: 4 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -