int main(int argc, char *argv[]) { int retcode; use_timeout = (argc >= 2 && strcmp(argv[1], "-t") == 0); if (is_help_requested(argc, argv)) { usage(argv[0], ""); } timeout.tv_sec = (time_t) 200; timeout.tv_nsec = (long) 0; if (use_timeout && argc >= 3) { int t; sscanf(argv[2], "%d", &t); timeout.tv_sec = (time_t) t; } printf("timout(%ld sec %ld msec)\n", (long) timeout.tv_sec, (long) timeout.tv_nsec); pthread_t thread[N_THREADS]; int tidx[N_THREADS]; for (size_t i = 0; i < N_THREADS; i++) { tidx[i] = (int) i; retcode = pthread_create(thread + i, NULL, run, (void *) (tidx + i)); // equivalent: ((void *) tidx) + sizeof(int)*i handle_thread_error(retcode, "creating thread failed", PROCESS_EXIT); } printf("in parent: setting up\n"); pthread_mutex_init(&mutex, NULL); sleep(2); printf("in parent: getting mutex\n"); if (use_timeout) { while (TRUE) { retcode = pthread_mutex_timedlock(&mutex, &timeout); if (retcode == 0) { break; } else if (retcode == ETIMEDOUT) { printf("timed out in parent\n"); } else { handle_thread_error(retcode, "parent failed (timed)lock", PROCESS_EXIT); } } } else { retcode = pthread_mutex_lock(&mutex); handle_thread_error(retcode, "parent failed lock", PROCESS_EXIT); } printf("parent got mutex\n"); sleep(5); printf("parent releases mutex\n"); pthread_mutex_unlock(&mutex); printf("parent released mutex\n"); printf("parent waiting for child to terminate\n"); for (size_t i = 0; i < N_THREADS; i++) { retcode = pthread_join(thread[i], NULL); handle_thread_error(retcode, "join failed", PROCESS_EXIT); printf("joined thread %d\n", (int) i); } pthread_mutex_destroy(&mutex); printf("done\n"); exit(0); }
int main(int argc, char **argv) { int retcode; if (argc == 2 && strcmp(argv[1], "--help") == 0) { usage(NULL, argv[0]); } if (argc < 3) { usage("not enough arguments", argv[0]); } buffer_size = atoi(argv[1]); if (buffer_size <= 0) { usage("buffersize must be > 0", argv[0]); } int nfds = argc-2; // printf("nfds=%d\n", nfds); retcode = pthread_barrier_init(&start_barrier, NULL, nfds); handle_thread_error(retcode, "pthread_barrier_init", PROCESS_EXIT); for (int i = 0; i < nfds; i++) { char *name = argv[2+i]; // printf("creating thread for pipe name=%s\n", name); pthread_t thread; retcode = pthread_create(&thread, NULL, handle_pipe, name); handle_thread_error(retcode, "pthread_create", PROCESS_EXIT); } /* let the child threads do the work */ // printf("exiting main thread\n"); pthread_exit(NULL); exit(0); }
void *run(void *arg) { int *argi = (int *) arg; int my_tidx = *argi; int retcode; printf("in child %d: sleeping\n", my_tidx); sleep(2); if (use_timeout) { while (TRUE) { retcode = pthread_mutex_timedlock(&mutex, &timeout); if (retcode == 0) { break; } else if (retcode == ETIMEDOUT) { printf("timed out in child %d\n", my_tidx); sleep(1); } else { handle_thread_error(retcode, "child failed timed lock", PROCESS_EXIT); } } } else { retcode = pthread_mutex_lock(&mutex); handle_thread_error(retcode, "child failed lock", PROCESS_EXIT); } printf("child %d got mutex\n", my_tidx); char line[1025]; fgets(line, 1024, stdin); printf("[%d]: %s\n", my_tidx, line); sleep(1); printf("child %d releases mutex\n", my_tidx); pthread_mutex_unlock(&mutex); printf("child %d released mutex\n", my_tidx); sleep(10); printf("child %d exiting\n", my_tidx); return NULL; }
/** * Indicate interrest for the first element of a list */ void useFirstElement(ConcurrentLinkedList *list) { // As long as the list exists this lock will never end in nirvana int retcode = pthread_mutex_lock(&list->firstElementMutex); handle_thread_error(retcode, "lock first elements mutex", THREAD_EXIT); ConcurrentListElement *element = list->firstElement; }
void *handle_pipe(void *targ) { sec = 5; nsec = 5000; char *name = (char *) targ; int retcode; // printf("starting thread pipe name=%s\n", name); retcode = pthread_barrier_wait(& start_barrier); if (retcode < 0 && retcode != PTHREAD_BARRIER_SERIAL_THREAD) { handle_thread_error(retcode, "pthread_barrier_wait", THREAD_EXIT); } // printf("opening pipe name=%s\n", name); int fd = open(name, O_RDONLY); // printf("opened fd=%d for pipe name=%s\n", fd, name); handle_error(fd, "open", THREAD_EXIT); char *buffer = (char *) malloc((buffer_size + 1) * sizeof(char)); // printf("starting thread on fd=%d\n", fd); if (sec >= 0 && nsec >= 0) { struct timeval timeout; timeout.tv_sec = sec; timeout.tv_usec = nsec; retcode = select(100, &fdin_set, NULL, NULL, &timeout); } else { retcode = select(nfds, &fdin_set, NULL, NULL, NULL); } handle_error(retcode, "select", PROCESS_EXIT); int n = read(fd, buffer, buffer_size); handle_error(n, "read", THREAD_EXIT); buffer[n] = '\000'; printf("for pipe name=%s (fd=%d) found data:\n\"%s\"\n", name, fd, buffer); sleep(1); printf("exiting\n"); exit(0); return NULL; }
void *handle_pipe(void *targ) { char *name = (char *) targ; int retcode; // printf("starting thread pipe name=%s\n", name); retcode = pthread_barrier_wait(& start_barrier); if (retcode < 0 && retcode != PTHREAD_BARRIER_SERIAL_THREAD) { handle_thread_error(retcode, "pthread_barrier_wait", THREAD_EXIT); } // printf("opening pipe name=%s\n", name); int fd = open(name, O_RDONLY); // printf("opened fd=%d for pipe name=%s\n", fd, name); handle_error(fd, "open", THREAD_EXIT); char buffer[buffer_size + 1]; // printf("starting thread on fd=%d\n", fd); int n = read(fd, buffer, buffer_size); handle_error(n, "read", THREAD_EXIT); buffer[n] = '\000'; printf("for pipe name=%s (fd=%d) found data:\n\"%s\"\n", name, fd, buffer); sleep(1); printf("exiting\n"); exit(0); return NULL; }
/* * Return an element */ void returnElement(ConcurrentListElement *element) { int retcode = pthread_mutex_unlock(&element->usageMutex); handle_thread_error(retcode, "unlock emement mutex", THREAD_EXIT); }
void *thread_run(void *ptr) { int retcode; struct thread_arg *arg = (struct thread_arg *) ptr; char **strings = arg->arr.strings; int len = arg->arr.len; int idx = arg->thread_idx; if (use_psort) { switch (selected_mt_sort_type) { case MT_HEAP_SORT: parallel_hsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, psort_internal_threads); break; case MT_TERNARY_HEAP_SORT: parallel_ternary_hsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, psort_internal_threads); break; case MT_QUICK_SORT: parallel_qsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, psort_internal_threads); break; case MT_FLASH_SORT: parallel_fsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, metric_str_full, (void *) NULL, psort_internal_threads); break; case MT_FLASH_SORT_BIN: parallel_fsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, metric_binary_printable_pref, (void *) NULL, psort_internal_threads); break; case MT_INSERTION_SORT: parallel_isort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, psort_internal_threads); break; case MT_MERGE_SORT: parallel_msort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, psort_internal_threads); break; default: /* should *never* happen: */ handle_error_myerrno(-1, -1, "wrong mt_sort_type", PROCESS_EXIT); } } else { switch (selected_mt_sort_type) { case MT_HEAP_SORT: hsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL); break; case MT_TERNARY_HEAP_SORT: ternary_hsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL); break; case MT_QUICK_SORT: qsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL); break; case MT_FLASH_SORT: fsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, metric_str_full, (void *) NULL); break; case MT_FLASH_SORT_BIN: fsort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL, metric_binary_printable_pref, (void *) NULL); break; case MT_INSERTION_SORT: isort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL); break; case MT_MERGE_SORT: msort_r(strings, len, sizeof(char_ptr), compare_str_full, (void *) NULL); break; default: /* should *never* happen: */ handle_error_myerrno(-1, -1, "wrong mt_sort_type", PROCESS_EXIT); } } for (int step = 1; step < thread_count; step *= 2) { retcode = pthread_barrier_wait(& barrier); if (retcode == PTHREAD_BARRIER_SERIAL_THREAD) { pthread_mutex_lock(&output_mutex); /* printf("thread %ld (%d) is PTHREAD_BARRIER_SERIAL_THREAD=%d\n", (long) id, tid, retcode); */ pthread_mutex_unlock(&output_mutex); } else { handle_thread_error(retcode, "pthread_barrier_wait", THREAD_EXIT); } if (idx % (2*step) == 0) { int other_idx = idx + step; if (other_idx < thread_count) { int i = 0; int j = 0; int k = 0; int m = segments[idx].arr.len; int n = segments[other_idx].arr.len; int total_len = m + n; char_ptr *strings = malloc(total_len * sizeof(char_ptr)); char_ptr *left = segments[idx].arr.strings; char_ptr *right = segments[other_idx].arr.strings; while (i+j < total_len) { if (i >= m) { while (j < n) { strings[k++] = right[j++]; } } else if (j >= n) { while (i < m) { strings[k++] = left[i++]; } } else { if (strcmp(left[i], right[j]) <= 0) { strings[k++] = left[i++]; } else { strings[k++] = right[j++]; } } } segments[idx].arr.len = total_len; segments[idx].arr.strings = strings; segments[other_idx].arr.len = 0; segments[other_idx].arr.strings = NULL; } } } return (void *) NULL; }
int main(int argc, char *argv[]) { int retcode; pthread_t *thread; char *argv0 = argv[0]; if (is_help_requested(argc, argv)) { usage(argv0, ""); } if (argc != 3 && argc != 5) { printf("found %d arguments\n", argc - 1); usage(argv0, "wrong number of arguments"); } int opt_idx = 1; int n_idx = 2; use_psort = FALSE; if (argc == 5) { if (strcmp(argv[1], "-p") != 0) { usage(argv0, "wrong first option"); } psort_internal_threads = atoi(argv[2]); opt_idx+=2; n_idx+=2; use_psort = TRUE; } /* TODO consider using getopt instead!! */ char *argv_opt = argv[opt_idx]; if (strlen(argv_opt) != 2 || argv_opt[0] != '-') { usage(argv0, "wrong option"); } char opt_char = argv_opt[1]; switch (opt_char) { case 'h' : selected_mt_sort_type = MT_HEAP_SORT; break; case 't' : selected_mt_sort_type = MT_TERNARY_HEAP_SORT; break; case 'f' : selected_mt_sort_type = MT_FLASH_SORT; break; case 'b' : selected_mt_sort_type = MT_FLASH_SORT_BIN; break; case 'q' : selected_mt_sort_type = MT_QUICK_SORT; break; case 'i' : selected_mt_sort_type = MT_INSERTION_SORT; break; case 'm' : selected_mt_sort_type = MT_MERGE_SORT; break; default: usage(argv0, "wrong option: only -q and -h supported"); break; } thread_count = atoi(argv[n_idx]); if (thread_count < 1 || thread_count > 1024) { printf("running with %d threads\n", thread_count); usage(argv[0], "wrong number of threads"); } struct string_array content = read_to_array(STDIN_FILENO); int len_per_thread = content.len / thread_count; thread = (pthread_t *) malloc(thread_count * sizeof(pthread_t)); segments = (struct thread_arg *) malloc(thread_count * sizeof(struct thread_arg)); retcode = pthread_barrier_init(&barrier, NULL, thread_count); handle_thread_error(retcode, "pthread_barrier_init", PROCESS_EXIT); retcode = pthread_mutex_init(&output_mutex, NULL); handle_thread_error(retcode, "pthread_mutex_init", PROCESS_EXIT); int rest_len = content.len; char **ptr = content.strings; for (int i = 0; i < thread_count; i++) { segments[i].thread_idx = i; segments[i].arr.strings = ptr; if (i == thread_count-1) { segments[i].arr.len = rest_len; } else { segments[i].arr.len = len_per_thread; } ptr += len_per_thread; rest_len -= len_per_thread; /* pthread_mutex_lock(&output_mutex); */ /* printf("main: starting thread %d\n", i); */ /* pthread_mutex_unlock(&output_mutex); */ retcode = pthread_create(&(thread[i]), NULL, thread_run, &(segments[i])); handle_thread_error(retcode, "pthread_create", PROCESS_EXIT); /* pthread_mutex_lock(&output_mutex); */ /* printf("main: started %d\n", i); */ /* pthread_mutex_unlock(&output_mutex); */ } for (int i = 0; i < thread_count; i++) { /* printf("main: joining thread %d\n", i); */ retcode = pthread_join(thread[i], NULL); handle_thread_error(retcode, "pthread_join", PROCESS_EXIT); /* printf("main: joined thread %d\n", i); */ } char_ptr *strings = segments[0].arr.strings; int len = segments[0].arr.len; for (int i = 0; i < len; i++) { /* printf("%5d \"%s\"\n", i, strings[i]); */ printf("%s\n", strings[i]); } pthread_barrier_destroy(&barrier); // printf("DONE\n"); exit(0); }