/* * threadtest * * A class concurreny failure demonstration. * Append -l to use locks. */ #include #include #include #include #include #include #include "lib/pthread.h" #define NUM_THREADS 5 #define VALUE 0x1000000 #define CHECKPOINT 0x03FFFFF volatile uint32_t result = 0; int8_t use_locks = 0; volatile uint8_t the_lock = 0; void spin_lock(uint8_t volatile * lock) { while(__sync_lock_test_and_set(lock, 0x01)) { ;; /* oh god */ } } void spin_unlock(uint8_t volatile * lock) { __sync_lock_release(lock); } void *print_pid(void * garbage) { int i; printf("I am a thread and my pid is %d but my tid is %d and my stack is at %p\n", getpid(), gettid(), &i); for (uint32_t i = 0; i < VALUE; ++i) { if (use_locks) { spin_lock(&the_lock); } if (!(result & CHECKPOINT)) { printf("[%d] Checkpoint: %x\n", gettid(), result); } result++; if (use_locks) { spin_unlock(&the_lock); } } pthread_exit(garbage); } int main(int argc, char * argv[]) { if (argc > 1) { if (!strcmp(argv[1], "-l")) { use_locks = 1; } } pthread_t thread[NUM_THREADS]; printf("I am the main process and my pid is %d and my tid is also %d\n", getpid(), gettid()); printf("Attempting to %s calculate %d!\n", (use_locks) ? "(safely)" : "(unsafely)", NUM_THREADS * VALUE); for (int i = 0; i < NUM_THREADS; ++i) { pthread_create(&thread[i], NULL, print_pid, NULL); } for (int i = 0; i < NUM_THREADS; ++i) { syscall_wait(thread[i].id); } printf("Done. Result of %scomputation was %d %s!!\n", (use_locks) ? "" : "(definitely unsafe) ", result, (result == NUM_THREADS * VALUE) ? "(yay, that's right!)" : "(boo, that's wrong!)"); return 0; }