367 lines
13 KiB
C
367 lines
13 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <sys/mman.h>
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <ctype.h>
|
|
#include <getopt.h>
|
|
|
|
|
|
struct args_struct{
|
|
int tred;
|
|
int iterations;
|
|
int json;
|
|
size_t words;
|
|
int simulate_errors;
|
|
};
|
|
struct args_struct args;
|
|
#include "cJSON/cJSON.h"
|
|
#include "args_parser.h"
|
|
|
|
|
|
#define DEBUG 0
|
|
#define jemalloc 0
|
|
|
|
#if defined(DEBUG) && DEBUG > 1
|
|
#define DEBUG_PRINT(fmt, args...) fprintf(stderr, "DEBUG: %s:%d:%s(): " fmt, \
|
|
__FILE__, __LINE__, __func__, ##args)
|
|
#elif DEBUG == 1
|
|
#define DEBUG_PRINT(fmt, args...) fprintf(stderr, "DEBUG: %d:%s(): " fmt, \
|
|
__LINE__, __func__, ##args)
|
|
#else
|
|
#define DEBUG_PRINT(fmt, args...) /* Don't do anything in release builds */
|
|
#endif
|
|
|
|
#define BLOCK_SIZE (1024ULL*1024ULL*1024ULL*8)
|
|
|
|
uint32_t test_patterns[] = {0x00000000, 0xFFFFFFFF, 0xAAAAAAAA, 0x55555555};
|
|
|
|
char* test_name[] = {"increment", "ones test", "zeros test"};
|
|
int pretest_delay = 0;
|
|
int test_list[] = {2,3,4};
|
|
#define bool unsigned char
|
|
|
|
|
|
|
|
struct test_info{
|
|
int error;
|
|
int number_addresses;
|
|
};
|
|
struct error_info{
|
|
uint32_t expected;
|
|
uint32_t actual;
|
|
struct error_info* error_info_next;
|
|
};
|
|
struct test_local_stats{
|
|
int error_int;
|
|
struct error_info* error_info;
|
|
struct error_info* error_info_end;
|
|
};
|
|
struct test_stats{
|
|
int len;
|
|
struct test_local_stats* test_local_stats[];
|
|
};
|
|
struct struct_info{
|
|
struct test_info* test_info;
|
|
struct test_stats* test_stats;
|
|
};
|
|
|
|
|
|
struct struct_info info;
|
|
|
|
struct tred_pizdec{
|
|
uint32_t* mem;
|
|
size_t words_stop;
|
|
int id;
|
|
size_t words_start;
|
|
int return_error;
|
|
bool test_tip;
|
|
struct test_stats* test_stats;
|
|
|
|
};
|
|
|
|
#include "multi_tred.h"
|
|
|
|
// Получить доступную память из /proc/meminfo
|
|
unsigned long int get_mem_available_mb() {
|
|
FILE* f = fopen("/proc/meminfo", "r");
|
|
if (!f) return 0;
|
|
char line[256];
|
|
unsigned long int available = 0;
|
|
while (fgets(line, sizeof(line), f)) {
|
|
if (sscanf(line, "MemAvailable: %lu kB", &available) == 1) break;
|
|
}
|
|
fclose(f);
|
|
if (!args.json){
|
|
printf("mem Gb: %lu\n",(available-available/100*10)/1024/1024);
|
|
printf("mem MB: %lu\n",(available-available/100*10)/1024);
|
|
}
|
|
return (available - available/100*20)*1024;
|
|
}
|
|
|
|
|
|
void meseng_proses(int test_tipe, int p){
|
|
if (args.json != 1){
|
|
if (test_tipe == 1){
|
|
printf("\rЗапушен патерн 0x%08X", test_patterns[p]);
|
|
fflush(stdout);
|
|
}
|
|
else{
|
|
printf("\rЗапушен патерн %s", test_name[test_tipe-2]);
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
}
|
|
void meseng_test_and_slip(){
|
|
if (pretest_delay!= 0){
|
|
printf("\rЖду ");
|
|
fflush(stdout);
|
|
usleep(pretest_delay*1000000);
|
|
}
|
|
if (args.json != 1){
|
|
printf("\r-- Проверяю ");
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
|
|
void test_patern(struct tred_pizdec* meta,unsigned long* thread, int tred, int* err, int p, int test_tipe){
|
|
meseng_proses(test_tipe, p);
|
|
for (bool i = 0;(i != tred); i++){// test
|
|
meta[i].id = p;
|
|
meta[i].test_tip = test_tipe;
|
|
DEBUG_PRINT("words_stop: %zu\n",meta[i].words_stop);
|
|
DEBUG_PRINT("words_start:%zu\n",meta[i].words_start);
|
|
pthread_create(&thread[i], NULL, fill_pattern_multi_tred, (void*)&meta[i]);
|
|
//pthread_join(thread[i], NULL);
|
|
}
|
|
for (bool i = 0;(i != tred); i++) //sink tred
|
|
pthread_join(thread[i], NULL);
|
|
//fill_pattern(mem, words, test_patterns[p]);
|
|
meseng_test_and_slip();
|
|
//int err = check_pattern(mem, words, test_patterns[p]);
|
|
for (bool i = 0;(i != tred); i++){// test
|
|
pthread_create(&thread[i], NULL, check_pattern_multi_tred, (void*)&meta[i]);
|
|
//pthread_join(thread[i], NULL);
|
|
}
|
|
for (bool i = 0;(i != tred); i++){ //sink tred
|
|
pthread_join(thread[i], NULL);
|
|
*err += meta[i].return_error;
|
|
}
|
|
if (!args.json){
|
|
if (*err == 0){
|
|
printf("\rOK\n");
|
|
fflush(stdout);
|
|
}
|
|
else printf("Errors: %d\n", *err);
|
|
}
|
|
}
|
|
|
|
void json_local_create(cJSON *error_info_array, struct error_info* error_info){
|
|
cJSON *error_local_info_array = cJSON_CreateObject();
|
|
{
|
|
char* char_dynamic = malloc(32);
|
|
sprintf(char_dynamic, "%p",(void*)&error_info->actual);
|
|
DEBUG_PRINT("%s\n", char_dynamic);
|
|
DEBUG_PRINT("0x%08X\n", error_info->actual);
|
|
cJSON *error_adres = cJSON_CreateString(char_dynamic);
|
|
cJSON_AddItemToObject(error_local_info_array, "error_adres", error_adres);
|
|
}{
|
|
char* char_dynamic = malloc(11);
|
|
sprintf(char_dynamic, "0x%08X",error_info->expected);
|
|
cJSON *expected = cJSON_CreateString(char_dynamic);
|
|
cJSON_AddItemToObject(error_local_info_array, "expected", expected);
|
|
}{
|
|
char* char_dynamic = malloc(11);
|
|
sprintf(char_dynamic, "0x%08X",error_info->actual);
|
|
cJSON *actual = cJSON_CreateString(char_dynamic);
|
|
cJSON_AddItemToObject(error_local_info_array, "actual", actual);
|
|
}
|
|
cJSON_AddItemToArray(error_info_array, error_local_info_array);
|
|
}
|
|
|
|
void json_sum_job(struct tred_pizdec* meta, cJSON *test_ob, char* char_dynamic, int i, unsigned int *error_int){
|
|
if (i < 4)
|
|
sprintf(char_dynamic, "0x%08X",test_patterns[i]);
|
|
else{
|
|
//sprintf(char_dynamic, "%s",test_name[i-4]);
|
|
//free(char_dynamic);
|
|
char_dynamic = test_name[i-4];
|
|
}
|
|
cJSON *error_ob = cJSON_CreateObject();
|
|
cJSON *error_info_array = cJSON_CreateArray();
|
|
unsigned int error_int_local=0;
|
|
for (int t=0; t != args.tred; t++){
|
|
struct error_info* error_info_A = meta[t].test_stats->test_local_stats[i]->error_info;
|
|
error_int_local += meta[t].test_stats->test_local_stats[i]->error_int;
|
|
while(NULL != error_info_A){
|
|
//for(){};
|
|
//p += meta[t].return_error;
|
|
json_local_create(error_info_array, error_info_A);
|
|
error_info_A = error_info_A->error_info_next;
|
|
}
|
|
}
|
|
*error_int += error_int_local;
|
|
cJSON *error_int_j = cJSON_CreateNumber(error_int_local);
|
|
cJSON_AddItemToObject(error_ob, "error", error_int_j);
|
|
cJSON_AddItemToObject(error_ob, "error_info", error_info_array);
|
|
cJSON_AddItemToObject(test_ob, char_dynamic, error_ob);
|
|
}
|
|
void json_create(struct tred_pizdec* meta){
|
|
cJSON *main_ob = cJSON_CreateObject();
|
|
cJSON *test_ob = cJSON_CreateObject();
|
|
cJSON_AddItemToObject(main_ob, "test", test_ob);
|
|
//char* char_dynamic = malloc(11);
|
|
char* char_dynamic = malloc(16);
|
|
unsigned int error_int=0;
|
|
for (int i = 0;i != sizeof(test_patterns)/sizeof(test_patterns[0])+ sizeof(test_name)/sizeof(test_name[0]); ++i){
|
|
json_sum_job(meta, test_ob, char_dynamic, i, &error_int);
|
|
}
|
|
free(char_dynamic);
|
|
cJSON *test_info_ob = cJSON_CreateObject();
|
|
cJSON_AddItemToObject(main_ob, "test_infoAAA", test_info_ob);
|
|
cJSON *error_int_j = cJSON_CreateNumber(error_int);
|
|
cJSON_AddItemToObject(test_info_ob, "error", error_int_j);
|
|
cJSON *message_str;
|
|
if (error_int)
|
|
message_str = cJSON_CreateString("Тест пройден неудачно!");
|
|
else
|
|
message_str = cJSON_CreateString("Тест пройден успешно!");
|
|
cJSON_AddItemToObject(test_info_ob, "message", message_str);
|
|
cJSON *number_addresses_int = cJSON_CreateNumber(args.words);
|
|
cJSON_AddItemToObject(test_info_ob, "number_addresses", number_addresses_int);
|
|
cJSON *mod_test_str = cJSON_CreateString("user_mod");
|
|
cJSON_AddItemToObject(test_info_ob, "mod_test", mod_test_str);
|
|
char *string = cJSON_Print(main_ob);
|
|
printf("%s", string);
|
|
}
|
|
|
|
|
|
void mem_meta_create(struct tred_pizdec* meta, uint32_t *mem, int i){
|
|
//meta = malloc(sizeof(struct tred_pizdec));
|
|
meta->test_stats = malloc(sizeof(struct test_stats) +
|
|
(sizeof(test_list)/sizeof(test_list[0]) + sizeof(test_patterns)/sizeof(test_patterns[0])) * sizeof(struct test_local_stats*)
|
|
);
|
|
meta->test_stats->len = (sizeof(test_list)/sizeof(test_list[0]) + sizeof(test_patterns)/sizeof(test_patterns[0]));
|
|
//meta->test_stats = malloc(meta[i]->test_stats->len);
|
|
for (int m=0;m != meta->test_stats->len;m++){
|
|
meta->test_stats->test_local_stats[m] = malloc(sizeof(struct test_local_stats));
|
|
meta->test_stats->test_local_stats[m]->error_int = 0;
|
|
meta->test_stats->test_local_stats[m]->error_info = NULL;
|
|
//meta->test_stats->test_local_stats[m]->
|
|
}
|
|
meta->mem = mem;
|
|
meta->words_stop = args.words/args.tred*(i+1);
|
|
meta->words_start = i * args.words/args.tred;
|
|
meta->return_error = 0;
|
|
DEBUG_PRINT("words_stop: %zu\n",meta->words_stop);
|
|
DEBUG_PRINT("words_start:%zu\n",meta->words_start);
|
|
}
|
|
|
|
int main(int argc, char *argv[]){
|
|
if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
|
|
perror("mlockall ошибка!\nВозможно недостаточно прав!\n");
|
|
return 1;
|
|
}
|
|
|
|
args.tred = 1;
|
|
args.iterations = 1;
|
|
args.json = 0;
|
|
args.simulate_errors = 0;
|
|
|
|
aaa(&argc, argv, &pretest_delay);
|
|
|
|
if (!args.json)
|
|
printf("threads: %d\n", args.tred);
|
|
|
|
unsigned long int mem_size = get_mem_available_mb();
|
|
size_t words = mem_size / sizeof(uint32_t);
|
|
args.words = words;
|
|
uint32_t *mem = malloc(mem_size);
|
|
if (!mem) {
|
|
printf("Память не выделена!");
|
|
return 1;
|
|
}
|
|
if (args.tred < 1){
|
|
if (!args.json) printf("Количество потоков изменено на 1");
|
|
args.tred = 1;
|
|
}
|
|
//struct tred_pizdec* meta[];
|
|
//pthread_t thread[];
|
|
int err = 0, iterations = args.iterations;
|
|
struct tred_pizdec* meta = malloc(sizeof(struct tred_pizdec) * args.tred);
|
|
pthread_t *thread = malloc(sizeof(pthread_t) * args.tred);
|
|
if (!args.json)
|
|
printf("iterations: %i\n", iterations);
|
|
if (args.tred > 1){
|
|
for (bool i = 0;(i != args.tred); i++)
|
|
mem_meta_create(&meta[i], mem, i);
|
|
DEBUG_PRINT("Выделена память!\n");
|
|
}
|
|
for (;iterations != 0; iterations--){
|
|
if (args.tred > 1){
|
|
for (size_t p = 0; p < sizeof(test_patterns)/sizeof(test_patterns[0]); ++p){
|
|
test_patern(meta, thread, args.tred, &err, p, 1);// Основные паттерны 0x00000000, 0xFFFFFFFF, 0xAAAAAAAA, 0x55555555
|
|
}
|
|
for (int test_list_id = 0; test_list_id < sizeof(test_list)/sizeof(test_list[0]); ++test_list_id){
|
|
test_patern(meta, thread, args.tred, &err, 0, test_list[test_list_id]);
|
|
}
|
|
}
|
|
else{
|
|
mem_meta_create(meta, mem, 0);
|
|
meta->test_tip = 1;
|
|
// Основные паттерны 0x00000000, 0xFFFFFFFF, 0xAAAAAAAA, 0x55555555
|
|
for (size_t p = 0; p < sizeof(test_patterns)/sizeof(test_patterns[0]); ++p){
|
|
//struct tred_pizdec meta = malloc(sizeof(struct tred_pizdec));
|
|
meta->id = p;
|
|
meseng_proses(meta->test_tip, meta->id);
|
|
fill_pattern_multi_tred((void*)meta);
|
|
//fill_pattern(mem, words, test_patterns[p]);
|
|
meseng_test_and_slip();
|
|
check_pattern_multi_tred((void*)meta);
|
|
err += meta->return_error;
|
|
//err += check_pattern(mem, words, test_patterns[p]);
|
|
if (!args.json){
|
|
if (!err){
|
|
printf("\rOK\n");
|
|
fflush(stdout);
|
|
}
|
|
else printf("\nErrors: %d\n", err);
|
|
}
|
|
}
|
|
for (int test_list_id = 0; test_list_id < sizeof(test_list)/sizeof(test_list[0]); ++test_list_id){
|
|
meta->test_tip = test_list[test_list_id];
|
|
meseng_proses(meta->test_tip, meta->id);
|
|
fill_pattern_multi_tred((void*)meta);
|
|
meseng_test_and_slip();
|
|
check_pattern_multi_tred((void*)meta);
|
|
if (!args.json){
|
|
if(!meta->return_error){
|
|
printf("\rOK\n");
|
|
fflush(stdout);
|
|
}
|
|
else printf("Errors: %d\n", meta->return_error);
|
|
}
|
|
err += meta->return_error;
|
|
if (!args.json){
|
|
if (!err){
|
|
printf("\rOK");
|
|
fflush(stdout);
|
|
}
|
|
else printf("\nErrors: %d\n", err);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(mem);
|
|
if (args.json)
|
|
json_create(meta);
|
|
free(meta);
|
|
//if(args.json)
|
|
//for (bool i = 0;(args.tred != -1 || i != args.tred); i++)
|
|
// free(meta[i]);
|
|
return 0;
|
|
}
|