Prashanth L.A.
2023-10-02
but shares - rest of address space (heap, static global, code section too)
Recall
Code segment is where instructions live
Heap segment contains malloc’d data dynamic data structures (grows downward)
Stack segment contains local variables arguments to routines, return values, etc (grows upward)
There will be one stack per thread
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "common.h"
#include "common_threads.h"
void *mythread(void *arg) {
printf("%s\n", (char *) arg);
return NULL;
}
int main(int argc, char *argv[]) {
if (argc != 1) {
fprintf(stderr, "usage: main\n");
exit(1);
}
pthread_t p1, p2;
printf("main: begin\n");
Pthread_create(&p1, NULL, mythread, "A");
Pthread_create(&p2, NULL, mythread, "B");
// join waits for the threads to finish
Pthread_join(p1, NULL);
Pthread_join(p2, NULL);
printf("main: end\n");
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "common.h"
#include "common_threads.h"
int max;
volatile int counter = 0; // shared global variable
void *mythread(void *arg) {
char *letter = arg;
int i; // stack (private per thread)
printf("%s: begin [addr of i: %p]\n", letter, &i);
for (i = 0; i < max; i++) {
counter = counter + 1; // shared: only one
}
printf("%s: done\n", letter);
return NULL;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "usage: main-first <loopcount>\n");
exit(1);
}
max = atoi(argv[1]);
pthread_t p1, p2;
printf("main: begin [counter = %d] [%x]\n", counter,
(unsigned int) &counter);
Pthread_create(&p1, NULL, mythread, "A");
Pthread_create(&p2, NULL, mythread, "B");
// join waits for the threads to finish
Pthread_join(p1, NULL);
Pthread_join(p2, NULL);
printf("main: done\n [counter: %d]\n [should: %d]\n",
counter, max*2);
return 0;
}
prompt> gcc -o main main.c -Wall -pthread; ./main main: begin (counter = 0)
A: begin
B: begin
A: done
B: done
main: done with both (counter = 20000000)
prompt> ./main
main: begin (counter = 0)
A: begin
B: begin
A: done
B: done
main: done with both (counter = 19345221)
prompt> ./main
main: begin (counter = 0)
A: begin
B: begin
A: done
B: done
main: done with both (counter = 19221041)
mov 0x8049a1c, %eax
add $0x1, %eax
mov %eax, 0x8049a1c
Two threads
counter = counter + 1 (default is 50)
Expected result: 52
Term | Meaning |
---|---|
Critical section | is a piece of code that accesses a shared resource, usually a variable or data structure. |
Race condition | arises if multiple threads of execution enter the critical section at roughly the same time; both attempt to update the shared data structure, leading to a surprising (and perhaps undesirable) outcome. |
Indeterminate program | consists of one or more race conditions; non-deterministic output |
Mutual exclusion primitives | guarantees that only a single thread ever enters a critical section |