/*------------------------------------------------------------*/ #define _REENTRANT #define SIZE 1000 #define SCOUNT 7 #define ROWS 10 #define STEPS 22 #define AVAILABLE 0 #define FILLING 1 #define SORTABLE 2 #define SORTING 3 #include #include #include static int data[ROWS][SIZE]; static int available; static int sortable; static int scoreboard[ROWS]; static int run; static pthread_mutex_t scorelock; static pthread_cond_t pcanwork; static pthread_cond_t sorterworkavail; /* Function prototypes */ static void *producer(); static void *sorter(); void sort(int); /*------------------------------------------------------------*/ int main(int argc, char* argv[]) { pthread_t producer_id; pthread_t sorter_id[SCOUNT]; pthread_attr_t attr; int i; available = ROWS; sortable = 0; run = 1; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); pthread_mutex_init(&scorelock, NULL); pthread_cond_init(&pcanwork, NULL); pthread_cond_init(&sorterworkavail, NULL); for (i=0; i < ROWS; i++) { scoreboard[i] = AVAILABLE; } if(argc == 1) /* No concurrency */ pthread_create(&producer_id, NULL, producer, NULL); else pthread_create(&producer_id, &attr, producer, NULL); for(i = 0; i < SCOUNT; i++) { if(argc == 1) pthread_create(&sorter_id[i], NULL, sorter, NULL); else pthread_create(&sorter_id[i], &attr, sorter, NULL); } printf("main> All threads running\n"); pthread_join(producer_id, NULL); for(i = 0; i < SCOUNT; i++) { pthread_cond_broadcast(&sorterworkavail); } for(i = 0; i < SCOUNT; i++) { pthread_join(sorter_id[i], NULL); } printf("Normal Termination\n"); return 0; } /*------------------------------------------------------------*/ static void *producer() { int pcount; int target; int i; for(pcount = 0; pcount < STEPS; pcount++) { pthread_mutex_lock(&scorelock); while(available == 0) { pthread_cond_wait(&pcanwork, &scorelock); } target = -1; for(i=0; i< ROWS; i++) { if(scoreboard[i] == AVAILABLE) { target = i; available = available - 1; break; } } pthread_mutex_unlock(&scorelock); if(target == -1) { printf("Producer cannot find available!\n"); pthread_exit(NULL); } printf("p> Filling row %d\n", target); for(i=0; i < SIZE; i++) { data[target][i] = rand(); } printf("p> Row %d complete\n", target); pthread_mutex_lock(&scorelock); scoreboard[target] = SORTABLE; sortable = sortable + 1; /* pthread_cond_broadcast(&sorterworkavail); */ pthread_mutex_unlock(&scorelock); pthread_cond_broadcast(&sorterworkavail); } run = 0; return NULL; /* pthread_exit(NULL); */ } /*------------------------------------------------------------*/ static void *sorter() { int i; int target; pthread_t me; me = pthread_self(); while(1) { pthread_mutex_lock(&scorelock); while(sortable == 0 && run) { pthread_cond_wait(&sorterworkavail, &scorelock); } if(!run && available == ROWS) { pthread_mutex_unlock(&scorelock); pthread_exit(NULL); } target = -1; for(i = 0; i < ROWS; i++) { if(scoreboard[i] == SORTABLE) { target = i; sortable = sortable - 1; scoreboard[target] = SORTING; break; } } if(target == -1) { pthread_mutex_unlock(&scorelock); pthread_exit(NULL); } pthread_mutex_unlock(&scorelock); printf("S> %x starting...\n", me); sort(target); printf("S>%x finishing min = %d max = %d\n", me, data[target][0], data[target][SIZE-1]); pthread_mutex_lock(&scorelock); scoreboard[target] = AVAILABLE; available = available + 1; /* pthread_cond_broadcast(&pcanwork); */ pthread_mutex_unlock(&scorelock); pthread_cond_broadcast(&pcanwork); } } void sort(int target) { int outer; int inner; int temp; outer = SIZE - 1; for(outer = SIZE - 1; outer > 0; outer--) { for(inner=0; inner < outer; inner++) { if(data[target][inner] > data[target][inner+1]) { temp = data[target][inner]; data[target][inner] = data[target][inner+1]; data[target][inner+1] = temp; } } } }