pthreads/{position_race/position_race.c → relay_race/relay_race.c} RENAMED
@@ -1,103 +1,168 @@
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
  }
1
  #include <pthread.h>
2
+ #include <semaphore.h>
3
  #include <stdio.h>
4
  #include <stdlib.h>
5
  #include <time.h>
6
  #include <unistd.h>
7
 
8
  typedef struct
9
  {
10
+ size_t team_count;
11
+ sem_t* batons;
12
+ pthread_barrier_t start_barrier;
13
+ useconds_t stage1_duration;
14
+ useconds_t stage2_duration;
15
  size_t position;
16
+ pthread_mutex_t position_mutex;
17
  } shared_data_t;
18
 
19
  typedef struct
20
  {
21
+ size_t my_team_number;
22
  shared_data_t* shared_data;
23
  } private_data_t;
24
 
25
+ int analyze_arguments(int argc, char* argv[], shared_data_t* shared_data);
26
  int create_threads(shared_data_t* shared_data);
27
+ void* start_race(void* data);
28
+ void* finish_race(void* data);
29
 
30
 
31
  int main(int argc, char* argv[])
32
  {
33
  shared_data_t* shared_data = (shared_data_t*) calloc(1, sizeof(shared_data_t));
34
  if ( shared_data == NULL )
35
  return (void)fprintf(stderr, "error: could not allocate shared memory\n"), 1;
36
 
37
+ int error = analyze_arguments(argc, argv, shared_data);
38
+ if ( error == 0 )
39
+ {
40
+ shared_data->batons = (sem_t*) calloc(shared_data->team_count, sizeof(sem_t));
41
+ if ( shared_data->batons )
42
+ {
43
+ for ( size_t index = 0; index < shared_data->team_count; ++index )
44
+ sem_init(&shared_data->batons[index], 0 /*pshared*/, 0);
45
 
46
+ pthread_barrier_init(&shared_data->start_barrier, /*attr*/ NULL, shared_data->team_count);
47
  shared_data->position = 0;
48
+ pthread_mutex_init(&shared_data->position_mutex, /*attr*/ NULL);
49
 
50
  struct timespec start_time;
51
  clock_gettime(CLOCK_MONOTONIC, &start_time);
52
 
53
+ error = create_threads(shared_data);
54
+ if ( error == 0 )
55
+ {
 
56
  struct timespec finish_time;
57
  clock_gettime(CLOCK_MONOTONIC, &finish_time);
58
 
59
  double elapsed_seconds = finish_time.tv_sec - start_time.tv_sec
60
  + 1e-9 * (finish_time.tv_nsec - start_time.tv_nsec);
61
 
62
+ printf("Simulation time %.9lfs\n", elapsed_seconds);
63
+ }
64
 
65
  pthread_mutex_destroy(&shared_data->position_mutex);
66
+ pthread_barrier_destroy(&shared_data->start_barrier);
67
+ free(shared_data->batons);
68
+ }
69
+ else
70
+ {
71
+ fprintf(stderr, "error: could not allocate memory for %zu batons\n", shared_data->team_count);
72
+ error = 2;
73
+ }
74
+ }
75
+
76
  free(shared_data);
77
+ return error;
78
+ }
79
+
80
+ int analyze_arguments(int argc, char* argv[], shared_data_t* shared_data)
81
+ {
82
+ if ( argc != 4 )
83
+ {
84
+ fprintf(stderr, "usage: relay_race teams stage1_duration stage2_duration\n");
85
+ return 1;
86
+ }
87
+
88
+ if ( sscanf(argv[1], "%zu", &shared_data->team_count) != 1 || shared_data->team_count == 0 )
89
+ return (void)fprintf(stderr, "invalid team count: %s\n", argv[1]), 1;
90
+
91
+ if ( sscanf(argv[2], "%u", &shared_data->stage1_duration) != 1 )
92
+ return (void)fprintf(stderr, "invalid stage 1 duration: %s\n", argv[2]), 2;
93
+
94
+ if ( sscanf(argv[3], "%u", &shared_data->stage2_duration) != 1 )
95
+ return (void)fprintf(stderr, "invalid stage 2 duration: %s\n", argv[3]), 3;
96
+
97
+ return EXIT_SUCCESS;
98
  }
99
 
100
  int create_threads(shared_data_t* shared_data)
101
  {
102
+ size_t thread_count = 2 * shared_data->team_count;
103
+
104
+ pthread_t* threads = (pthread_t*) malloc(thread_count * sizeof(pthread_t));
105
  if ( threads == NULL )
106
+ return (void)fprintf(stderr, "error: could not allocate memory for %zu threads\n", thread_count), 2;
107
 
108
+ private_data_t* private_data = (private_data_t*) calloc(thread_count, sizeof(private_data_t));
109
  if ( private_data == NULL )
110
+ return (void)fprintf(stderr, "error: could not allocate private memory for %zu threads\n", thread_count), 3;
111
 
112
+ #if INVERTED_TEAM_ORDER
113
+ for ( size_t index = shared_data->team_count - 1; index < shared_data->team_count; --index )
114
+ #else
115
+ for ( size_t index = 0; index < shared_data->team_count; ++index )
116
+ #endif
117
  {
118
+ private_data[index].my_team_number = index;
119
  private_data[index].shared_data = shared_data;
120
+ pthread_create(&threads[index], NULL, start_race, &private_data[index]);
121
  }
122
 
123
+ #if INVERTED_TEAM_ORDER
124
+ for ( size_t index = thread_count - 1; index >= shared_data->team_count; --index )
125
+ #else
126
+ for ( size_t index = shared_data->team_count; index < thread_count; ++index )
127
+ #endif
128
+ {
129
+ private_data[index].my_team_number = index - shared_data->team_count;
130
+ private_data[index].shared_data = shared_data;
131
+ pthread_create(&threads[index], NULL, finish_race, &private_data[index]);
132
+ }
133
 
134
+ for ( size_t index = 0; index < thread_count; ++index )
135
  pthread_join(threads[index], NULL);
136
 
137
  free(private_data);
138
  free(threads);
139
  return 0;
140
  }
141
 
142
+ void* start_race(void* data)
143
  {
144
  private_data_t* private_data = (private_data_t*)data;
145
  shared_data_t* shared_data = private_data->shared_data;
146
 
147
+ pthread_barrier_wait(&shared_data->start_barrier);
148
+ usleep( 1000 * shared_data->stage1_duration );
149
+ sem_post(&shared_data->batons[private_data->my_team_number]);
150
 
151
+ return NULL;
152
+ }
153
 
154
+ void* finish_race(void* data)
155
+ {
156
+ private_data_t* private_data = (private_data_t*)data;
157
+ shared_data_t* shared_data = private_data->shared_data;
158
 
159
+ sem_wait(&shared_data->batons[private_data->my_team_number]);
160
+ usleep( 1000 * shared_data->stage2_duration );
161
+
162
+ pthread_mutex_lock(&shared_data->position_mutex);
163
+ if ( ++shared_data->position <= 3 )
164
+ printf("Place %zu: team %zu\n", shared_data->position, private_data->my_team_number + 1);
165
  pthread_mutex_unlock(&shared_data->position_mutex);
166
 
167
  return NULL;
168
  }