// !> Multi-threaded sum using a single global variable and mutexes
/**
* Usage
*
* ./sum <from> <to>
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pthread.h>
#include <assert.h>
long sum = 0;
pthread_mutex_t sum_lock = PTHREAD_MUTEX_INITIALIZER;
typedef struct {
long from;
long to;
} sum_args_t;
long sum_from_to(long from, long to) {
for (long i = from; i <= to; ++i) {
// enter if allowed, lock entry
//while (sum_lock) { /* wait */ };
//sum_lock = 1;
pthread_mutex_lock(&sum_lock);
sum += i; // not performed atomically
pthread_mutex_unlock(&sum_lock);
//sum_lock = 0; //unlock
// unlock entry, and exit
// movq sum, %rax
// addq %rcx, %rax
// movq %rax, sum
//
// sum Thread 1 Thread 2
// 100 read 100 ---
// 100 add 12 to 100
// 112 write 112 to sum
// 112 read 112 from sum
// 112 --- read 112 from sum
// 112 add 52 to 112
// 164 write 164 to sum
// 164 add 13 112 ---
// 125 write 125 to sum
}
fprintf(stderr, "Completed %ld to %ld\n", from, to);
}
void *sum_thread(void *args) {
sum_args_t *sum_args = args;
sum_from_to(sum_args->from, sum_args->to);
return NULL;
}
int main(int argc, char **argv) {
assert(argc >= 3);
long from = atol(argv[1]);
long to = atol(argv[2]);
pthread_t th;
sum_args_t sum_args = { .from = from, .to = to / 2 };
// perform sum of 'from' to 'to / 2' in helper thread
assert(0 == pthread_create(&th, NULL, sum_thread, &sum_args));
// perform sum of '(to / 2) + 1' to 'to'
sum_from_to(to / 2 + 1, to);
assert(0 == pthread_join(th, NULL));
printf("%ld\n", sum);
return 0;
}