diff --git a/src/01-skeleton/s02e07-sleeping.c b/src/01-skeleton/s02e07-sleeping.c new file mode 100644 index 0000000..5db3164 --- /dev/null +++ b/src/01-skeleton/s02e07-sleeping.c @@ -0,0 +1,94 @@ +#include // needed by all modules +#include // needed for macros +#include // needed for debugging + + +#include +#include +#include +#include + + +#define TIMEOUT_S 5 + +DECLARE_WAIT_QUEUE_HEAD(queue_1); +DECLARE_WAIT_QUEUE_HEAD(queue_2); + +static struct task_struct* thread_1; +static struct task_struct* thread_2; +static atomic_t trigger = ATOMIC_INIT(0); + + +int thread_skeleton_1(void* data) { + // must wait 5 seconds and start thread 2 + + pr_info("Thread 1 started\n"); + + while (!kthread_should_stop()) { + pr_info("Thread 1 wakes up\n"); + ssleep(TIMEOUT_S); + + // Setup trigger for condition of the thread 2 + atomic_set(&trigger, 1); + + // Wake up thread 2 + wake_up_interruptible(&queue_2); + + // Wait until thread 2 has reset the trigger + wait_event_interruptible(queue_1, atomic_read(&trigger) == 0 || kthread_should_stop()); + + } + + return 0; +} + +int thread_skeleton_2(void* data) { + // have to PING when wakes up + + pr_info("Thread 2 started\n"); + + + while (!kthread_should_stop()) { + + // wait until trigger is set up + wait_event_interruptible(queue_2, atomic_read(&trigger) == 1 || kthread_should_stop()); + pr_info("Thread 2 wakes up\n"); + + // reset trigger + atomic_set(&trigger, 0); + + // wake up thread 1 + wake_up_interruptible(&queue_1); + } + + return 0; +} + + +void sleeping_init(void) { + pr_info("Initialize kernel thread\n"); + + atomic_set(&trigger, 0); + + thread_1 = kthread_run(thread_skeleton_1, NULL, "Thread 1 - sleeping"); + if (IS_ERR(thread_1)) { + pr_err("Failed to create kernel thread 1\n"); + return; + } + + thread_2 = kthread_run(thread_skeleton_2, NULL, "Thread 2 - sleeping"); + if (IS_ERR(thread_2)) { + pr_err("Failed to create kernel thread 1\n"); + return; + } + + pr_info("Kernel thread sleeping initialized\n"); + +} + +void sleeping_exit(void) { + pr_info("Exiting kernel sleeping thread\n"); + kthread_stop(thread_1); + kthread_stop(thread_2); + pr_info("Kernel thread sleeping exited\n"); +}