/* * Simulation of readers-writers problem. * * Program requires the following command-line arguments: * number of readers * number of writers * number of reads per reader * number of writes per writer * maximum time to delay in readers (milliseconds) * maximum time to delay in writers (milliseconds) * optional seed for generating delays * * Code is designed to allow different implementations of parts involving * synchronization. */ #define _XOPEN_SOURCE 500 /* may be needed to get usleep() in unistd.h */ #define _SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE /* similarly for *rand48_r() */ #include #include #include #include #include void * reader_fcn(void * thread_arg); void * writer_fcn(void * thread_arg); /* global variables for runtime parameters */ int num_readers; int num_writers; int num_reads_per_reader; int num_writes_per_writer; int max_reader_delay; int max_writer_delay; int seed; #include "getint.h" #include "timer.h" #include "test-readers-writers.h" #include "readers-writers.h" /* ---- main program ---- */ int main(int argc, char* argv[]) { char *usage_msg = "parameters:\n" "\treaders\n" "\twriters\n" "\treads_per_reader\n" "\twrites_per_writer\n" "\treader_delay (msec)\n" "\twriter_delay (msec)\n" "\tseed for random delays (optional)\n"; if (argc < 7) { fprintf(stderr, usage_msg); exit(EXIT_FAILURE); } get_positive_int_or_exit(usage_msg, argv[1], &num_readers); get_positive_int_or_exit(usage_msg, argv[2], &num_writers); get_positive_int_or_exit(usage_msg, argv[3], &num_reads_per_reader); get_positive_int_or_exit(usage_msg, argv[4], &num_writes_per_writer); get_positive_int_or_exit(usage_msg, argv[5], &max_reader_delay); get_positive_int_or_exit(usage_msg, argv[6], &max_writer_delay); if (argc > 7) { get_positive_int_or_exit(usage_msg, argv[7], &seed); } /* initialize timer */ init_start_time(); /* initialize for synchronization */ init_synch(); /* set up IDs for threads */ int readerIDs[num_readers]; for (int i = 0; i < num_readers; ++i) readerIDs[i] = i; int writerIDs[num_writers]; for (int i = 0; i < num_writers; ++i) writerIDs[i] = i; /* start threads for readers and writers */ pthread_t readers[num_readers]; for (int i = 0; i < num_readers; ++i) pthread_create(&readers[i], NULL, reader_fcn, (void *) &readerIDs[i]); pthread_t writers[num_writers]; for (int i = 0; i < num_writers; ++i) pthread_create(&writers[i], NULL, writer_fcn, (void *) &writerIDs[i]); /* wait for all threads to complete */ for (int i = 0; i < num_readers; ++i) pthread_join(readers[i], NULL); for (int i = 0; i < num_writers; ++i) pthread_join(writers[i], NULL); /* clean up and exit */ end_synch(); return EXIT_SUCCESS; } /* ---- code to be executed by each reader ---- */ void * reader_fcn(void * thread_arg) { int myID = * (int *) thread_arg; /* use *rand48_r because they're thread-safe and rand() is not */ struct drand48_data rand_local_save; /* unique sequence in each thread */ srand48_r(seed + myID, &rand_local_save); long int rand_out; for (int i = 0; i < num_reads_per_reader; ++i) { lrand48_r(&rand_local_save, &rand_out); int delay = (rand_out % max_reader_delay) + 1; usleep(delay * 1000); printf("at time %ld reader %d ready to read\n", elapsed_time(), myID); simulate_read_with_synch(myID, delay); } pthread_exit((void* ) NULL); } /* ---- code to be executed by each writer ---- */ void * writer_fcn(void * thread_arg) { int myID = * (int *) thread_arg; /* use *rand48_r because they're thread-safe and rand() is not */ struct drand48_data rand_local_save; /* unique sequence in each thread */ srand48_r(seed + myID + num_readers, &rand_local_save); long int rand_out; for (int i = 0; i < num_writes_per_writer; ++i) { lrand48_r(&rand_local_save, &rand_out); int delay = (rand_out % max_writer_delay) + 1; usleep(delay * 1000); printf("at time %ld writer %d ready to write\n", elapsed_time(), myID); simulate_write_with_synch(myID, delay); } pthread_exit((void* ) NULL); } /* ---- simulated read, write ---- */ void simulate_read(const int readerID, const int num_readers, const int delay) { printf("at time %ld reader %d reading\n", elapsed_time(), readerID); usleep(delay * 1000); printf("at time %ld reader %d done reading\n", elapsed_time(), readerID); } void simulate_write(const int writerID, const int delay) { printf("at time %ld writer %d writing\n", elapsed_time(), writerID); usleep(delay * 1000); printf("at time %ld writer %d done writing\n", elapsed_time(), writerID); }