From d9925d1aadb4f19f01c7271092e506446929ae62 Mon Sep 17 00:00:00 2001 From: Mara Date: Fri, 1 Apr 2022 08:58:21 +0300 Subject: [PATCH 1/6] lab05: Add empty skel Signed-off-by: Mara-Ioana Nicolae --- .../labs/skels/deferred_work/1-2-timer/Kbuild | 3 + .../skels/deferred_work/1-2-timer/timer.c | 46 +++++ .../3-4-5-deferred/include/deferred.h | 35 ++++ .../3-4-5-deferred/kernel/Kbuild | 3 + .../3-4-5-deferred/kernel/deferred.c | 189 ++++++++++++++++++ .../3-4-5-deferred/kernel/makenode | 9 + .../3-4-5-deferred/user/.gitignore | 1 + .../3-4-5-deferred/user/Makefile | 9 + .../deferred_work/3-4-5-deferred/user/test.c | 93 +++++++++ .../labs/skels/deferred_work/6-kthread/Kbuild | 3 + .../skels/deferred_work/6-kthread/kthread.c | 54 +++++ 11 files changed, 445 insertions(+) create mode 100644 tools/labs/skels/deferred_work/1-2-timer/Kbuild create mode 100644 tools/labs/skels/deferred_work/1-2-timer/timer.c create mode 100644 tools/labs/skels/deferred_work/3-4-5-deferred/include/deferred.h create mode 100644 tools/labs/skels/deferred_work/3-4-5-deferred/kernel/Kbuild create mode 100644 tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c create mode 100644 tools/labs/skels/deferred_work/3-4-5-deferred/kernel/makenode create mode 100644 tools/labs/skels/deferred_work/3-4-5-deferred/user/.gitignore create mode 100644 tools/labs/skels/deferred_work/3-4-5-deferred/user/Makefile create mode 100644 tools/labs/skels/deferred_work/3-4-5-deferred/user/test.c create mode 100644 tools/labs/skels/deferred_work/6-kthread/Kbuild create mode 100644 tools/labs/skels/deferred_work/6-kthread/kthread.c diff --git a/tools/labs/skels/deferred_work/1-2-timer/Kbuild b/tools/labs/skels/deferred_work/1-2-timer/Kbuild new file mode 100644 index 00000000000000..fa3cd3e263f84b --- /dev/null +++ b/tools/labs/skels/deferred_work/1-2-timer/Kbuild @@ -0,0 +1,3 @@ +ccflags-y = -Wno-unused-function -Wno-unused-label -Wno-unused-variable + +obj-m = timer.o diff --git a/tools/labs/skels/deferred_work/1-2-timer/timer.c b/tools/labs/skels/deferred_work/1-2-timer/timer.c new file mode 100644 index 00000000000000..f7b0d6578bbe3c --- /dev/null +++ b/tools/labs/skels/deferred_work/1-2-timer/timer.c @@ -0,0 +1,46 @@ +/* + * Deferred Work + * + * Exercise #1, #2: simple timer + */ + +#include +#include +#include +#include + +MODULE_DESCRIPTION("Simple kernel timer"); +MODULE_AUTHOR("SO2"); +MODULE_LICENSE("GPL"); + +#define TIMER_TIMEOUT 1 + +static struct timer_list timer; + +static void timer_handler(struct timer_list *tl) +{ + /* TODO 1: print a message */ + + /* TODO 2: rechedule timer */ +} + +static int __init timer_init(void) +{ + pr_info("[timer_init] Init module\n"); + + /* TODO 1: initialize timer */ + + /* TODO 1: schedule timer for the first time */ + + return 0; +} + +static void __exit timer_exit(void) +{ + pr_info("[timer_exit] Exit module\n"); + + /* TODO 1: cleanup; make sure the timer is not running after we exit */ +} + +module_init(timer_init); +module_exit(timer_exit); diff --git a/tools/labs/skels/deferred_work/3-4-5-deferred/include/deferred.h b/tools/labs/skels/deferred_work/3-4-5-deferred/include/deferred.h new file mode 100644 index 00000000000000..f9408c704401ad --- /dev/null +++ b/tools/labs/skels/deferred_work/3-4-5-deferred/include/deferred.h @@ -0,0 +1,35 @@ +/* + * SO2 - Lab 6 - Deferred Work + * + * Exercises #3, #4, #5: deferred work + * + * Header file. + */ + +#ifndef __DEFERRED_H__ +#define __DEFERRED_H__ + +#include + +#define MY_IOCTL_TIMER_SET _IOW('k', 1, unsigned long) +#define MY_IOCTL_TIMER_CANCEL _IO ('k', 2) +#define MY_IOCTL_TIMER_ALLOC _IOW('k', 3, unsigned long) +#define MY_IOCTL_TIMER_MON _IO ('k', 4) + +/* converts ioctl command code to message */ +inline static char *ioctl_command_to_string(int cmd) +{ + switch(cmd) { + case MY_IOCTL_TIMER_SET: + return "Set timer"; + case MY_IOCTL_TIMER_CANCEL: + return "Cancel timer"; + case MY_IOCTL_TIMER_ALLOC: + return "Allocate memory"; + case MY_IOCTL_TIMER_MON: + return "Monitor pid"; + } + return "Unknown command"; +} + +#endif /* __DEFERRED_H__ */ diff --git a/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/Kbuild b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/Kbuild new file mode 100644 index 00000000000000..fa3f727c8a53d2 --- /dev/null +++ b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/Kbuild @@ -0,0 +1,3 @@ +ccflags-y = -Wno-unused-function -Wno-unused-label -Wno-unused-variable + +obj-m = deferred.o diff --git a/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c new file mode 100644 index 00000000000000..48fdd4cfd43f37 --- /dev/null +++ b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c @@ -0,0 +1,189 @@ +/* + * SO2 - Lab 6 - Deferred Work + * + * Exercises #3, #4, #5: deferred work + * + * Code skeleton. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/deferred.h" + +#define MY_MAJOR 42 +#define MY_MINOR 0 +#define MODULE_NAME "deferred" + +#define TIMER_TYPE_NONE -1 +#define TIMER_TYPE_SET 0 +#define TIMER_TYPE_ALLOC 1 +#define TIMER_TYPE_MON 2 + +MODULE_DESCRIPTION("Deferred work character device"); +MODULE_AUTHOR("SO2"); +MODULE_LICENSE("GPL"); + +struct mon_proc { + struct task_struct *task; + struct list_head list; +}; + +static struct my_device_data { + struct cdev cdev; + /* TODO 1: add timer */ + /* TODO 2: add flag */ + /* TODO 3: add work */ + /* TODO 4: add list for monitored processes */ + /* TODO 4: add spinlock to protect list */ +} dev; + +static void alloc_io(void) +{ + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(5 * HZ); + pr_info("Yawn! I've been sleeping for 5 seconds.\n"); +} + +static struct mon_proc *get_proc(pid_t pid) +{ + struct task_struct *task; + struct mon_proc *p; + + rcu_read_lock(); + task = pid_task(find_vpid(pid), PIDTYPE_PID); + rcu_read_unlock(); + if (!task) + return ERR_PTR(-ESRCH); + + p = kmalloc(sizeof(*p), GFP_ATOMIC); + if (!p) + return ERR_PTR(-ENOMEM); + + get_task_struct(task); + p->task = task; + + return p; +} + + +/* TODO 3: define work handler */ + +#define ALLOC_IO_DIRECT +/* TODO 3: undef ALLOC_IO_DIRECT*/ + +static void timer_handler(struct timer_list *tl) +{ + /* TODO 1: implement timer handler */ + /* TODO 2: check flags: TIMER_TYPE_SET or TIMER_TYPE_ALLOC */ + /* TODO 3: schedule work */ + /* TODO 4: iterate the list and check the proccess state */ + /* TODO 4: if task is dead print info ... */ + /* TODO 4: ... decrement task usage counter ... */ + /* TODO 4: ... remove it from the list ... */ + /* TODO 4: ... free the struct mon_proc */ +} + +static int deferred_open(struct inode *inode, struct file *file) +{ + struct my_device_data *my_data = + container_of(inode->i_cdev, struct my_device_data, cdev); + file->private_data = my_data; + pr_info("[deferred_open] Device opened\n"); + return 0; +} + +static int deferred_release(struct inode *inode, struct file *file) +{ + pr_info("[deferred_release] Device released\n"); + return 0; +} + +static long deferred_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct my_device_data *my_data = (struct my_device_data*) file->private_data; + + pr_info("[deferred_ioctl] Command: %s\n", ioctl_command_to_string(cmd)); + + switch (cmd) { + case MY_IOCTL_TIMER_SET: + /* TODO 2: set flag */ + /* TODO 1: schedule timer */ + break; + case MY_IOCTL_TIMER_CANCEL: + /* TODO 1: cancel timer */ + break; + case MY_IOCTL_TIMER_ALLOC: + /* TODO 2: set flag and schedule timer */ + break; + case MY_IOCTL_TIMER_MON: + { + /* TODO 4: use get_proc() and add task to list */ + /* TODO 4: protect access to list */ + + /* TODO 4: set flag and schedule timer */ + break; + } + default: + return -ENOTTY; + } + return 0; +} + +struct file_operations my_fops = { + .owner = THIS_MODULE, + .open = deferred_open, + .release = deferred_release, + .unlocked_ioctl = deferred_ioctl, +}; + +static int deferred_init(void) +{ + int err; + + pr_info("[deferred_init] Init module\n"); + err = register_chrdev_region(MKDEV(MY_MAJOR, MY_MINOR), 1, MODULE_NAME); + if (err) { + pr_info("[deffered_init] register_chrdev_region: %d\n", err); + return err; + } + + /* TODO 2: Initialize flag. */ + /* TODO 3: Initialize work. */ + + /* TODO 4: Initialize lock and list. */ + + cdev_init(&dev.cdev, &my_fops); + cdev_add(&dev.cdev, MKDEV(MY_MAJOR, MY_MINOR), 1); + + /* TODO 1: Initialize timer. */ + + return 0; +} + +static void deferred_exit(void) +{ + struct mon_proc *p, *n; + + pr_info("[deferred_exit] Exit module\n" ); + + cdev_del(&dev.cdev); + unregister_chrdev_region(MKDEV(MY_MAJOR, MY_MINOR), 1); + + /* TODO 1: Cleanup: make sure the timer is not running after exiting. */ + /* TODO 3: Cleanup: make sure the work handler is not scheduled. */ + + /* TODO 4: Cleanup the monitered process list */ + /* TODO 4: ... decrement task usage counter ... */ + /* TODO 4: ... remove it from the list ... */ + /* TODO 4: ... free the struct mon_proc */ +} + +module_init(deferred_init); +module_exit(deferred_exit); diff --git a/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/makenode b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/makenode new file mode 100644 index 00000000000000..1e46669d4a1c98 --- /dev/null +++ b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/makenode @@ -0,0 +1,9 @@ +#!/bin/sh + +device=deferred +type=c +major=42 +minor=0 + +rm -f /dev/${device} +mknod /dev/${device} $type $major $minor && ls -al /dev/${device} diff --git a/tools/labs/skels/deferred_work/3-4-5-deferred/user/.gitignore b/tools/labs/skels/deferred_work/3-4-5-deferred/user/.gitignore new file mode 100644 index 00000000000000..ee4c92682341e4 --- /dev/null +++ b/tools/labs/skels/deferred_work/3-4-5-deferred/user/.gitignore @@ -0,0 +1 @@ +/test diff --git a/tools/labs/skels/deferred_work/3-4-5-deferred/user/Makefile b/tools/labs/skels/deferred_work/3-4-5-deferred/user/Makefile new file mode 100644 index 00000000000000..62768622c42fee --- /dev/null +++ b/tools/labs/skels/deferred_work/3-4-5-deferred/user/Makefile @@ -0,0 +1,9 @@ +CFLAGS=-Wall -m32 +LDFLAGS=-static -m32 + +test: test.o + +.PHONY: clean + +clean: + -rm -f *~ *.o test diff --git a/tools/labs/skels/deferred_work/3-4-5-deferred/user/test.c b/tools/labs/skels/deferred_work/3-4-5-deferred/user/test.c new file mode 100644 index 00000000000000..3cef70f86e2b75 --- /dev/null +++ b/tools/labs/skels/deferred_work/3-4-5-deferred/user/test.c @@ -0,0 +1,93 @@ +/* + * SO2 - Lab 6 - Deferred Work + * + * Exercises #3, #4, #5: deferred work + * + * User-mode test program. + */ + +#include +#include +#include +#include +#include +#include +#include "../include/deferred.h" + +#define DEVICE_PATH "/dev/deferred" + +/* prints error message and exits */ +void error(char *message) +{ + perror(message); + exit(EXIT_FAILURE); +} + +/* prints usage message and exits */ +void usage() +{ + printf("Usage: test \n options:\n" + "\ts - set timer to run after seconds\n" + "\tc - cancel timer\n" + "\ta - allocate memory after seconds\n" + "\tp - monitor pid\n" + "\n"); + exit(1); +} + +#define BUFFER_LEN 128 + +int main(int argc, char **argv) +{ + int fd; + unsigned long seconds, pid; + + if (argc < 2) + usage(); + + fd = open(DEVICE_PATH, O_RDONLY); + if (fd < 0) + error(DEVICE_PATH); + + switch (argv[1][0]) { + case 's': + /* Set timer. */ + if (argc < 3) + usage(); + seconds = atoi(argv[2]); + printf("Set timer to %ld seconds\n", seconds); + if (ioctl(fd, MY_IOCTL_TIMER_SET, seconds) < 0) + error("ioctl set timer error"); + break; + case 'c': + /* Cancel timer. */ + printf("Cancel timer\n"); + if (ioctl(fd, MY_IOCTL_TIMER_CANCEL) < 0) + error("ioctl cancel timer error"); + break; + case 'a': + /* Allocate memory. */ + if (argc < 3) + usage(); + seconds = atoi(argv[2]); + printf("Allocate memory after %ld seconds\n",seconds); + if (ioctl(fd, MY_IOCTL_TIMER_ALLOC, seconds) < 0) + error("ioctl allocate memory error"); + break; + case 'p': + /* Monitor pid. */ + if (argc < 3) + usage(); + pid = atoi(argv[2]); + printf("Monitor PID %lu.\n", pid); + if (ioctl(fd, MY_IOCTL_TIMER_MON, pid) < 0) + error("ioctl monitor pid error"); + break; + default: + error("Wrong parameter"); + } + + close(fd); + + return 0; +} diff --git a/tools/labs/skels/deferred_work/6-kthread/Kbuild b/tools/labs/skels/deferred_work/6-kthread/Kbuild new file mode 100644 index 00000000000000..028c060071dd8c --- /dev/null +++ b/tools/labs/skels/deferred_work/6-kthread/Kbuild @@ -0,0 +1,3 @@ +ccflags-y = -Wno-unused-function -Wno-unused-label -Wno-unused-variable + +obj-m = kthread.o diff --git a/tools/labs/skels/deferred_work/6-kthread/kthread.c b/tools/labs/skels/deferred_work/6-kthread/kthread.c new file mode 100644 index 00000000000000..ad1770211be519 --- /dev/null +++ b/tools/labs/skels/deferred_work/6-kthread/kthread.c @@ -0,0 +1,54 @@ +/* + * SO2 - Lab 6 - Deferred Work + * + * Exercise #6: kernel thread + */ + +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("Simple kernel thread"); +MODULE_AUTHOR("SO2"); +MODULE_LICENSE("GPL"); + +wait_queue_head_t wq_stop_thread; +atomic_t flag_stop_thread; +wait_queue_head_t wq_thread_terminated; +atomic_t flag_thread_terminated; + + +int my_thread_f(void *data) +{ + pr_info("[my_thread_f] Current process id is %d (%s)\n", + current->pid, current->comm); + /* TODO: Wait for command to remove module on wq_stop_thread queue. */ + + /* TODO: set flag to mark kernel thread termination */ + /* TODO: notify the unload process that we have exited */ + pr_info("[my_thread_f] Exiting\n"); + do_exit(0); +} + +static int __init kthread_init(void) +{ + pr_info("[kthread_init] Init module\n"); + + /* TODO: init the waitqueues and flags */ + /* TODO: create and start the kernel thread */ + + return 0; +} + +static void __exit kthread_exit(void) +{ + /* TODO: notify the kernel thread that its time to exit */ + /* TODO: wait for the kernel thread to exit */ + pr_info("[kthread_exit] Exit module\n"); +} + +module_init(kthread_init); +module_exit(kthread_exit); From a8cf778f4441f6bd47dd235d3633d49246d3a249 Mon Sep 17 00:00:00 2001 From: Mara Date: Sat, 2 Apr 2022 23:14:21 +0300 Subject: [PATCH 2/6] lab05: Add solution for exercises 1 and 2 Signed-off-by: Mara --- tools/labs/skels/deferred_work/1-2-timer/timer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/labs/skels/deferred_work/1-2-timer/timer.c b/tools/labs/skels/deferred_work/1-2-timer/timer.c index f7b0d6578bbe3c..7d386cb2698327 100644 --- a/tools/labs/skels/deferred_work/1-2-timer/timer.c +++ b/tools/labs/skels/deferred_work/1-2-timer/timer.c @@ -20,8 +20,10 @@ static struct timer_list timer; static void timer_handler(struct timer_list *tl) { /* TODO 1: print a message */ + pr_info("Hello timer!\n"); /* TODO 2: rechedule timer */ + mod_timer(&timer, jiffies + TIMER_TIMEOUT * HZ); } static int __init timer_init(void) @@ -29,9 +31,10 @@ static int __init timer_init(void) pr_info("[timer_init] Init module\n"); /* TODO 1: initialize timer */ + timer_setup(&timer, timer_handler, 0); /* TODO 1: schedule timer for the first time */ - + mod_timer(&timer, jiffies + TIMER_TIMEOUT * HZ); return 0; } @@ -40,6 +43,7 @@ static void __exit timer_exit(void) pr_info("[timer_exit] Exit module\n"); /* TODO 1: cleanup; make sure the timer is not running after we exit */ + del_timer_sync(&timer); } module_init(timer_init); From 27e11e80265969e9b93dd3cd224cbf883e45c4fa Mon Sep 17 00:00:00 2001 From: Mara Date: Sat, 2 Apr 2022 23:31:03 +0300 Subject: [PATCH 3/6] lab05: Add solution for ex 3 and 4 Signed-off-by: Mara --- .../3-4-5-deferred/kernel/deferred.c | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c index 48fdd4cfd43f37..3a85daea59987d 100644 --- a/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c +++ b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c @@ -38,7 +38,10 @@ struct mon_proc { static struct my_device_data { struct cdev cdev; /* TODO 1: add timer */ + struct timer_list timer; + bool already_deleted_timer; /* TODO 2: add flag */ + bool use_blocking_op; /* TODO 3: add work */ /* TODO 4: add list for monitored processes */ /* TODO 4: add spinlock to protect list */ @@ -82,6 +85,14 @@ static void timer_handler(struct timer_list *tl) { /* TODO 1: implement timer handler */ /* TODO 2: check flags: TIMER_TYPE_SET or TIMER_TYPE_ALLOC */ + + if (!dev.use_blocking_op) { + struct task_struct *p = current; + pr_info("Comm: %s\n", p->comm); + pr_info("PID: %d\n", p->pid); + } else { + alloc_io(); + } /* TODO 3: schedule work */ /* TODO 4: iterate the list and check the proccess state */ /* TODO 4: if task is dead print info ... */ @@ -114,13 +125,21 @@ static long deferred_ioctl(struct file *file, unsigned int cmd, unsigned long ar switch (cmd) { case MY_IOCTL_TIMER_SET: /* TODO 2: set flag */ + my_data->use_blocking_op = false; /* TODO 1: schedule timer */ + mod_timer(&my_data->timer, jiffies + arg * HZ); + my_data->already_deleted_timer = false; break; case MY_IOCTL_TIMER_CANCEL: /* TODO 1: cancel timer */ + del_timer_sync(&my_data->timer); + my_data->already_deleted_timer = true; break; case MY_IOCTL_TIMER_ALLOC: /* TODO 2: set flag and schedule timer */ + my_data->use_blocking_op = true; + pr_info("ioctl: %d\n", my_data->use_blocking_op); + mod_timer(&my_data->timer, jiffies + arg * HZ); break; case MY_IOCTL_TIMER_MON: { @@ -155,6 +174,7 @@ static int deferred_init(void) } /* TODO 2: Initialize flag. */ + dev.use_blocking_op = false; /* TODO 3: Initialize work. */ /* TODO 4: Initialize lock and list. */ @@ -163,7 +183,8 @@ static int deferred_init(void) cdev_add(&dev.cdev, MKDEV(MY_MAJOR, MY_MINOR), 1); /* TODO 1: Initialize timer. */ - + timer_setup(&dev.timer, timer_handler, 0); + dev.already_deleted_timer = false; return 0; } @@ -177,6 +198,11 @@ static void deferred_exit(void) unregister_chrdev_region(MKDEV(MY_MAJOR, MY_MINOR), 1); /* TODO 1: Cleanup: make sure the timer is not running after exiting. */ + if (!dev.already_deleted_timer) { + del_timer_sync(&dev.timer); + dev.already_deleted_timer = true; + } + /* TODO 3: Cleanup: make sure the work handler is not scheduled. */ /* TODO 4: Cleanup the monitered process list */ From e035073fe33d9eb14348598d63c74e414840e2c1 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 3 Apr 2022 00:10:56 +0300 Subject: [PATCH 4/6] lab05: Solution for ex 3, 4, 5 Signed-off-by: Mara --- .../3-4-5-deferred/kernel/deferred.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c index 3a85daea59987d..3f7628dda13c4a 100644 --- a/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c +++ b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c @@ -43,6 +43,7 @@ static struct my_device_data { /* TODO 2: add flag */ bool use_blocking_op; /* TODO 3: add work */ + struct work_struct my_work; /* TODO 4: add list for monitored processes */ /* TODO 4: add spinlock to protect list */ } dev; @@ -77,23 +78,28 @@ static struct mon_proc *get_proc(pid_t pid) /* TODO 3: define work handler */ +static void my_work_handler(struct work_struct * work) +{ + alloc_io(); +} #define ALLOC_IO_DIRECT /* TODO 3: undef ALLOC_IO_DIRECT*/ +#undef ALLOC_IO_DIRECT static void timer_handler(struct timer_list *tl) { /* TODO 1: implement timer handler */ /* TODO 2: check flags: TIMER_TYPE_SET or TIMER_TYPE_ALLOC */ - if (!dev.use_blocking_op) { struct task_struct *p = current; pr_info("Comm: %s\n", p->comm); pr_info("PID: %d\n", p->pid); } else { - alloc_io(); - } /* TODO 3: schedule work */ + schedule_work(&dev.my_work); + } + /* TODO 4: iterate the list and check the proccess state */ /* TODO 4: if task is dead print info ... */ /* TODO 4: ... decrement task usage counter ... */ @@ -176,6 +182,7 @@ static int deferred_init(void) /* TODO 2: Initialize flag. */ dev.use_blocking_op = false; /* TODO 3: Initialize work. */ + INIT_WORK(&dev.my_work, my_work_handler); /* TODO 4: Initialize lock and list. */ @@ -204,7 +211,7 @@ static void deferred_exit(void) } /* TODO 3: Cleanup: make sure the work handler is not scheduled. */ - + flush_scheduled_work(); /* TODO 4: Cleanup the monitered process list */ /* TODO 4: ... decrement task usage counter ... */ /* TODO 4: ... remove it from the list ... */ From b8d13c59dcf1058b80e1e02845580c2729d16fe8 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 3 Apr 2022 01:29:04 +0300 Subject: [PATCH 5/6] lab05: Add solution for task 6 Signed-off-by: Mara --- tools/labs/skels/deferred_work/6-kthread/kthread.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/labs/skels/deferred_work/6-kthread/kthread.c b/tools/labs/skels/deferred_work/6-kthread/kthread.c index ad1770211be519..eaea6ccb2ecbe0 100644 --- a/tools/labs/skels/deferred_work/6-kthread/kthread.c +++ b/tools/labs/skels/deferred_work/6-kthread/kthread.c @@ -26,9 +26,13 @@ int my_thread_f(void *data) pr_info("[my_thread_f] Current process id is %d (%s)\n", current->pid, current->comm); /* TODO: Wait for command to remove module on wq_stop_thread queue. */ + wait_event_interruptible(wq_stop_thread, atomic_read(&flag_stop_thread) != 0); /* TODO: set flag to mark kernel thread termination */ + atomic_set(&flag_thread_terminated, 1); /* TODO: notify the unload process that we have exited */ + wake_up_interruptible(&wq_thread_terminated); + pr_info("[my_thread_f] Exiting\n"); do_exit(0); } @@ -39,7 +43,10 @@ static int __init kthread_init(void) /* TODO: init the waitqueues and flags */ /* TODO: create and start the kernel thread */ + struct task_struct *p = current; + kthread_create(my_thread_f, NULL, "%skthread%d", "my", 0); + int wake_up_process(p); return 0; } From 65c243facbffe2a990a9e57ef76c6aa8fb4c236d Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 3 Apr 2022 01:29:36 +0300 Subject: [PATCH 6/6] lab05: Add solution for ex 7 Signed-off-by: Mara --- .../3-4-5-deferred/kernel/deferred.c | 62 +++++++++++++++---- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c index 3f7628dda13c4a..b7844c6690aea1 100644 --- a/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c +++ b/tools/labs/skels/deferred_work/3-4-5-deferred/kernel/deferred.c @@ -45,7 +45,10 @@ static struct my_device_data { /* TODO 3: add work */ struct work_struct my_work; /* TODO 4: add list for monitored processes */ + struct list_head list; /* TODO 4: add spinlock to protect list */ + spinlock_t lock; + bool flag; } dev; static void alloc_io(void) @@ -90,21 +93,35 @@ static void my_work_handler(struct work_struct * work) static void timer_handler(struct timer_list *tl) { /* TODO 1: implement timer handler */ - /* TODO 2: check flags: TIMER_TYPE_SET or TIMER_TYPE_ALLOC */ - if (!dev.use_blocking_op) { - struct task_struct *p = current; - pr_info("Comm: %s\n", p->comm); - pr_info("PID: %d\n", p->pid); + if (!dev.flag) { + /* TODO 2: check flags: TIMER_TYPE_SET or TIMER_TYPE_ALLOC */ + if (!dev.use_blocking_op) { + struct task_struct *p = current; + pr_info("Comm: %s\n", p->comm); + pr_info("PID: %d\n", p->pid); + } else { + /* TODO 3: schedule work */ + schedule_work(&dev.my_work); + } } else { - /* TODO 3: schedule work */ - schedule_work(&dev.my_work); - } - /* TODO 4: iterate the list and check the proccess state */ - /* TODO 4: if task is dead print info ... */ - /* TODO 4: ... decrement task usage counter ... */ - /* TODO 4: ... remove it from the list ... */ - /* TODO 4: ... free the struct mon_proc */ + struct mon_proc *p, *n; + spin_lock(&dev.lock); + list_for_each_entry_safe(p, n, &dev.list, list) { + // /* TODO 4: if task is dead print info ... */ + // /* TODO 4: ... decrement task usage counter ... */ + // /* TODO 4: ... remove it from the list ... */ + // /* TODO 4: ... free the struct mon_proc */ + if (p->task->state == TASK_DEAD) { + pr_info("Delete proc from list %d\n", p->task->pid); + put_task_struct(p->task); + list_del(&p->list); + kfree(p); + } + } + spin_unlock(&dev.lock); + mod_timer(&dev.timer, jiffies + HZ); + } } static int deferred_open(struct inode *inode, struct file *file) @@ -150,9 +167,18 @@ static long deferred_ioctl(struct file *file, unsigned int cmd, unsigned long ar case MY_IOCTL_TIMER_MON: { /* TODO 4: use get_proc() and add task to list */ + struct mon_proc *p = get_proc(arg); + /* TODO 4: protect access to list */ + spin_lock_bh(&my_data->lock); + if (p) { + list_add(&p->list, &my_data->list); + } + spin_unlock_bh(&my_data->lock); /* TODO 4: set flag and schedule timer */ + my_data->flag = true; + mod_timer(&my_data->timer, jiffies + HZ); break; } default: @@ -181,10 +207,13 @@ static int deferred_init(void) /* TODO 2: Initialize flag. */ dev.use_blocking_op = false; + dev.flag = false; /* TODO 3: Initialize work. */ INIT_WORK(&dev.my_work, my_work_handler); /* TODO 4: Initialize lock and list. */ + spin_lock_init(&dev.lock); + INIT_LIST_HEAD(&dev.list); cdev_init(&dev.cdev, &my_fops); cdev_add(&dev.cdev, MKDEV(MY_MAJOR, MY_MINOR), 1); @@ -213,9 +242,16 @@ static void deferred_exit(void) /* TODO 3: Cleanup: make sure the work handler is not scheduled. */ flush_scheduled_work(); /* TODO 4: Cleanup the monitered process list */ + spin_lock(&dev.lock); + list_for_each_entry_safe(p, n, &dev.list, list) { /* TODO 4: ... decrement task usage counter ... */ /* TODO 4: ... remove it from the list ... */ /* TODO 4: ... free the struct mon_proc */ + put_task_struct(p->task); + list_del(&p->list); + kfree(p); + } + spin_unlock(&dev.lock); } module_init(deferred_init);