#include "pthread.h" /* * memtest.c * simple memory test * Copyright (C) 2008 All rights reserved. * */ void memoryTest(void * arg) { int *loc = (int *)arg; int start_p = *loc; int end_p = *(loc + 1); int times = *(loc + 2); int *totalCorrect_p = loc + 3; // 主线程中记录测试成功的内存单元总个数的变量的指针 int *totalTimes_p = loc + 4; // 主线程中记录测试内存单元总个数的变量的指针 char FailFlag = '0'; // 本次测试是否通过的标志,字符‘0’表示通过,‘1’表示测试没有通过 char random = rand(); char testData[5] = {0x00, 0xFF, 0x55, 0xAA, random}; // 用于测试的五数据,最后一个是没有被初始化的随机数random没有初始化 char *i = (char *)start_p; int j = 0; int k = 0; for( ; i <= (char *)end_p; i++) { for(j = 0; j < times; j++) { if(*(loc + 5) == 1) pthread_exit(0); for(k = 0; k < 5; k++) // 五种数据都通过才算是通过测试 { if(*(loc + 5) == 1) // 如果主线程发了终止线程信号,要立刻终止该线程 pthread_exit(0); *i = testData[k]; if(*i != testData[k]) { FailFlag = '1'; break; } } if(FailFlag == '1')// times次测试中有一次不成功就算是没有通过测试 break; } if(*(loc + 5) == 1) // 如果主线程发了终止线程信号,要立刻终止该线程 pthread_exit(0); if(FailFlag == '0') // 通过时候测试通过的内存单元个数加一 (*totalCorrect_p)++; (*totalTimes_p)++; // 完成的测试内存单元数要加一 FailFlag = '0';// 标志复位 } pthread_exit(0); // 线程安全退出 } int main() { char *command[6] = {"thread", "times", "go", "status", "abort", "exit"};// 所有的命令 char *ThisCommand; int TotalThreadsNum = 0; // 线程总数 int times = 0; // 测试的次数 pthread_t threads[64] = {0}; // 设置最大64个线程足够使用 int addrSize = 0; // 每个线程有五个参数需要知道: // 开始测试地址,结束地址,每个地址测试次数,测试正常的内存单元个数,测试内存单元的总个数、主线程是否发出了终止线程的信号 // 把第一个参数地址传递过去,其他的四个通过地址增加来共享主线程的数据,从而得到参数或者对参数内容进行读写 int args[64][6] = {{0}}; int i = 0; int value = 0; // 等待线程结束的返回之存放在这个变量中 char *testAddr = (char *)malloc(0x000FFFFF); // 申请1MB内存用于测试 while(1) { printf(">>>>"); fflush(stdout); scanf("%s",ThisCommand); if( strcmp(ThisCommand, command[0]) == 0 ) // thread number { scanf("%d",&TotalThreadsNum); // 读到thread number后设置每个线程需要的开始和结束地址的参数 // 创建number个线程 addrSize = 0x000FFFFF / TotalThreadsNum; args[0][0] = (int)testAddr; args[0][1] = args[0][0] + addrSize - 1; for(i = 1; i < TotalThreadsNum - 1; i++) { args[i][0] = args[i - 1][1] + 1; args[i][1] = addrSize + args[i][0] - 1; } args[i][0] = args[i - 1][1] + 1; args[i][1] = (int)testAddr + 0x000FFFFF - 1; // 测试结束的地址 printf("Will use %d threads.\n",TotalThreadsNum); continue; } if( strcmp(ThisCommand, command[1]) == 0 ) // times { scanf("%d",×); for(i = 0; i < TotalThreadsNum; i++) { args[i][2] = times; } printf("Each byte will be tested by %d times.\n",times); continue; } if( strcmp(ThisCommand, command[2]) == 0 ) // go { for(i = 0; i < TotalThreadsNum; i++) // 创建线程 pthread_create(&threads[i], NULL, (void *)memoryTest, (void *)args[i]); continue; } if( strcmp(ThisCommand, command[3]) == 0 ) // status { for(i = 0; i < TotalThreadsNum; i++) { // 为了简化操作,如果本次已经测试的总内存单元数(放在args[i][4])等于分配的总个数或者线程状态被设置为'1' // 即可以简单的认为表示本线程已经结束 if( args[i][4] == args[i][1] - args[i][0] + 1 || args[i][5] == 1 ) printf("Thread %d has exited.(%p-%p, %d/%d/%d)\n", i, args[i][0], args[i][1], args[i][3], args[i][4], args[i][1] - args[i][0] + 1); else printf("Thread %d is running.(%p-%p, %d/%d/%d)\n", i, args[i][0], args[i][1], args[i][3], args[i][4], args[i][1] - args[i][0] + 1); } continue; } if( strcmp(ThisCommand, command[4]) == 0 ) // abort { // 线程终止状态设置为'1',表示线程被人为退出 for(i = 0; i < TotalThreadsNum; i++) args[i][5] = 1; continue; } if( strcmp(ThisCommand, command[5]) == 0 ) // exit { for(i = 0; i < TotalThreadsNum; i++) // 给每个线程的标志为设置为1,让其退出 { args[i][5] = 1; // 线程终止状态设置为'1',表示线程被人为退出 } // 标志为设置为1之后要等待每个线程真正的结束,主线程才能退出,否则主线程释放内存 // 线程再执行的时候会出现严重的错误 for(i = 0; i < TotalThreadsNum; i++) { pthread_join(threads[i], (void *)value); } return 0; } } return 0; }