pthreads/{hello_ordered_wait/hello_ordered_wait.c → position_race/position_race.c} RENAMED
@@ -1,132 +1,126 @@
1
  /*
2
  * Copyright 2021 Jeisson Hidalgo-Cespedes - Universidad de Costa Rica
3
  * Creates a secondary thread that greets in the standard output
4
  */
5
 
6
  #include <inttypes.h>
7
  #include <pthread.h>
8
  #include <stdint.h>
9
  #include <stdio.h>
10
  #include <stdlib.h>
11
  #include <unistd.h>
12
 
13
  typedef struct shared_thread_data {
14
  size_t thread_count;
15
- size_t next_thread;
 
16
  pthread_mutex_t stdout_mutex;
17
  } shared_thread_data_t;
18
 
19
  typedef struct private_thread_data {
20
  size_t thread_number; // rank
21
  shared_thread_data_t* shared_thread_data;
22
  } private_thread_data_t;
23
 
24
  void* run(void* data);
25
  int create_threads(shared_thread_data_t* shared_thread_data);
26
 
27
  int main(int argc, char* argv[]) {
28
  int error = 0;
29
 
30
  size_t thread_count = sysconf(_SC_NPROCESSORS_ONLN);
31
  if (argc >= 2) {
32
  thread_count = strtoull(argv[1], NULL, 10);
33
  }
34
 
35
  shared_thread_data_t* shared_thread_data = (shared_thread_data_t*)
36
  calloc(1, sizeof(shared_thread_data_t));
37
 
38
  if (shared_thread_data) {
39
  shared_thread_data->thread_count = thread_count;
40
- shared_thread_data->next_thread = 0;
 
41
  error = pthread_mutex_init(&shared_thread_data->stdout_mutex, /*attr*/NULL);
42
 
43
  if (error == 0) {
44
  struct timespec start_time, finish_time;
45
  clock_gettime(/*clk_id*/CLOCK_MONOTONIC, &start_time);
46
 
47
  error = create_threads(shared_thread_data);
48
 
49
  clock_gettime(/*clk_id*/CLOCK_MONOTONIC, &finish_time);
50
  double elapsed_time = finish_time.tv_sec - start_time.tv_sec +
51
  (finish_time.tv_nsec - start_time.tv_nsec) * 1e-9;
52
  printf("execution time: %.9lfs\n", elapsed_time);
53
 
54
  pthread_mutex_destroy(&shared_thread_data->stdout_mutex);
55
  } else {
56
  fprintf(stderr, "error: could not init mutex\n");
57
  error = 11;
58
  }
59
 
60
  free(shared_thread_data);
61
  } else {
62
  fprintf(stderr, "error: could not allocated shared memory\n");
63
  error = 12;
64
  }
65
 
66
  return error;
67
  }
68
 
69
  int create_threads(shared_thread_data_t* shared_thread_data) {
70
  int error = 0;
71
  pthread_t* threads = (pthread_t*)
72
  malloc(shared_thread_data->thread_count * sizeof(pthread_t));
73
 
74
  private_thread_data_t* private_thread_data = (private_thread_data_t*)
75
  calloc(shared_thread_data->thread_count, sizeof(private_thread_data_t));
76
 
77
  if (threads && private_thread_data) {
78
  for (size_t index = 0; index < shared_thread_data->thread_count; ++index) {
79
  private_thread_data[index].thread_number = index;
80
  private_thread_data[index].shared_thread_data = shared_thread_data;
81
 
82
  error = pthread_create(&threads[index], NULL, run
83
  , &private_thread_data[index]);
84
 
85
  if (error) {
86
  fprintf(stderr, "error: could not create thread %zu\n", index);
87
  error = 21;
88
  }
89
  }
90
 
91
  pthread_mutex_lock(&shared_thread_data->stdout_mutex);
92
  printf("Hello from main thread\n");
93
  pthread_mutex_unlock(&shared_thread_data->stdout_mutex);
94
 
95
  for (size_t index = 0; index < shared_thread_data->thread_count; ++index) {
96
  pthread_join(threads[index], NULL);
97
  }
98
 
99
  free(private_thread_data);
100
  free(threads);
101
  } else {
102
  fprintf(stderr, "error: could not allocate memory for %zu threads\n"
103
  , shared_thread_data->thread_count);
104
  error = 22;
105
  }
106
 
107
  return error;
108
  }
109
 
110
  void* run(void* data) {
111
  private_thread_data_t* private_data = (private_thread_data_t*)data;
112
  shared_thread_data_t *shared_data = private_data->shared_thread_data;
113
 
114
- // bad wait
115
- // sleep(1);
 
116
 
117
- // Wait until it is my turn
118
- while (shared_data->next_thread < private_data->thread_number) {
119
- // busy-wait
120
- }
121
-
122
- // Do the ordered-task here
123
  pthread_mutex_lock(&private_data->shared_thread_data->stdout_mutex);
124
- printf("Hello from secondary thread %zu of %zu\n"
125
- , (*private_data).thread_number, shared_data->thread_count);
126
  pthread_mutex_unlock(&shared_data->stdout_mutex);
127
 
128
- // Allow subsequent thread to do the task
129
- ++shared_data->next_thread;
130
-
131
  return NULL;
132
  }
1
  /*
2
  * Copyright 2021 Jeisson Hidalgo-Cespedes - Universidad de Costa Rica
3
  * Creates a secondary thread that greets in the standard output
4
  */
5
 
6
  #include <inttypes.h>
7
  #include <pthread.h>
8
  #include <stdint.h>
9
  #include <stdio.h>
10
  #include <stdlib.h>
11
  #include <unistd.h>
12
 
13
  typedef struct shared_thread_data {
14
  size_t thread_count;
15
+ pthread_mutex_t position_mutex;
16
+ size_t position;
17
  pthread_mutex_t stdout_mutex;
18
  } shared_thread_data_t;
19
 
20
  typedef struct private_thread_data {
21
  size_t thread_number; // rank
22
  shared_thread_data_t* shared_thread_data;
23
  } private_thread_data_t;
24
 
25
  void* run(void* data);
26
  int create_threads(shared_thread_data_t* shared_thread_data);
27
 
28
  int main(int argc, char* argv[]) {
29
  int error = 0;
30
 
31
  size_t thread_count = sysconf(_SC_NPROCESSORS_ONLN);
32
  if (argc >= 2) {
33
  thread_count = strtoull(argv[1], NULL, 10);
34
  }
35
 
36
  shared_thread_data_t* shared_thread_data = (shared_thread_data_t*)
37
  calloc(1, sizeof(shared_thread_data_t));
38
 
39
  if (shared_thread_data) {
40
  shared_thread_data->thread_count = thread_count;
41
+ shared_thread_data->position = 0;
42
+ error = pthread_mutex_init(&shared_thread_data->position_mutex, NULL);
43
  error = pthread_mutex_init(&shared_thread_data->stdout_mutex, /*attr*/NULL);
44
 
45
  if (error == 0) {
46
  struct timespec start_time, finish_time;
47
  clock_gettime(/*clk_id*/CLOCK_MONOTONIC, &start_time);
48
 
49
  error = create_threads(shared_thread_data);
50
 
51
  clock_gettime(/*clk_id*/CLOCK_MONOTONIC, &finish_time);
52
  double elapsed_time = finish_time.tv_sec - start_time.tv_sec +
53
  (finish_time.tv_nsec - start_time.tv_nsec) * 1e-9;
54
  printf("execution time: %.9lfs\n", elapsed_time);
55
 
56
  pthread_mutex_destroy(&shared_thread_data->stdout_mutex);
57
  } else {
58
  fprintf(stderr, "error: could not init mutex\n");
59
  error = 11;
60
  }
61
 
62
  free(shared_thread_data);
63
  } else {
64
  fprintf(stderr, "error: could not allocated shared memory\n");
65
  error = 12;
66
  }
67
 
68
  return error;
69
  }
70
 
71
  int create_threads(shared_thread_data_t* shared_thread_data) {
72
  int error = 0;
73
  pthread_t* threads = (pthread_t*)
74
  malloc(shared_thread_data->thread_count * sizeof(pthread_t));
75
 
76
  private_thread_data_t* private_thread_data = (private_thread_data_t*)
77
  calloc(shared_thread_data->thread_count, sizeof(private_thread_data_t));
78
 
79
  if (threads && private_thread_data) {
80
  for (size_t index = 0; index < shared_thread_data->thread_count; ++index) {
81
  private_thread_data[index].thread_number = index;
82
  private_thread_data[index].shared_thread_data = shared_thread_data;
83
 
84
  error = pthread_create(&threads[index], NULL, run
85
  , &private_thread_data[index]);
86
 
87
  if (error) {
88
  fprintf(stderr, "error: could not create thread %zu\n", index);
89
  error = 21;
90
  }
91
  }
92
 
93
  pthread_mutex_lock(&shared_thread_data->stdout_mutex);
94
  printf("Hello from main thread\n");
95
  pthread_mutex_unlock(&shared_thread_data->stdout_mutex);
96
 
97
  for (size_t index = 0; index < shared_thread_data->thread_count; ++index) {
98
  pthread_join(threads[index], NULL);
99
  }
100
 
101
  free(private_thread_data);
102
  free(threads);
103
  } else {
104
  fprintf(stderr, "error: could not allocate memory for %zu threads\n"
105
  , shared_thread_data->thread_count);
106
  error = 22;
107
  }
108
 
109
  return error;
110
  }
111
 
112
  void* run(void* data) {
113
  private_thread_data_t* private_data = (private_thread_data_t*)data;
114
  shared_thread_data_t *shared_data = private_data->shared_thread_data;
115
 
116
+ pthread_mutex_lock(&private_data->shared_thread_data->position_mutex);
117
+ const size_t my_position = ++shared_data->position;
118
+ pthread_mutex_unlock(&private_data->shared_thread_data->position_mutex);
119
 
 
 
 
 
 
 
120
  pthread_mutex_lock(&private_data->shared_thread_data->stdout_mutex);
121
+ printf("Thread %zu/%zu: I arrived at position %zu\n"
122
+ , private_data->thread_number, shared_data->thread_count, my_position);
123
  pthread_mutex_unlock(&shared_data->stdout_mutex);
124
 
 
 
 
125
  return NULL;
126
  }