/////////////////////////////////////////////////////////////////////////////// // File : // // main.c // // Date : // // November 2013 // // Author : // // Cesar Fuguet Tortolero // // Description : // // Sort application using the GIET-VM OS. This application uses the // barrier routines to apply a sort algorithm in several stages. // // Considerations : // // - It supports up to 256 processors and the number of processors // must be a power of 2. // // - If there is only one TTY available, this application uses a spin // lock to avoid several threads writting at the same time. // // - This application must be executed on a cache coherent // architecture. Otherwise some modifications must be applied // // - The processors executing this application must have a contiguous // processor id and the first processor must have id 0. // /////////////////////////////////////////////////////////////////////////////// #include "stdio.h" #include "hard_config.h" #include "barrier.h" ////////////////////////////////////////////////////////////////////////// // The NTHREADS constant must be modified depending on the desired number of // threads #define NTHREADS 8 #define ARRAY_LENGTH (NTHREADS * 128) #define IPT (ARRAY_LENGTH / NTHREADS) // ITEMS PER THREAD //////////////////////////////////////////////////////////////////////////////// // Processors other than 0 display algorithm state // The processor 0 always displays some information so this does not affect him #define VERBOSE 1 /////////////////////////////////////////////////////////////////////// // Define printf according to verbosity option and number of available // TTY #if (VERBOSE == 1) # define printf(...) giet_tty_printf(__VA_ARGS__) # define puts(...) giet_tty_puts(__VA_ARGS__) #else // VERBOSE == 0 # define printf(...) # define puts(...) #endif #define task0_printf(...) if(thread_id == 0) giet_tty_printf(__VA_ARGS__) #define exit giet_exit #define procid giet_procid #define rand giet_rand int array0[ARRAY_LENGTH]; int array1[ARRAY_LENGTH]; volatile int init_ok = 0; void bubbleSort( int * array, unsigned int length, unsigned int init_pos); void merge( int * array, int * result, int length, int init_pos_a, int init_pos_b, int init_pos_result); /////////////////////////////////////////////////// // This application support at most 256 processors // Number of barriers = log2(NTHREADS) giet_barrier_t barrier[8]; __attribute__ ((constructor)) void sort() { int thread_id = giet_thread_id(); int * src_array; int * dst_array; int i; printf("[ Thread %d ] Initializing vector and barriers...\n\r", thread_id); /////////////////////////// // Barriers Initialization for (i = 0; i < __builtin_ctz(NTHREADS); i++) { barrier_init(&barrier[i], NTHREADS >> i); } //////////////////////// // Array Initialization for (i = IPT * thread_id; i < IPT * (thread_id + 1); i++) { array0[i] = rand(); } /////////////////////////////////// // Parallel sort of array elements printf("[ Thread %d ] Stage 0: Processor Sorting...\n\r", thread_id); bubbleSort(array0, IPT, IPT * thread_id); printf("[ Thread %d ] Finishing Stage 0\n\r", thread_id); for (i = 0; i < __builtin_ctz(NTHREADS); i++) { asm volatile ("sync"); barrier_wait(&barrier[i]); if((thread_id % (2 << i)) != 0) { printf("[ Thread %d ] Quits\n\r", thread_id); exit(); } printf("[ Thread %d ] Stage %d: Starting...\n\r", thread_id, i+1); if((i % 2) == 0) { src_array = &array0[0]; dst_array = &array1[0]; } else { src_array = &array1[0]; dst_array = &array0[0]; } merge(src_array, dst_array , IPT << i , IPT * thread_id , IPT * (thread_id + (1 << i)) , IPT * thread_id ); printf("[ Thread %d ] Finishing Stage %d\n\r", thread_id, i + 1); } int success; int failure_index; ////////////////////////////// // Verify the resulting array if(thread_id == 0) { success = 1; for(i=0; i<(ARRAY_LENGTH-1); i++) { if(dst_array[i] > dst_array[i+1]) { success = 0; failure_index = i; break; } } if (success) { printf("[ Thread 0 ] Success!!\n\r"); } else { printf("[ Thread 0 ] Failure!! Incorrect element: %d\n\r", failure_index); for(i=0; i array[j + 1]) { aux = array[j + 1]; array[j + 1] = array[j]; array[j] = aux; } } } } void merge( int * array, int * result, int length, int init_pos_a, int init_pos_b, int init_pos_result) { int i; int j; int k; i = 0; j = 0; k = init_pos_result; while((i < length) || (j < length)) { if((i < length) && (j < length)) { if(array[init_pos_a + i] < array[init_pos_b + j]) { result[k++] = array[init_pos_a + i]; i++; } else { result[k++] = array[init_pos_b + j]; j++; } } else if(i < length) { result[k++] = array[init_pos_a + i]; i++; } else { result[k++] = array[init_pos_b + j]; j++; } } } /* vim: tabstop=4 : shiftwidth=4 : expandtab */