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);
}
Example #2
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;
}
Example #6
0
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);
}