This project implements a simple user-level scheduler within a process with thread synchronization.
Implements the following pthread interfaces:
pthread_create
: Creates a new thread with the specified start routine and argumentspthread_exit
: Terminates the calling thread and makes its exit status availablepthread_join
: Waits for a specific thread to terminate and retrieves its exit statuspthread_self
: Returns the ID of the calling thread
Threads are cycled in a round-robin fashion and the scheduler uses SIGALRM
for timeouts.
- Signal blocking mechanisms (
lock()
andunlock()
), which block/unblockSIGALRM
to create critical sections where scheduling cannot occur. - An implementation of mutex interfaces:
pthread_mutex_init
: Initializes a mutex with default attributespthread_mutex_lock
: Acquires a lock on the specified mutexpthread_mutex_destroy
: Destroys a mutex, freeing its resourcespthread_mutex_unlock
: Releases a lock on the specified mutex
- An implementation of barrier interfaces:
pthread_barrier_init
: Initializes a barrier with a specific thread countpthread_barrier_wait
: Makes the calling thread wait at a barrier until all threads reach itpthread_barrier_destroy
: Destroys a barrier, freeing its resources
enum thread_status { TS_EXITED, TS_READY, TS_RUNNING, TS_BLOCKED };
typedef struct thread_control_block {
pthread_t id;
jmp_buf registers;
void *stack;
enum thread_status status;
void *ret_val;
bool has_mutex;
} TCB;
typedef struct {
int flag;
} mutex_t;
typedef union {
pthread_mutex_t mutex;
mutex_t my_mutex;
} my_mutex_t;
typedef struct {
queue_t waitqueue;
unsigned limit;
unsigned count;
} barrier_t;
typedef union {
pthread_barrier_t barrier;
barrier_t my_barrier;
} my_barrier_t;
void scheduler_init()
: Initializes the scheduler by assigning the first thread as the main threadvoid init_handler()
: Initializes the signal handler (schedule) for the timerTCB *get_new_thread()
: Returns a new thread from the thread poolvoid thread_init(TCB *new_thread)
: Allocates the stack for the new threadvoid reg_init(TCB *new_thread, void *(*start_routine)(void *), void *arg)
: Initializes the registers for the new thread to run the start routinevoid lock()
: Blocks SIGALRM to prevent schedulingvoid unlock()
: Unblocks SIGALRM to allow schedulingvoid clear_waitlist(queue_t *waitqueue)
: Moves all threads from the wait queue to the ready queue
- test_one_thread.c: Tests the creation, execution, and cleanup of a single thread
- test_custom_schedule.c: Tests the scheduling of a few threads
- test_early_exit.c: Tests the handling of main thread exiting early
- test_many_threads.c: Tests the handling of the maximum allowed number of threads
- test_random_threads.c: Tests the handling of a few threads counting up to a random number
- test_new_threads.c: Tests the cleanup of old threads and the creation of new threads
- test_zombie_threads.c: Tests the handling of zombie threads (threads that have exited but have not been joined)
- test_wait_thread.c: Tests waiting for one busy thread to finish
- test_mutex.c: Tests basic mutex operations
- test_mutex_2.c: Tests mutex with multiple threads
- test_mutex_3.c: Tests mutex contention scenarios
- test_barrier.c: Tests basic barrier functionality
- test_barrier_2.c: Tests barriers with multiple threads
- test_barrier_3.c: Tests complex barrier scenarios
- test_busy_threads.c: Tests scheduler with CPU-intensive threads
- test_sync.c: Tests synchronization between threads