#CFLAGS=-O2 -Wall -g -lpthread
CFLAGS= -lpthread
NAME=mbw
TARFILE=${NAME}.tar.gz
mbw: mbw.c
clean:
rm -f mbw
rm -f ${NAME}.tar.gz
${TARFILE}: clean
tar cCzf .. ${NAME}.tar.gz --exclude-vcs ${NAME} || true
rpm: ${TARFILE}
rpmbuild -ta ${NAME}.tar.gz
/*
* Copyright (C) 2008-2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _CUTILS_LIST_H_
#define _CUTILS_LIST_H_
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct listnode
{
struct listnode *next;
struct listnode *prev;
};
#define node_to_item(node, container, member) \
(container *) (((char*) (node)) - offsetof(container, member))
#define list_declare(name) \
struct listnode name = { \
.next = &(name), \
.prev = &(name), \
}
#define list_for_each(node, list) \
for ((node) = (list)->next; (node) != (list); (node) = (node)->next)
#define list_for_each_reverse(node, list) \
for ((node) = (list)->prev; (node) != (list); (node) = (node)->prev)
#define list_for_each_safe(node, n, list) \
for ((node) = (list)->next, (n) = (node)->next; \
(node) != (list); \
(node) = (n), (n) = (node)->next)
static inline void list_init(struct listnode *node)
{
node->next = node;
node->prev = node;
}
static inline void list_add_tail(struct listnode *head, struct listnode *item)
{
item->next = head;
item->prev = head->prev;
head->prev->next = item;
head->prev = item;
}
static inline void list_add_head(struct listnode *head, struct listnode *item)
{
item->next = head->next;
item->prev = head;
head->next->prev = item;
head->next = item;
}
static inline void list_remove(struct listnode *item)
{
item->next->prev = item->prev;
item->prev->next = item->next;
}
#define list_empty(list) ((list) == (list)->next)
#define list_head(list) ((list)->next)
#define list_tail(list) ((list)->prev)
#ifdef __cplusplus
};
#endif /* __cplusplus */
#endif
/*
* vim: ai ts=4 sts=4 sw=4 cinoptions=>4 expandtab
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include "list.h"
/* how many runs to average by default */
#define DEFAULT_NR_LOOPS 10
/* we have 3 tests at the moment */
#define MAX_TESTS 3
/* default block size for test 2, in bytes */
#define DEFAULT_BLOCK_SIZE 262144
/* test types */
#define TEST_MEMCPY 0
#define TEST_DUMB 1
#define TEST_MCBLOCK 2
/* version number */
#define VERSION "1.4"
/*
* MBW memory bandwidth benchmark
*
* 2006, 2012 Andras.Horvath@gmail.com
* 2013 j.m.slocum@gmail.com
* (Special thanks to Stephen Pasich)
*
* http://github.com/raas/mbw
*
* compile with:
* gcc -O -o mbw mbw.c
*
* run with eg.:
*
* ./mbw 300
*
* or './mbw -h' for help
*
* watch out for swap usage (or turn off swap)
*/
void usage()
{
printf("mbw memory benchmark v%s, https://github.com/raas/mbw\n", VERSION);
printf("Usage: mbw [options] array_size_in_MiB\n");
printf("Options:\n");
printf(" -n: number of runs per test (0 to run forever)\n");
printf(" -a: Don't display average\n");
printf(" -t%d: memcpy test\n", TEST_MEMCPY);
printf(" -t%d: dumb (b[i]=a[i] style) test\n", TEST_DUMB);
printf(" -t%d: memcpy test with fixed block size\n", TEST_MCBLOCK);
printf(" -b <size>: block size in bytes for -t2 (default: %d)\n", DEFAULT_BLOCK_SIZE);
printf(" -q: quiet (print statistics only)\n");
printf("(will then use two arrays, watch out for swapping)\n");
printf("'Bandwidth' is amount of data copied over the time this operation took.\n");
printf("\nThe default is to run all tests available.\n");
}
/* ------------------------------------------------------ */
/* allocate a test array and fill it with data
* so as to force Linux to _really_ allocate it */
long *make_array(unsigned long long asize)
{
unsigned long long t;
unsigned int long_size=sizeof(long);
long *a;
a=calloc(asize, long_size);
if(NULL==a) {
perror("Error allocating memory");
exit(1);
}
/* make sure both arrays are allocated, fill with pattern */
for(t=0; t<asize; t++) {
a[t]=0xaa;
}
return a;
}
/* actual benchmark */
/* asize: number of type 'long' elements in test arrays
* long_size: sizeof(long) cached
* type: 0=use memcpy, 1=use dumb copy loop (whatever GCC thinks best)
*
* return value: elapsed time in seconds
*/
double worker(unsigned long long asize, long *a, long *b, int type, unsigned long long block_size)
{
unsigned long long t;
struct timeval starttime, endtime;
double te;
unsigned int long_size=sizeof(long);
/* array size in bytes */
unsigned long long array_bytes=asize*long_size;
if(type==TEST_MEMCPY) { /* memcpy test */
/* timer starts */
gettimeofday(&starttime, NULL);
memcpy(b, a, array_bytes);
/* timer stops */
gettimeofday(&endtime, NULL);
} else if(type==TEST_MCBLOCK) { /* memcpy block test */
char* aa = (char*)a;
char* bb = (char*)b;
gettimeofday(&starttime, NULL);
for (t=array_bytes; t >= block_size; t-=block_size, aa+=block_size){
bb=mempcpy(bb, aa, block_size);
}
if(t) {
bb=mempcpy(bb, aa, t);
}
gettimeofday(&endtime, NULL);
} else if(type==TEST_DUMB) { /* dumb test */
gettimeofday(&starttime, NULL);
for(t=0; t<asize; t++) {
b[t]=a[t];
}
gettimeofday(&endtime, NULL);
}
te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
return te;
}
/* ------------------------------------------------------ */
/* pretty print worker's output in human-readable terms */
/* te: elapsed time in seconds
* mt: amount of transferred data in MiB
* type: see 'worker' above
*
* return value: -
*/
void printout(double te, double mt, int type)
{
switch(type) {
case TEST_MEMCPY:
printf("Method: MEMCPY\t");
break;
case TEST_DUMB:
printf("Method: DUMB\t");
break;
case TEST_MCBLOCK:
printf("Method: MCBLOCK\t");
break;
}
printf("Elapsed: %.5f\t", te);
printf("MiB: %.5f\t", mt);
printf("Copy: %.3f MiB/s\n", mt/te);
return;
}
/* ------------------------------------------------------ */
int main1(int argc, char **argv)
{
unsigned int long_size=0;
double te, te_sum; /* time elapsed */
unsigned long long asize=0; /* array size (elements in array) */
int i;
long *a, *b; /* the two arrays to be copied from/to */
int o; /* getopt options */
unsigned long testno;
/* options */
/* how many runs to average? */
int nr_loops=DEFAULT_NR_LOOPS;
/* fixed memcpy block size for -t2 */
unsigned long long block_size=DEFAULT_BLOCK_SIZE;
/* show average, -a */
int showavg=1;
/* what tests to run (-t x) */
int tests[MAX_TESTS];
double mt=0; /* MiBytes transferred == array size in MiB */
int quiet=0; /* suppress extra messages */
tests[0]=0;
tests[1]=0;
tests[2]=0;
while((o=getopt(argc, argv, "haqn:t:b:")) != EOF) {
switch(o) {
case 'h':
usage();
exit(1);
break;
case 'a': /* suppress printing average */
showavg=0;
break;
case 'n': /* no. loops */
nr_loops=strtoul(optarg, (char **)NULL, 10);
break;
case 't': /* test to run */
testno=strtoul(optarg, (char **)NULL, 10);
if(testno>MAX_TESTS-1) {
printf("Error: test number must be between 0 and %d\n", MAX_TESTS-1);
exit(1);
}
tests[testno]=1;
break;
case 'b': /* block size in bytes*/
block_size=strtoull(optarg, (char **)NULL, 10);
if(0>=block_size) {
printf("Error: what block size do you mean?\n");
exit(1);
}
break;
case 'q': /* quiet */
quiet=1;
break;
default:
break;
}
}
/* default is to run all tests if no specific tests were requested */
if( (tests[0]+tests[1]+tests[2]) == 0) {
tests[0]=1;
tests[1]=1;
tests[2]=1;
}
if( nr_loops==0 && ((tests[0]+tests[1]+tests[2]) != 1) ) {
printf("Error: nr_loops can be zero if only one test selected!\n");
exit(1);
}
if(optind<argc) {
mt=strtoul(argv[optind++], (char **)NULL, 10);
} else {
printf("Error: no array size given!\n");
exit(1);
}
if(0>=mt) {
printf("Error: array size wrong!\n");
exit(1);
}
/* ------------------------------------------------------ */
long_size=sizeof(long); /* the size of long on this platform */
asize=1024*1024/long_size*mt; /* how many longs then in one array? */
if(asize*long_size < block_size) {
printf("Error: array size larger than block size (%llu bytes)!\n", block_size);
exit(1);
}
if(!quiet) {
printf("Long uses %d bytes. ", long_size);
printf("Allocating 2*%lld elements = %lld bytes of memory.\n", asize, 2*asize*long_size);
if(tests[2]) {
printf("Using %lld bytes as blocks for memcpy block copy test.\n", block_size);
}
}
a=make_array(asize);
b=make_array(asize);
/* ------------------------------------------------------ */
if(!quiet) {
printf("Getting down to business... Doing %d runs per test.\n", nr_loops);
}
/* run all tests requested, the proper number of times */
for(testno=0; testno<MAX_TESTS; testno++) {
te_sum=0;
if(tests[testno]) {
for (i=0; nr_loops==0 || i<nr_loops; i++) {
te=worker(asize, a, b, testno, block_size);
te_sum+=te;
printf("%d\t", i);
printout(te, mt, testno);
}
if(showavg) {
printf("AVG\t");
printout(te_sum/nr_loops, mt, testno);
}
}
}
free(a);
free(b);
return 0;
}
unsigned long get_a_rand( void )
{
int i;
unsigned long out;
unsigned int rand1,rand2;
int retval;
struct timeval currentv;
retval = gettimeofday( ¤tv, NULL );
if( retval != 0 ){
printf( "get time err\n");
return 1;
}
//printf( "currentv.tv_sec = %d\n", currentv.tv_sec);
//printf( "currentv.tv_sec = %d\n", currentv.tv_usec);
//srand( currentv.tv_usec );
rand1 = rand();
rand2 = rand();
//printf( "rand1 = %x\n", rand1 );
//printf( "rand2 = %x\n", rand2 );
out = (((unsigned long)rand1)<<12) | (rand2 & 0xfff);
//printf( "out = %llx\n", out );
//printf( "sizeof(out) = %llx\n", sizeof(out) );
}
struct mytest_device {
//pthread_mutex_t lock; /* see note below on mutex acquisition order */
struct listnode list_node;
unsigned int value;
};
#define HASH_BITS_20 true
//#define HASH_BITS_22 true
//#define HASH_BITS_24 true
//#define HASH_BITS_26 true
#ifdef HASH_BITS_20
#define ENTRY_NUMS (1024*1024*1)
#define TABLE_LEN (1024*1024*1)
#define INDEX_OFFSET (24)
#define VALUE_MASK (0xffffff)
#elif defined HASH_BITS_22
#define ENTRY_NUMS (1024*1024*4)
#define TABLE_LEN (1024*1024*4)
#define INDEX_OFFSET (22)
#define VALUE_MASK (0x3fffff)
#elif defined HASH_BITS_24
#define ENTRY_NUMS (1024*1024*16)
#define TABLE_LEN (1024*1024*16)
#define INDEX_OFFSET (20)
#define VALUE_MASK (0xfffff)
#elif defined HASH_BITS_26
#define ENTRY_NUMS (1024*1024*64)
#define TABLE_LEN (1024*1024*64)
#define INDEX_OFFSET (18)
#define VALUE_MASK (0x3ffff)
#else
#define ENTRY_NUMS (1024*1024*1)
#define TABLE_LEN (1024*1024*1)
#define INDEX_OFFSET (24)
#define VALUE_MASK (0xffffff)
#endif
void creat_hash_table(unsigned long int *table)
{
unsigned long rand_num;
unsigned int table_index,table_value,clash_cnt;
int i;
struct listnode* list_node;
struct listnode* head_list_node;
struct listnode *node;
struct mytest_device *test_device;
clash_cnt = 0x00;
for( i=0x00; i<ENTRY_NUMS; i++ ){
repeat_creat:
rand_num = get_a_rand();
//rand_num = test_rand[i];
//printf( "rand_num = %11lx\n", rand_num );
table_index = rand_num >> INDEX_OFFSET;
//printf( "table_index = %x\n", table_index );
table_value = rand_num & VALUE_MASK;
//printf( "table_value = %x\n", table_value );
if( table[table_index] == 0x00 ){
test_device = (struct mytest_device*)malloc(sizeof(struct mytest_device));
//list_node = (struct listnode*)malloc(sizeof(struct mytest_device));
list_node = &test_device->list_node;
list_init(list_node);
test_device->value = table_value;
table[table_index] = (unsigned long int)test_device;
//printf("list_node = %p.\n", list_node);
}else{
clash_cnt = clash_cnt + 1;
test_device = (struct mytest_device*)table[table_index];
head_list_node = (struct listnode*)&test_device->list_node;
if( test_device->value == table_value ){
//printf( "hash cyt1\n" );
goto repeat_creat;
}
list_for_each(node,head_list_node){
//printf( "node->value = %x\n", node->value );
test_device = (struct mytest_device *)node_to_item(node, struct mytest_device, list_node);
if( test_device->value == table_value ){
//printf( "hash cyt2\n" );
goto repeat_creat;
}
}
test_device = (struct mytest_device*)malloc(sizeof(struct mytest_device));
list_node = &test_device->list_node;
list_init(list_node);
test_device->value = table_value;
list_add_tail(head_list_node, list_node);
//break;
}
}
//printf( "i = %x\n", i );
}
void destroy_hash_table( unsigned long int *table )
{
int i;
struct listnode *head_list_node;
struct listnode *node, *n;
struct mytest_device *test_device;
int free_cnt;
free_cnt = 0x00;
for( i=0x00; i<ENTRY_NUMS; i++ ){
if( table[i] == 0x00 ){
continue;
}else{
test_device = (struct mytest_device*)table[i];
head_list_node = &test_device->list_node;
list_for_each_safe(node, n, head_list_node){
test_device = (struct mytest_device *)node_to_item(node, struct mytest_device, list_node);
list_remove(node);
if( test_device ){
free(test_device);
free_cnt++;
test_device = NULL;
}
}
table[i] = 0x00;
test_device = (struct mytest_device *)node_to_item(head_list_node, struct mytest_device, list_node);
if( test_device ){
free(test_device);
free_cnt++;
test_device = NULL;
}
}
}
//printf( "free_cnt = %x\n", free_cnt );
free(table);
}
void insert_a_record( unsigned long int *table, unsigned int table_index, unsigned int table_value )
{
struct listnode* list_node;
struct listnode* head_list_node;
struct mytest_device *test_device;
test_device = (struct mytest_device*)table[table_index];
head_list_node = &test_device->list_node;
if( table[table_index] == 0x00 ){
test_device = (struct mytest_device*)malloc(sizeof(struct mytest_device));
list_node = &test_device->list_node;
list_init(list_node);
test_device->value = table_value;
table[table_index] = (unsigned long int)test_device;
}else{
test_device = (struct mytest_device*)malloc(sizeof(struct mytest_device));
list_node = &test_device->list_node;
list_init(list_node);
test_device->value = table_value;
list_add_tail(head_list_node, list_node);
}
}
int g_last_dump_entry = 0x00;
void dump_a_table( unsigned long int *table )
{
int i;
struct listnode* head_list_node;
struct listnode* node;
struct mytest_device *test_device;
for( i=0x00; i<ENTRY_NUMS; i++ ){
if( table[i] == 0x00 ){
continue;
}else{
test_device = (struct mytest_device*)table[i];
printf( "record test_device = 0x%p\n", test_device );
head_list_node = &test_device->list_node;
g_last_dump_entry = i;
printf( "record num = 0x%x\n", i );
printf( "head_list_node->value = %x\n", test_device->value );
list_for_each(node,head_list_node){
test_device = (struct mytest_device *)node_to_item(node, struct mytest_device, list_node);
printf( "node->value = %x\n", test_device->value );
}
printf( "\n");
}
}
}
void dump_a_table_entry( unsigned long int *table, int index )
{
struct listnode* head_list_node;
struct listnode* node;
struct mytest_device *test_device;
if( table[index] == 0x00 ){
printf( "entry is empty\n");
}else{
test_device = (struct mytest_device*)table[index];
head_list_node = &test_device->list_node;
printf( "record num = 0x%x\n", index );
printf( "head_list_node->value = %x\n", test_device->value );
list_for_each(node, head_list_node){
test_device = (struct mytest_device *)node_to_item(node, struct mytest_device, list_node);
printf( "node->value = %x\n", test_device->value );
}
printf( "\n");
}
}
int match_a_entry( unsigned long int *tableA, int table_index, unsigned int table_value, unsigned long int *tableC )
{
struct mytest_device *test_deviceA;
struct mytest_device *test_deviceA_N;
struct listnode *head_list_nodeA;
struct listnode *nodeA;
struct listnode *nodeA_N;
int match;
match = 0x00;
if( tableA[table_index] ){
test_deviceA = (struct mytest_device *)tableA[table_index];
head_list_nodeA = &(test_deviceA->list_node);
if( test_deviceA->value == table_value ){
insert_a_record(tableC, table_index, table_value );
if( list_empty(head_list_nodeA) ){
//printf( "list_empty = %p\n", head_list_nodeA );
tableA[table_index] = 0x00;
if( test_deviceA ){
free(test_deviceA);
test_deviceA = NULL;
}
}else{
test_deviceA = (struct mytest_device *)node_to_item(head_list_nodeA, struct mytest_device, list_node);
//待删除的节点
nodeA_N = head_list_nodeA->next;
test_deviceA_N = (struct mytest_device *)node_to_item(nodeA_N, struct mytest_device, list_node);
tableA[table_index] = (unsigned long int)test_deviceA_N;
//printf("ready to rm a node: %p\n", test_deviceA );
//printf("test_deviceA value: 0x%x\n", test_deviceA->value );
//dump_a_table_entry( tableA, table_index);
list_remove(head_list_nodeA);
if( test_deviceA ){
free(test_deviceA);
test_deviceA = NULL;
}
}
match = 0x01;
return match;
}
list_for_each(nodeA,head_list_nodeA){
test_deviceA = (struct mytest_device *)node_to_item(nodeA, struct mytest_device, list_node);
if( test_deviceA->value == table_value ){
//printf( "table_index = %x\n", table_index );
//printf( "node->value = %x\n", node->value );
//printf("\n");
insert_a_record(tableC, table_index, table_value );
list_remove(nodeA);
if( test_deviceA ){
free(test_deviceA);
test_deviceA = NULL;
}
match = 0x02;
break;
}
}
}
return match;
}
int main_test( void *arg )
{
unsigned long int *tableA;
unsigned long int *tableB;
unsigned long int *tableC;
unsigned int table_index,table_value;
int i;
struct listnode* head_list_nodeB;
struct listnode *nodeB;
struct mytest_device *test_deviceB;
int match;
struct timeval starttime, endtime;
double te;
gettimeofday(&starttime, NULL);
srand( (unsigned int)time(NULL) );
tableA = malloc(TABLE_LEN*8);
if( tableA == NULL ){
printf("malloc failed!!!\n");
return 1;
}
memset( tableA, 0x00, TABLE_LEN*8 );
creat_hash_table(tableA);
//创建hash表A
tableB = malloc(TABLE_LEN*8);
if( tableB == NULL ){
printf("malloc failed!!!\n");
return 1;
}
memset( tableB, 0x00, TABLE_LEN*8 );
creat_hash_table(tableB);
//创建hash表B
tableC = malloc(TABLE_LEN*8);
//printf("table = %p.\n", table);
if( tableC == NULL ){
printf("malloc failed!!!\n");
return 1;
}
memset( tableC, 0x00, TABLE_LEN*8 );
//创建hash表C 存储A与B的交集
gettimeofday(&endtime, NULL);
te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
printf( "pid = %d, Elapsed creat rand: %.5f\n", getpid(), te );
gettimeofday(&starttime, NULL);
//B n A = C
//A表中的匹配项被删除,B表中的匹配项没有删除
//所有匹配记录存储于C表中
for( table_index=0x00; table_index<TABLE_LEN; table_index++ ){
if( tableB[table_index] == 0x00 ){
continue;
}else{
test_deviceB = (struct mytest_device*)tableB[table_index];
head_list_nodeB = &test_deviceB->list_node;
table_value = test_deviceB->value;
if( list_empty(head_list_nodeB) ){
match = match_a_entry( tableA, table_index, table_value, tableC );
continue;
}else{
match = match_a_entry( tableA, table_index, table_value, tableC );
if( match ){
continue;
}
list_for_each(nodeB, head_list_nodeB){
test_deviceB = (struct mytest_device *)node_to_item(nodeB, struct mytest_device, list_node);
table_value = test_deviceB->value;
match = match_a_entry( tableA, table_index, table_value, tableC );
if( match ){
break;
}
}
}
}
}
gettimeofday(&endtime, NULL);
te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
printf( "pid = %d, Elapsed calc over: %.5f\n", getpid(), te );
gettimeofday(&starttime, NULL);
//printf("dump table 3:\n");
//g_last_dump_entry = 0x00;
//dump_a_table(tableC);
#if 0
for( i=0x00; i<1024*1024; i++ ){
if(tableC[i]==0x00){
continue;
}
//printf("dump table 1:\n");
//dump_a_table_entry( tableA, i);
}
#endif
destroy_hash_table(tableA);
destroy_hash_table(tableB);
destroy_hash_table(tableC);
gettimeofday(&endtime, NULL);
te=((double)(endtime.tv_sec*1000000-starttime.tv_sec*1000000+endtime.tv_usec-starttime.tv_usec))/1000000;
printf( "pid = %d, del rand: %.5f\n", getpid(), te );
}
unsigned long test_rand[32] = {
0x0112233,
0x1112244,
0x2112255,
0x2112266,
0x2112277,
0x2112288,
0x2112299,
0x2112256,
};
void test_creat_hash_table(unsigned long int *table)
{
unsigned long rand_num;
unsigned int table_index,table_value,clash_cnt;
int i;
struct listnode* list_node;
struct listnode* head_list_node;
struct listnode *node;
struct mytest_device *test_device;
clash_cnt = 0x00;
for( i=0x00; i<8; i++ ){
repeat_creat:
//rand_num = get_a_rand();
rand_num = test_rand[i];
//printf( "rand_num = %11lx\n", rand_num );
table_index = rand_num >> 24;
//printf( "table_index = %x\n", table_index );
table_value = rand_num & 0xffffff;
//printf( "table_value = %x\n", table_value );
if( table[table_index] == 0x00 ){
test_device = (struct mytest_device*)malloc(sizeof(struct mytest_device));
//list_node = (struct listnode*)malloc(sizeof(struct mytest_device));
list_node = &test_device->list_node;
list_init(list_node);
test_device->value = table_value;
table[table_index] = (unsigned long int)test_device;
//printf("list_node = %p.\n", list_node);
}else{
clash_cnt = clash_cnt + 1;
test_device = (struct mytest_device*)table[table_index];
head_list_node = (struct listnode*)&test_device->list_node;
if( test_device->value == table_value ){
//printf( "hash cyt1\n" );
goto repeat_creat;
}
list_for_each(node,head_list_node){
//printf( "node->value = %x\n", node->value );
test_device = (struct mytest_device *)node_to_item(node, struct mytest_device, list_node);
if( test_device->value == table_value ){
//printf( "hash cyt2\n" );
goto repeat_creat;
}
}
test_device = (struct mytest_device*)malloc(sizeof(struct mytest_device));
list_node = &test_device->list_node;
list_init(list_node);
test_device->value = table_value;
list_add_tail(head_list_node, list_node);
//break;
}
}
//printf( "i = %x\n", i );
}
typedef int (* func_pointer)(void *arg);
int do_create_thread(func_pointer thread_func, void *arg)
{
int Threaderr, ret;
pthread_attr_t attr;
pthread_t tmp_thread_id;
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
Threaderr = pthread_create( &tmp_thread_id, NULL, (void *(*)(void *))thread_func, arg );
ret = pthread_detach( tmp_thread_id );
if( Threaderr != 0 ){
printf("pthread_create error.\n");
}
return tmp_thread_id;
//当线程为joinable时,使用pthread_join来获取线程返回值,并释放资源
//当线程为非joinable时,也可在线程中调用 pthread_detach(pthread_self())来分离自己
}
void print_exit(void )
{
printf("tuichu!!!\n");
}
int thread_test( void *arg )
{
//在线程里面fork比较容易受控制
pid_t pid;
pid = fork();
if( pid == 0 ){
main_test(0);
}
}
int main( int argc, char **argv )
{
int i;
unsigned long int *tableA;
int arg[8];
for( i=0x00; i<8; i++ ){
do_create_thread(thread_test, &arg[i]);
}
printf("1main exit!!!\n");
while(1){
sleep(1);
}
}
//scp -r xxx@192.168.0.107:/home/xxx/mbw/* ./