Compare commits
3 Commits
02-KernelM
...
02-KernelM
| Author | SHA1 | Date | |
|---|---|---|---|
|
59b7caf82e
|
|||
|
b1a1d6af60
|
|||
|
d477abe506
|
@@ -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
|
||||
//-------------------
|
||||
|
||||
94
src/01-skeleton/s02e07-sleeping.c
Normal file
94
src/01-skeleton/s02e07-sleeping.c
Normal 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");
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user