You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
6.0 KiB

#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("There will be %d threads.\n",TotalThreadsNum);
continue;
}
if( strcmp(ThisCommand, command[1]) == 0 ) // times
{
scanf("%d",&times);
for(i = 0; i < TotalThreadsNum; i++)
{
args[i][2] = times;
}
printf("Each byte will be tested %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 no.%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 no.%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;
}