1
0

3 Commits

Author SHA1 Message Date
59b7caf82e feat(lab02): add ex07 resouces 2026-04-01 13:07:56 +02:00
b1a1d6af60 doc(lab02): start doc for ex7 2026-04-01 13:07:06 +02:00
d477abe506 feat(lab02): add code for ex07 2026-04-01 10:20:35 +02:00
3 changed files with 126 additions and 12 deletions

View File

@@ -150,7 +150,7 @@ license: GPL
description: Module skeleton
author: Klagarge <remi@heredero.ch>
author: Fastium <fastium.pro@proton.me>
depends:
depends:
name: mymodule
vermagic: 5.15.148 SMP preempt mod_unload aarch64
parm: text:charp
@@ -332,13 +332,13 @@ for (int i = 0; i < elements; i++) {
"temperature" = -1991 dot "register value" / 10 + 223000
$
The chip ID can be verified in ```/proc/iomem```.
The register value of the temperature can be verified in the file: ```/sys/class/thermal/thermal_zone0/temp```.
The chip ID can be verified in ```/proc/iomem```.
The register value of the temperature can be verified in the file: ```/sys/class/thermal/thermal_zone0/temp```.
The MAC address can be verified with ``` ifconfig```.
]
)
The resources are savec in a struct:
The resources are savec in a struct:
```c
static struct resource* resources[3] = {[0] = 0,};
```
@@ -384,6 +384,15 @@ Easy exercice, a thread in the kernet is a `struct task_struct*` that can be cre
]
)
This exercice make 2 threads in concurrency with wait queue. Here the queue ware declare
statically with the macro `DECLARE_WAIT_QUEUE_HEAD`. Then for this exercice we use an atomic
trigger with 2 queues. It important that the trigger is atomic or protected by mutex because
there is concurrency. The wait queues are used to wait until the trigger has changed to keep
synchronization between the threads.
It is very important to add `kthread_should_stop()` as a condition to wake up queue, because if there is
a problem during the implementation, we cannot kill the code.
//-------------------
// Exercise 8: Interrupts
//-------------------

View File

@@ -0,0 +1,94 @@
#include <linux/module.h> // needed by all modules
#include <linux/init.h> // needed for macros
#include <linux/kernel.h> // needed for debugging
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/atomic.h>
#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");
}

View File

@@ -7,6 +7,7 @@
#include "s02e04-dynamic_allocation.c"
#include "s02e05-io_memory_mapped.c"
#include "s02e06-thread.c"
#include "s02e07-sleeping.c"
static int __init skeleton_init(void) {
@@ -14,22 +15,27 @@ static int __init skeleton_init(void) {
pr_info("--------------------\n");
// Lab02 - Exercise 2: Parameters
parameters_print();
// parameters_print();
pr_info("--------------------\n");
// Lab02 - Exercise 4: Dynamic memory allocation and linked list
dynAlloc_init();
// dynAlloc_init();
pr_info("--------------------\n");
// Lab02 - Exercise 5: Memory-mapped I/O
ioMemoryMapped_init();
// ioMemoryMapped_init();
pr_info("--------------------\n");
// Lab02 - Exercise 6: Kernel thread
thread_init();
// thread_init();
pr_info("--------------------\n");
// Lab02 - Exercise 7: Sleeping
sleeping_init();
pr_info("--------------------\n");
@@ -39,19 +45,24 @@ static int __init skeleton_init(void) {
static void __exit skeleton_exit(void) {
// Lab02 - Exercise 4: Dynamic memory allocation and linked list
dynAlloc_exit();
// dynAlloc_exit();
pr_info("--------------------\n");
// Lab02 - Exercise 5: Memory-mapped I/O
ioMemoryMapped_exit();
// ioMemoryMapped_exit();
pr_info("--------------------\n");
// Lab02 - Exercise 6: Kernel thread
thread_exit();
// thread_exit();
pr_info("--------------------\n");
// Lab02 - Exercise 7: Sleeping
sleeping_exit();
pr_info("--------------------\n");