pthreads/{hello_ordered_wait/hello_ordered_wait.c → position_race/position_race.c} RENAMED
@@ -1,97 +1,103 @@
1
  #include <pthread.h>
2
  #include <stdio.h>
3
  #include <stdlib.h>
4
  #include <time.h>
5
  #include <unistd.h>
6
 
7
  typedef struct
8
  {
9
  size_t thread_count;
10
- size_t next_thread; // next thread to print
 
11
  } shared_data_t;
12
 
13
  typedef struct
14
  {
15
  size_t thread_num;
16
  shared_data_t* shared_data;
17
  } private_data_t;
18
 
19
  int create_threads(shared_data_t* shared_data);
20
  void* run(void* data);
21
 
22
 
23
  int main(int argc, char* argv[])
24
  {
25
  shared_data_t* shared_data = (shared_data_t*) calloc(1, sizeof(shared_data_t));
26
  if ( shared_data == NULL )
27
  return (void)fprintf(stderr, "error: could not allocate shared memory\n"), 1;
28
 
29
  shared_data->thread_count = sysconf(_SC_NPROCESSORS_ONLN);
30
  if ( argc >= 2 )
31
  shared_data->thread_count = strtoull(argv[1], NULL, 10);
32
 
33
- shared_data->next_thread = 0;
 
34
 
35
  struct timespec start_time;
36
  clock_gettime(CLOCK_MONOTONIC, &start_time);
37
 
38
  int error = create_threads(shared_data);
39
  if ( error )
40
  return error;
41
 
42
  struct timespec finish_time;
43
  clock_gettime(CLOCK_MONOTONIC, &finish_time);
44
 
45
  double elapsed_seconds = finish_time.tv_sec - start_time.tv_sec
46
  + 1e-9 * (finish_time.tv_nsec - start_time.tv_nsec);
47
 
48
  printf("Hello execution time %.9lfs\n", elapsed_seconds);
49
 
 
50
  free(shared_data);
51
  return 0;
52
  }
53
 
54
  int create_threads(shared_data_t* shared_data)
55
  {
56
  pthread_t* threads = (pthread_t*) malloc(shared_data->thread_count * sizeof(pthread_t));
57
  if ( threads == NULL )
58
  return (void)fprintf(stderr, "error: could not allocate memory for %zu threads\n", shared_data->thread_count), 2;
59
 
60
  private_data_t* private_data = (private_data_t*) calloc(shared_data->thread_count, sizeof(private_data_t));
61
  if ( private_data == NULL )
62
  return (void)fprintf(stderr, "error: could not allocate private memory for %zu threads\n", shared_data->thread_count), 3;
63
 
64
  for ( size_t index = 0; index < shared_data->thread_count; ++index )
65
  {
66
  private_data[index].thread_num = index;
67
  private_data[index].shared_data = shared_data;
68
  pthread_create(&threads[index], NULL, run, &private_data[index]);
69
  }
70
 
 
71
  printf("Hello world from main thread\n");
 
72
 
73
  for ( size_t index = 0; index < shared_data->thread_count; ++index )
74
  pthread_join(threads[index], NULL);
75
 
76
  free(private_data);
77
  free(threads);
78
  return 0;
79
  }
80
 
81
  void* run(void* data)
82
  {
83
  private_data_t* private_data = (private_data_t*)data;
84
  shared_data_t* shared_data = private_data->shared_data;
85
 
86
  size_t thread_num = (*private_data).thread_num;
87
  size_t thread_count = shared_data->thread_count;
88
 
89
- while ( shared_data->next_thread < thread_num )
90
- ; // busy wait
91
 
92
- printf("Hello world from secondary thread %zu of %zu\n", thread_num, thread_count);
 
 
93
 
94
- ++shared_data->next_thread;
95
 
96
  return NULL;
97
  }
1
  #include <pthread.h>
2
  #include <stdio.h>
3
  #include <stdlib.h>
4
  #include <time.h>
5
  #include <unistd.h>
6
 
7
  typedef struct
8
  {
9
  size_t thread_count;
10
+ pthread_mutex_t position_mutex;
11
+ size_t position;
12
  } shared_data_t;
13
 
14
  typedef struct
15
  {
16
  size_t thread_num;
17
  shared_data_t* shared_data;
18
  } private_data_t;
19
 
20
  int create_threads(shared_data_t* shared_data);
21
  void* run(void* data);
22
 
23
 
24
  int main(int argc, char* argv[])
25
  {
26
  shared_data_t* shared_data = (shared_data_t*) calloc(1, sizeof(shared_data_t));
27
  if ( shared_data == NULL )
28
  return (void)fprintf(stderr, "error: could not allocate shared memory\n"), 1;
29
 
30
  shared_data->thread_count = sysconf(_SC_NPROCESSORS_ONLN);
31
  if ( argc >= 2 )
32
  shared_data->thread_count = strtoull(argv[1], NULL, 10);
33
 
34
+ pthread_mutex_init(&shared_data->position_mutex, /*attr*/ NULL);
35
+ shared_data->position = 0;
36
 
37
  struct timespec start_time;
38
  clock_gettime(CLOCK_MONOTONIC, &start_time);
39
 
40
  int error = create_threads(shared_data);
41
  if ( error )
42
  return error;
43
 
44
  struct timespec finish_time;
45
  clock_gettime(CLOCK_MONOTONIC, &finish_time);
46
 
47
  double elapsed_seconds = finish_time.tv_sec - start_time.tv_sec
48
  + 1e-9 * (finish_time.tv_nsec - start_time.tv_nsec);
49
 
50
  printf("Hello execution time %.9lfs\n", elapsed_seconds);
51
 
52
+ pthread_mutex_destroy(&shared_data->position_mutex);
53
  free(shared_data);
54
  return 0;
55
  }
56
 
57
  int create_threads(shared_data_t* shared_data)
58
  {
59
  pthread_t* threads = (pthread_t*) malloc(shared_data->thread_count * sizeof(pthread_t));
60
  if ( threads == NULL )
61
  return (void)fprintf(stderr, "error: could not allocate memory for %zu threads\n", shared_data->thread_count), 2;
62
 
63
  private_data_t* private_data = (private_data_t*) calloc(shared_data->thread_count, sizeof(private_data_t));
64
  if ( private_data == NULL )
65
  return (void)fprintf(stderr, "error: could not allocate private memory for %zu threads\n", shared_data->thread_count), 3;
66
 
67
  for ( size_t index = 0; index < shared_data->thread_count; ++index )
68
  {
69
  private_data[index].thread_num = index;
70
  private_data[index].shared_data = shared_data;
71
  pthread_create(&threads[index], NULL, run, &private_data[index]);
72
  }
73
 
74
+ pthread_mutex_lock(&shared_data->position_mutex);
75
  printf("Hello world from main thread\n");
76
+ pthread_mutex_unlock(&shared_data->position_mutex);
77
 
78
  for ( size_t index = 0; index < shared_data->thread_count; ++index )
79
  pthread_join(threads[index], NULL);
80
 
81
  free(private_data);
82
  free(threads);
83
  return 0;
84
  }
85
 
86
  void* run(void* data)
87
  {
88
  private_data_t* private_data = (private_data_t*)data;
89
  shared_data_t* shared_data = private_data->shared_data;
90
 
91
  size_t thread_num = (*private_data).thread_num;
92
  size_t thread_count = shared_data->thread_count;
93
 
94
+ pthread_mutex_lock(&shared_data->position_mutex);
 
95
 
96
+ ++shared_data->position;
97
+ fprintf(stdout, "Thread %zu/%zu: I arrived at position %zu\n", thread_num
98
+ , thread_count, shared_data->position);
99
 
100
+ pthread_mutex_unlock(&shared_data->position_mutex);
101
 
102
  return NULL;
103
  }