os_labs/lab11/main-common.c

140 lines
2.9 KiB
C

vector_t v[2 * MAX_THREADS];
// used to ensure print outs make sense
pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER;
void usage(char *prog) {
fprintf(stderr, "usage: %s [-d (turn on deadlocking behavior)] [-l loops] [-n num_threads] [-t (do timing)] [-v (for verbose)]\n", prog);
exit(1);
}
// only called by one thread (not thread-safe)
void vector_init(vector_t *v, int value) {
int i;
for (i = 0; i < VECTOR_SIZE; i++) {
v->values[i] = value;
}
Pthread_mutex_init(&v->lock, NULL);
}
// only called by one thread (not thread-safe)
void vector_print(vector_t *v, char *str) {
int i;
for (i = 0; i < VECTOR_SIZE; i++) {
printf("%s[%d] %d\n", str, i, v->values[i]);
}
}
void print_info(int call_return, int thread_id, int v0, int v1) {
if (verbose == 0)
return;
Pthread_mutex_lock(&print_lock);
int j;
for (j = 0; j < thread_id; j++) printf(" ");
if (call_return)
printf("<-add(%d, %d)\n", v0, v1);
else
printf("->add(%d, %d)\n", v0, v1);
Pthread_mutex_unlock(&print_lock);
}
typedef struct __thread_arg_t {
int tid;
int vector_add_order;
int vector_0;
int vector_1;
} thread_arg_t;
void *worker(void *arg) {
thread_arg_t *args = (thread_arg_t *) arg;
int i, v0, v1;
for (i = 0; i < loops; i++) {
if (args->vector_add_order == 0) {
v0 = args->vector_0;
v1 = args->vector_1;
} else {
v0 = args->vector_1;
v1 = args->vector_0;
}
print_info(0, args->tid, v0, v1);
vector_add(&v[v0], &v[v1]);
print_info(1, args->tid, v0, v1);
}
return NULL;
}
int main(int argc, char *argv[]) {
opterr = 0;
int c;
while ((c = getopt (argc, argv, "l:n:vtdp")) != -1) {
switch (c) {
case 'l':
loops = atoi(optarg);
break;
case 'n':
num_threads = atoi(optarg);
break;
case 'v':
verbose = 1;
break;
case 't':
do_timing = 1;
break;
case 'd':
cause_deadlock = 1;
break;
case 'p':
enable_parallelism = 1;
break;
default:
usage(argv[0]);
}
}
assert(num_threads < MAX_THREADS);
pthread_t pid[MAX_THREADS];
thread_arg_t args[MAX_THREADS];
int i;
for (i = 0; i < num_threads; i++) {
args[i].tid = i;
if (enable_parallelism == 0) {
args[i].vector_0 = 0;
args[i].vector_1 = 1;
} else {
args[i].vector_0 = i * 2;
args[i].vector_1 = i * 2 + 1;
}
if (cause_deadlock && i % 2 == 1)
args[i].vector_add_order = 1;
else
args[i].vector_add_order = 0;
}
for (i = 0; i < 2 * MAX_THREADS; i++)
vector_init(&v[i], i);
double t1 = Time_GetSeconds();
for (i = 0; i < num_threads; i++)
Pthread_create(&pid[i], NULL, worker, (void *) &args[i]);
for (i = 0; i < num_threads; i++)
Pthread_join(pid[i], NULL);
double t2 = Time_GetSeconds();
fini();
if (do_timing) {
printf("Time: %.2f seconds\n", t2 - t1);
}
//vector_print(&v[0], "v1");
//vector_print(&v[1], "v2");
return 0;
}