00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <pthread.h>
00021 #include <limits.h>
00022 #include <sys/time.h>
00023 #include <sys/syscall.h>
00024 #include <unistd.h>
00025 #include <errno.h>
00026 #include <string.h>
00027 #include "vsidevice.h"
00028
00029 char *NomeDisco;
00030 unsigned long long int TamanhoDisco;
00031 unsigned int TamanhoBloco;
00032 unsigned int NumeroBlocos;
00033 unsigned int NumLeituras;
00034 unsigned int MaxMicroSegundos;
00035 CvsiDevice Disco;
00036
00037 void *FuncaoThread( void * Param )
00038 {
00039 int erro;
00040 unsigned int i;
00041 unsigned int Bloco;
00042 unsigned int TempoEspera;
00043 unsigned long long int PosicaoDisco;
00044 double TempoInicial;
00045 double TempoFinal;
00046 CvsiDevice DiscoThread;
00047 struct timeval inicio;
00048 struct timeval fim;
00049 char *BufferLeitura;
00050 pthread_t ThreadId;
00051
00052
00053 ThreadId = pthread_self();
00054 printf("Thread %lu (pid=%lu): iniciada. \n", ThreadId, syscall(SYS_gettid) );
00055 TempoEspera = random() % MaxMicroSegundos;
00056 printf("Thread %lu: esperando %u ms. \n", ThreadId, TempoEspera);
00057 usleep(TempoEspera * 1000);
00058 printf("Thread %lu: iniciando a leitura. \n", ThreadId);
00059
00060 BufferLeitura = new char[ TamanhoBloco ];
00061
00062 if( BufferLeitura == NULL )
00063 {
00064 printf("Thread %lu: erro ao criar o buffer com %u bytes. \n", ThreadId,
00065 TamanhoBloco );
00066 pthread_exit( NULL );
00067 }
00068
00069
00070 erro = DiscoThread.OpenDeviceAgain(NomeDisco, TamanhoDisco);
00071 if( erro != 0 )
00072 {
00073 printf( "Thread %lu: erro ao abrir o dispositivo %s. \n", ThreadId,
00074 NomeDisco );
00075 pthread_exit( NULL );
00076 }
00077 else
00078 printf( "Thread %lu: dispositivo %s aberto com sucesso. \n", ThreadId,
00079 NomeDisco);
00080
00081 for( i = 0; i < NumLeituras; i++ )
00082 {
00083
00084 Bloco = random() % NumeroBlocos;
00085 PosicaoDisco = Bloco * TamanhoBloco;
00086 gettimeofday( &inicio, NULL );
00087 erro = DiscoThread.Read( PosicaoDisco, TamanhoBloco, BufferLeitura );
00088 gettimeofday( &fim, NULL );
00089 if( erro != 0 )
00090 {
00091 printf( "Thread %lu: erro ao ler o bloco %u (com %u bytes) do dispositivo %s. ",
00092 ThreadId, Bloco, TamanhoBloco, NomeDisco);
00093 printf( "Posicao no disco %llu. Tipo do erro gerado %d. ",
00094 PosicaoDisco, erro);
00095 printf( "Erro do sistema %u (%s).\n", errno, strerror( errno ) );
00096 fflush( stdout );
00097 }
00098 else
00099 {
00100 TempoInicial = ( ( double ) inicio.tv_sec ) * 1000.0 +
00101 ( ( double ) inicio.tv_usec / 1000.0);
00102 TempoFinal = ( ( double ) fim.tv_sec ) * 1000.0 +
00103 ( ( double ) fim.tv_usec / 1000.0);
00104 if( TempoFinal-TempoInicial > 1000 )
00105 {
00106 printf( "*************************************************\n" );
00107 printf( "Thread %lu: bloco %u (com %u bytes) do dispositivo %s lido em %4.6f ms. \n",
00108 ThreadId, Bloco, TamanhoBloco, NomeDisco,
00109 TempoFinal-TempoInicial );
00110 printf( "*************************************************\n" );
00111 }
00112 else
00113 printf( "Thread %lu: bloco %u (com %u bytes) do dispositivo %s lido em %4.6f ms. \n",
00114 ThreadId, Bloco, TamanhoBloco, NomeDisco,
00115 TempoFinal-TempoInicial );
00116 }
00117 }
00118
00119 delete[] BufferLeitura;
00120 DiscoThread.Close();
00121 printf( "Thread %lu: terminada. \n", ThreadId );
00122 pthread_exit( NULL );
00123 }
00124
00125 int main( int argc, char *argv[] )
00126 {
00127 int erro;
00128 unsigned int i;
00129 unsigned int NumeroThreads;
00130 pthread_attr_t ThreadAttr;
00131 pthread_t *ThreadId;
00132 CvsiDevice Disco;
00133 struct timeval atual;
00134
00135 gettimeofday( &atual, NULL );
00136 srandom(atual.tv_sec);
00137
00138 if( argc < 6 )
00139 {
00140 printf( "Sintaxe: %s [dispositivo] [tambloco] [numthreads] [numleituras] [maxmicrosegundos]\n",
00141 argv[ 0 ] );
00142 return -1;
00143 }
00144
00145 NomeDisco = argv[ 1 ];
00146 TamanhoBloco = atoi(argv[ 2 ]);
00147 NumeroThreads = atoi(argv[ 3 ]);
00148 NumLeituras = atoi(argv[ 4 ]);
00149 MaxMicroSegundos = atoi(argv[ 5 ]);
00150
00151
00152 erro = Disco.Open( NomeDisco );
00153 if( erro != 0 )
00154 {
00155 printf( "main: erro ao abrir o dispositivo %s.\n", NomeDisco );
00156 return erro;
00157 }
00158
00159
00160 TamanhoDisco = Disco.Size();
00161 if( TamanhoDisco % TamanhoBloco != 0 )
00162 {
00163 printf( "main: o tamanho do bloco %u nao divide o tamanho do disco %llu.\n",
00164 TamanhoBloco, TamanhoDisco);
00165 Disco.Close();
00166 return -2;
00167 }
00168
00169 NumeroBlocos = (unsigned int) (TamanhoDisco /
00170 (unsigned long long int) TamanhoBloco);
00171
00172 ThreadId = new pthread_t [NumeroThreads];
00173 if( ThreadId == NULL )
00174 {
00175 printf( "main: erro ao alocar o vetor com as ids de threads com %u ids/\n",
00176 NumeroThreads);
00177 Disco.Close();
00178 return -3;
00179 }
00180
00181 pthread_attr_init( &ThreadAttr );
00182 pthread_attr_setstacksize( &ThreadAttr, 2 * PTHREAD_STACK_MIN );
00183
00184 for( i = 0; i < NumeroThreads; i++ )
00185 {
00186 erro = pthread_create( &ThreadId[ i ], &ThreadAttr, FuncaoThread,
00187 NULL );
00188 if( erro != 0 )
00189 printf("main: aviso - erro ao criar uma das threads.\n");
00190 else
00191 printf("main: thread %lu criada com sucesso.\n", ThreadId[i]);
00192 }
00193
00194 for( i = 0; i < NumeroThreads; i++ )
00195 pthread_join( ThreadId[ i ], NULL );
00196
00197 Disco.Close();
00198 delete[] ThreadId;
00199 return 0;
00200 }