hs-krispy/Lab2-Sync

lab2_bst_test.c 설명

Closed this issue · 0 comments

/*
*	Operating System Lab
*	    Lab2 (Synchronization)
*
*   lab2_bst_test.c :
*       - thread-safe bst test code.
*       - coarse-grained, fine-grained lock test code
*
* You can compare single thread result, coarse grained result and fine grained result.
*/

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>

#include "lab2_sync_types.h"

#define LAB2_TYPE_FINEGRAINED       0
#define LAB2_TYPE_COARSEGRAINED     1
#define LAB2_TYPE_SINGLE            2

#define LAB2_OPTYPE_INSERT          0
#define LAB2_OPTYPE_DELETE          1

void lab2_sync_usage(char *cmd) // 입력 형식에 대한 설명
{
    printf("\n Usage for %s : \n",cmd);
    printf("    -t: num thread, must be bigger than 0 ( e.g. 4 )\n");
    printf("    -c: test node count, must be bigger than 0 ( e.g. 10000000 ) \n");
}

void lab2_sync_example(char *cmd) // 입력 형식
{
    printf("\n Example : \n");
    printf("    #sudo %s -t 4 -c 10000000 \n", cmd);
    printf("    #sudo %s -t 4 -c 10000000 \n", cmd);
}

static void print_result(lab2_tree *tree, int num_threads, int node_count, int is_sync, int op_type, double time){
    char *cond[] = {"fine-grained BST  ", "coarse-grained BST", "single thread BST"};
    char *op[] = {"insert","delete"};
    int result_count = 0;


    printf("=====  Multi thread %s  %s experiment  =====\n",cond[is_sync],op[op_type]);
    printf("\n Experiment info \n");
    printf("    test node           : %d \n", node_count);
    printf("    test threads        : %d \n", num_threads);
    printf("    execution time      : %lf seconds \n\n", time);

    printf("\n BST inorder iteration result : \n");
    result_count = lab2_node_print_inorder(tree);
    printf("    total node count    : %d \n\n", node_count);

}

void* thread_job_delete(void *arg){

    thread_arg *th_arg = (thread_arg *)arg;
    lab2_tree *tree = th_arg->tree;
    int is_sync = th_arg->is_sync;
    int *data_set = th_arg->data_set; // 삭제할 데이터의 정보를 저장
    int start = th_arg->start, end = th_arg->end;
    int i;
    for(i = start; i < end; i++ ){
        if(is_sync == LAB2_TYPE_FINEGRAINED)
            lab2_node_remove_fg(tree, data_set[i]);
        else if(is_sync == LAB2_TYPE_COARSEGRAINED)
            lab2_node_remove_cg(tree, data_set[i]);
    }
}

void* thread_job_insert(void *arg){

    thread_arg *th_arg = (thread_arg *)arg; // 인자로 받아온 구조체 정보를 넣어줌
    lab2_tree *tree = th_arg->tree; // 루트 노드 설정
    int is_sync = th_arg->is_sync;
    int *data = th_arg->data_set;
    int start = th_arg->start, end = th_arg->end;
    int i;

    for (i = start; i < end; i++) {
        lab2_node* node = lab2_node_create(data[i]); // 노드 개수만큼 노드 생성
        if(is_sync == LAB2_TYPE_FINEGRAINED)
            lab2_node_insert_fg(tree, node);
        else if(is_sync == LAB2_TYPE_COARSEGRAINED)
            lab2_node_insert_cg(tree, node);
    }
}

void bst_test(int num_threads, int node_count){

    lab2_tree *tree;
    lab2_node *node;
    struct timeval tv_insert_start, tv_insert_end, tv_delete_start, tv_delete_end, tv_start, tv_end;
    // timeval 구조체 변수 선언
    /*
     * struct timeval
        {
            long tv_sec;       // 초
            long tv_usec;      // 마이크로초
        }
    */
    int errors, i = 0, count = 0;
    int root_data = 40;
    int term = node_count / num_threads, is_sync;
    double exe_time = 0.0;
    thread_arg *threads; // 쓰레드 구조체 배열 생성
    int *data = (int*)malloc(sizeof(int)*node_count);

    srand(time(NULL));
    for (i=0; i < node_count; i++) { // 노드의 data에 랜덤값을 넣어줌
        data[i] = rand();
    }

    if (!(threads = (thread_arg*)malloc(sizeof(thread_arg) * num_threads)))
        abort(); // 프로그램을 비정상 종료시킴

    /*
     * single thread insert test.
     */
    gettimeofday(&tv_start, NULL); // 시작 시간
    printf("\n");
    tree = lab2_tree_create(); // 루트 노드 생성
    for (i=0 ; i < node_count ; i++) {
        lab2_node* node = lab2_node_create(data[i]); // 노드 생성
        lab2_node_insert(tree, node); //루트 노드에 새 노드 연결(트리에 노드 삽입)
    }

    gettimeofday(&tv_end, NULL); // 종료 시간
    exe_time = get_timeval(&tv_start, &tv_end); // 종료 시간 - 시작 시간
    print_result(tree, num_threads, node_count, LAB2_TYPE_SINGLE, LAB2_OPTYPE_INSERT, exe_time);
    lab2_tree_delete(tree);

    /*
     * multi therad insert test coarse-grained
     */
    is_sync = LAB2_TYPE_COARSEGRAINED;
    tree = lab2_tree_create();

    gettimeofday(&tv_insert_start, NULL);
    for(i=0; i < num_threads ; i++){
        thread_arg *th_arg = &threads[i]; // 쓰레드 구조체 배열
        th_arg->tree = tree;
        th_arg->is_sync = is_sync;
        th_arg->data_set = data;
        th_arg->start = i*term;
        th_arg->end = (i+1)*term;

        pthread_create(&threads[i].thread, NULL, thread_job_insert, (void*)th_arg); // 쓰레드 개수만큼 생성
    }

    for (i = 0; i < num_threads; i++)
        pthread_join(threads[i].thread, NULL); // 해당 쓰레드가 끝날때 까지 대기

    gettimeofday(&tv_insert_end, NULL);
    exe_time = get_timeval(&tv_insert_start, &tv_insert_end);
    print_result(tree,num_threads, node_count, is_sync, LAB2_OPTYPE_INSERT, exe_time);
    lab2_tree_delete(tree);

    /*
     *  multi thread insert test fine-grained \
     */
    is_sync = LAB2_TYPE_FINEGRAINED;
    tree = lab2_tree_create();

    gettimeofday(&tv_insert_start, NULL);
    for(i=0; i < num_threads ; i++){
        thread_arg *th_arg = &threads[i];
        th_arg->tree = tree;
        th_arg->is_sync = is_sync;
        th_arg->data_set = data;
        th_arg->start = i*term;
        th_arg->end = (i+1)*term;

        pthread_create(&threads[i].thread,NULL,thread_job_insert,(void*)th_arg);
    }

    for (i = 0; i < num_threads; i++)
        pthread_join(threads[i].thread, NULL);

    gettimeofday(&tv_insert_end, NULL);
    exe_time = get_timeval(&tv_insert_start, &tv_insert_end);
    print_result(tree,num_threads, node_count, is_sync, LAB2_OPTYPE_INSERT,exe_time);
    lab2_tree_delete(tree);

    /*
     * single thread delete test
     */

    tree = lab2_tree_create();
    for (i=0 ; i < node_count ; i++) {
        lab2_node* node = lab2_node_create(data[i]);
        lab2_node_insert(tree, node);
    }

    gettimeofday(&tv_start, NULL);
    for(i=0 ; i < node_count ; i++){
        lab2_node_remove(tree,data[i]);
    }

    gettimeofday(&tv_end, NULL);
    exe_time = get_timeval(&tv_start, &tv_end);
    print_result(tree, num_threads, node_count, LAB2_TYPE_SINGLE, LAB2_OPTYPE_DELETE,exe_time);
    lab2_tree_delete(tree);

    /*
     * multi thread delete test coarse-grained
     */
    is_sync = LAB2_TYPE_COARSEGRAINED;
    tree = lab2_tree_create();

    for (i=0; i < node_count; i++) {
        node = lab2_node_create(data[i]);
        if(is_sync == LAB2_TYPE_FINEGRAINED)
            lab2_node_insert_fg(tree,node);
        else if(is_sync == LAB2_TYPE_COARSEGRAINED)
            lab2_node_insert_cg(tree,node);
    }

    gettimeofday(&tv_delete_start, NULL);
    for(i=0 ; i < num_threads ; i++){
        thread_arg *th_arg = &threads[i];
        th_arg->tree = tree;
        th_arg->is_sync = is_sync;
        th_arg->data_set = data;
        th_arg->start = i*term;
        th_arg->end = (i+1)*term;

        pthread_create(&threads[i].thread,NULL,thread_job_delete,(void*)th_arg);
    }

    for (i = 0; i < num_threads; i++)
        pthread_join(threads[i].thread, NULL);
    gettimeofday(&tv_delete_end, NULL);
    exe_time = get_timeval(&tv_delete_start, &tv_delete_end);

    print_result(tree,num_threads, node_count, is_sync,LAB2_OPTYPE_DELETE,exe_time);
    lab2_tree_delete(tree);

    /*
     * multi thread delete test fine-grained
     */
    is_sync = LAB2_TYPE_FINEGRAINED;
    tree = lab2_tree_create();
    for (i=0; i < node_count; i++) {
        node = lab2_node_create(data[i]);
        if(is_sync == LAB2_TYPE_FINEGRAINED)
            lab2_node_insert_fg(tree,node);
        else if(is_sync == LAB2_TYPE_COARSEGRAINED)
            lab2_node_insert_cg(tree,node);
    }

    gettimeofday(&tv_delete_start, NULL);
    for(i=0 ; i < num_threads ; i++){
        thread_arg *th_arg = &threads[i];
        th_arg->tree = tree;
        th_arg->is_sync = is_sync;
        th_arg->data_set = data;
        th_arg->start = i*term;
        th_arg->end = (i+1)*term;

        pthread_create(&threads[i].thread,NULL,thread_job_delete,(void*)th_arg);
    }

    for (i = 0; i < num_threads; i++)
        pthread_join(threads[i].thread, NULL);

    gettimeofday(&tv_delete_end, NULL);
    exe_time = get_timeval(&tv_delete_start, &tv_delete_end);

    print_result(tree ,num_threads, node_count, is_sync, LAB2_OPTYPE_DELETE,exe_time);
    lab2_tree_delete(tree);

    printf("\n");

    free(threads);
    free(data);
}

int main(int argc, char *argv[])
{
    char op;
    int num_threads=0, node_count=0;
    int fd;

    optind = 0;

    while ((op = getopt(argc, argv, "t:c:")) != -1) { // "t: 동시에 수행 할 thread의 개수, c: 노드의 개수"
        switch (op) {
            case 't':
                num_threads = atoi(optarg); // 문자열로 저장된 옵션값을 정수로 변환
                break;
            case 'c':
                node_count = atoi(optarg);
                break;
            default:
                goto INVALID_ARGS;
        }
    }
    if((num_threads > 0) && (node_count > 0)){
        bst_test(num_threads, node_count);
    }else{
        goto INVALID_ARGS;
    }

    return LAB2_SUCCESS; // 0 성공 리턴 (헤더에 정의)
    INVALID_ARGS:
    lab2_sync_usage(argv[0]); // 인자로 실행 파일명을 넘겨줌
    lab2_sync_example(argv[0]); // 인자로 실행 파일명을 넘겨줌

    return LAB2_ERROR; // -1 에러 리턴
}