#include #include #include #include #include //#define SMALL_TEST #define T 8 #ifdef SMALL_TEST #define N 9 #else #define N 20 #endif #ifdef SMALL_TEST //unsigned int seznam[] = {7,4,3,6,5,2,8,9,1}; unsigned int seznam[] = {2,3,4,1,5,6,7,9,8}; #else unsigned int seznam[N]; #endif typedef enum { false = 0, true = 1 } status_t; typedef struct{ int threadID; int idxStart; int iBlockSize; } thread_args_t; pthread_t nit[T]; pthread_barrier_t barrier; thread_args_t args[T]; void* funkcija_niti(void* args); pthread_mutex_t kljucavnica = PTHREAD_MUTEX_INITIALIZER; status_t globalno_sortirano = true; void* ((*pFunkcijaNiti)(void*)) = funkcija_niti; unsigned int *pSeznam = &seznam[0]; time_t seconds; /* timespec is a struct defined in ctime as * struct timespec { * time_t tv_sec; // seconds * long tv_nsec; // nanoseconds * }; */ struct timespec timeStart, timeEnd; status_t primerjaj_in_zamenjaj(unsigned int* a, unsigned int* b){ unsigned int temp; status_t sorted = true; if (*b < *a) { temp = *a; *a = *b; *b = temp; sorted = false; } return sorted; } status_t sodi_prehod(int iEnd, unsigned int* pSeznam, int threadID){ status_t sorted = true; int iStart= (threadID*(N/T))%2; for (int i = iStart; i < iEnd; i=i+2){ sorted = sorted & primerjaj_in_zamenjaj(&pSeznam[i], &pSeznam[i+1]); } return sorted; } status_t lihi_prehod(int iEnd, unsigned int* pSeznam, int threadID){ int iStart= (threadID*(N/T))%2; status_t sorted = true; for (int i = 1-iStart; i < iEnd; i=i+2){ sorted = sorted & primerjaj_in_zamenjaj(&pSeznam[i], &pSeznam[i+1]); } return sorted; } void izpisi_seznam(unsigned int *pSeznam){ for (int i = 0; i < N; i++) { printf("%d ", *(pSeznam+i)); } printf("\n"); } int main(){ #ifndef SMALL_TEST // init random generatorja: srand((unsigned) time(&seconds)); //init seznama: for(int i = 0; i < N; i++){ seznam[i] = rand() % (100); } #endif izpisi_seznam(pSeznam); pthread_barrier_init(&barrier, NULL, T); clock_gettime(CLOCK_REALTIME, &timeStart); for(int i = 0; i < T; i++){ args[i].threadID = i; args[i].idxStart = i * (N/T); if (i < T-1) args[i].iBlockSize = N/T; // če je nit od 0... T-2 else args[i].iBlockSize = (N/T) + (N%T) - 1; // če je zadnja nit (T-1) pthread_create( &nit[i], NULL, pFunkcijaNiti, (void *) &args[i]); } for(int i = 0; i < T; i++){ pthread_join(nit[i], NULL); } clock_gettime(CLOCK_REALTIME, &timeEnd); double elapsed_time = (timeEnd.tv_sec - timeStart.tv_sec) + (timeEnd.tv_nsec - timeStart.tv_nsec) / 1e9; printf("Čas izvajanja: %f sekund \n", elapsed_time); pthread_barrier_destroy(&barrier); izpisi_seznam(pSeznam); return 0; } void* funkcija_niti(void* args){ thread_args_t *argumenti = (thread_args_t*) args; status_t sorted = true; for (int i = 0; i < N; i++) { /*printf("Sodi prehod:. Nit %d, %d \n", argumenti->threadID, *(pSeznam+(argumenti->idxStart)));*/ sorted = true; sorted &= sodi_prehod(argumenti->iBlockSize, pSeznam+(argumenti->idxStart), argumenti->threadID); printf("Sodi. T:%d, i=%d, sorted=%d \n", argumenti->threadID, i, sorted); //printf("Sodi prehod:. Nit %d, i=%d, %d \n", argumenti->threadID, i, globalno_sortirano); pthread_mutex_lock(&kljucavnica); globalno_sortirano = globalno_sortirano & sorted; pthread_mutex_unlock(&kljucavnica); pthread_barrier_wait(&barrier); /*printf("Lihi prehod:. Nit %d, %d \n", argumenti->threadID, *(pSeznam+(argumenti->idxStart)));*/ sorted = true; sorted &= lihi_prehod(argumenti->iBlockSize, pSeznam+(argumenti->idxStart), argumenti->threadID); printf("Lihi. T:%d, i=%d, sorted=%d \n", argumenti->threadID, i, sorted); pthread_mutex_lock(&kljucavnica); globalno_sortirano = globalno_sortirano & sorted; //printf("Lihi prehod:. Nit %d, i=%d, %d \n", argumenti->threadID, i, globalno_sortirano); pthread_mutex_unlock(&kljucavnica); pthread_barrier_wait(&barrier); if (globalno_sortirano == true) { printf("Break. T:%d,i=%d \n", argumenti->threadID, i); break; } pthread_barrier_wait(&barrier); if (argumenti->threadID == 0){ globalno_sortirano = true; } pthread_barrier_wait(&barrier); } }