1
0

5 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
8fff875529 feat(lab02): add ex06 2026-03-31 21:06:44 +02:00
e4089d2e05 fix(lab02): avoid to free a null pointer 2026-03-31 21:06:05 +02:00
5 changed files with 182 additions and 11 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,};
```
@@ -369,6 +369,8 @@ registers[0] = ioremap(CHIP_ID_BASE_ADDR, 0x1000);
]
)
Easy exercice, a thread in the kernet is a `struct task_struct*` that can be created with `kthread_run`
//-------------------
// Exercise 7: Sleeping
//-------------------
@@ -382,6 +384,15 @@ registers[0] = ioremap(CHIP_ID_BASE_ADDR, 0x1000);
]
)
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

@@ -49,7 +49,9 @@ void dynAlloc_exit(void) {
e = list_entry(list_unique_elements.next, struct element, node);
pr_info ("delete element %d: %s\n", e->unique_number, e->text);
list_del(&e->node);
kfree(e);
if (e != 0) {
kfree(e);
}
}
pr_info("Memory allocated for dynamic allocation and linked list freed\n");

View File

@@ -0,0 +1,42 @@
#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>
static struct task_struct* sample_thread;
#define DELAY_S 5
int thread_skeletonThread (void* data) {
pr_info("Thread started\n");
while (!kthread_should_stop()) {
pr_info("PING!\n");
ssleep(DELAY_S);
}
return 0;
}
void thread_init(void) {
pr_info("Initialize kernel thread\n");
sample_thread = kthread_run(thread_skeletonThread, NULL, "The Machine that goes");
if (IS_ERR(sample_thread)) {
pr_err("Failed to create kernel thread\n");
return;
}
pr_info("Kernel thread initialized\n");
}
void thread_exit(void) {
pr_info("Exiting kernel thread\n");
kthread_stop(sample_thread);
pr_info("Kernel thread exited\n");
}

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

@@ -6,6 +6,8 @@
#include "s02e02-parameters.c"
#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) {
@@ -13,17 +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();
pr_info("--------------------\n");
// Lab02 - Exercise 7: Sleeping
sleeping_init();
pr_info("--------------------\n");
@@ -33,14 +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();
pr_info("--------------------\n");
// Lab02 - Exercise 7: Sleeping
sleeping_exit();
pr_info("--------------------\n");