toaruos/userspace/tests/test-threads.c
Kevin Lange 4d8335ad75 Implement proper wait/waitpid.
This is a pretty big commit, so let's run through it in parts:

- All of the userspace changes are to switch away from syscall_wait
  Mostly, this is to waitpid; some things were tweaked to do things
  "properly" instead of waiting for particular processes. Init has
  been fixed to do a proper spin wait.
- syscall_wait is gone - as are its uses. newlib bindings have been
  using just waitpid for a while now.
- waitpid now performs like a Unix waitpid
- process reaping is no longer a "do this on next change thing":
  it happens when a process is waited on, like it should
  (That means we can have real zombies: terminated processes that
  have not yet been waited on)
- Reparenting of children to init has been implemented, so you
  can fork-daemonize!

Overall, this is pretty big... So I hope it doesn't break everything.
2014-04-27 01:37:33 -07:00

83 lines
1.7 KiB
C

/*
* threadtest
*
* A class concurreny failure demonstration.
* Append -l to use locks.
*/
#include <stdio.h>
#include <unistd.h>
#include <syscall.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/wait.h>
#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) {
waitpid(thread[i].id, NULL, 0);
}
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;
}