#include #include #define MAX_THREADS 1000 #include typedef struct { int readers; int writer; pthread_cond_t readers_proceed; pthread_cond_t writer_proceed; int pending_writers; pthread_mutex_t read_write_lock; } mylib_rwlock_t; void mylib_rwlock_init (mylib_rwlock_t *l) { l -> readers = l -> writer = l -> pending_writers = 0; pthread_mutex_init(&(l -> read_write_lock), NULL); pthread_cond_init(&(l -> readers_proceed), NULL); pthread_cond_init(&(l -> writer_proceed), NULL); } void mylib_rwlock_rlock(mylib_rwlock_t *l) { /* if there is a write lock or pending writers, perform condition wait.. else increment count of readers and grant read lock */ pthread_mutex_lock(&(l -> read_write_lock)); while ((l -> pending_writers > 0) || (l -> writer > 0)) pthread_cond_wait(&(l -> readers_proceed), &(l -> read_write_lock)); l -> readers ++; pthread_mutex_unlock(&(l -> read_write_lock)); } void mylib_rwlock_wlock(mylib_rwlock_t *l) { /* if there are readers or writers, increment pending writers count and wait. On being woken, decrement pending writers count and increment writer count */ pthread_mutex_lock(&(l -> read_write_lock)); while ((l -> writer > 0) || (l -> readers > 0)) { l -> pending_writers ++; pthread_cond_wait(&(l -> writer_proceed), &(l -> read_write_lock)); } l -> pending_writers --; l -> writer ++; pthread_mutex_unlock(&(l -> read_write_lock)); } void mylib_rwlock_unlock(mylib_rwlock_t *l) { /* if there is a write lock then unlock else if there are read locks, decrement count of read locks. If the count is 0 and there is a pending writer, let him through, else if there are pending readers, let them all go through */ pthread_mutex_lock(&(l -> read_write_lock)); if (l -> writer > 0) l -> writer = 0; else if (l -> readers > 0) l -> readers --; pthread_mutex_unlock(&(l -> read_write_lock)); if ((l -> readers == 0) && (l -> pending_writers > 0)) pthread_cond_signal(&(l -> writer_proceed)); else if (l -> readers > 0) pthread_cond_broadcast(&(l -> readers_proceed)); } int list[10000]; void *rw_test(void *s); pthread_t p_threads[MAX_THREADS]; pthread_attr_t attr; mylib_rwlock_t rwl; int min, elements_per_thread; pthread_mutex_t min_lock; main() { int i, hits[MAX_THREADS]; double start, end; struct timeval tz; struct timezone tx; FILE *fp; min = 99999999; elements_per_thread = 10000 / MAX_THREADS; /* fp = fopen("random_list", "r"); */ pthread_mutex_init(&min_lock, NULL); pthread_attr_init (&attr); pthread_attr_setscope (&attr,PTHREAD_SCOPE_SYSTEM); mylib_rwlock_init (&rwl); for (i = 0; i < 10000; i++) list[i] = rand()*rand(); /* fscanf(fp, "%d", &list[i]); */ gettimeofday(&tz, &tx); start = (double)tz.tv_sec + (double) tz.tv_usec / 1000000.0; for (i = 0; i < MAX_THREADS; i ++) { hits[i] = i; pthread_create(&p_threads[i], &attr, rw_test, (void *) &hits[i]); } for (i = 0; i < MAX_THREADS; i ++) pthread_join(p_threads[i], NULL); gettimeofday(&tz, &tx); end = (double)tz.tv_sec + (double) tz.tv_usec / 1000000.0; printf("%d\n", min); printf("Avg time = %lf sec\n", (end - start)/1000000000.0 ); } void *rw_test (void *start_ptr) { int my_id, i, my_min; my_id = *((int *) start_ptr); my_min = 99999999; for (i = my_id * elements_per_thread; i < (my_id + 1) * elements_per_thread; i++) if (list[i] < my_min) my_min = list[i]; mylib_rwlock_rlock(&rwl); if (my_min < min) { mylib_rwlock_unlock(&rwl); mylib_rwlock_wlock(&rwl); min = my_min; } mylib_rwlock_unlock(&rwl); }