1
0
mirror of https://github.com/bashrc/LKMPG.git synced 2018-06-11 03:06:54 +02:00

Spinlocks

This commit is contained in:
Bob Mottram
2017-03-30 23:13:40 +01:00
parent 1a5c5029e0
commit a90589dbf3
5 changed files with 487 additions and 257 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -2670,6 +2670,79 @@ So even though /flywheel_thread/ is started first you should notice if you load
There are other variations upon the /wait_for_completion/ function, which include timeouts or being interrupted, but this basic mechanism is enough for many common situations without adding a lot of complexity.
** Avoiding Deadlock
If processes running on different CPUs or in different threads try to access the same memory then it's possible that strange things can happen or your system can lock up. To avoid this various types of mutual exclusion kernel functions are possible. These indicate if a section of code is "locked" or "unlocked" so that simultaneous attempts to run it can't happen.
*** Spinlocks
As the name suggests, spinlocks lock up the CPU that the code is running on, taking 100% of its resources. Because of this you sould only use the spinlock mechanism around code which is likely to take no more than a few milliseconds to run and so won't noticably slow anything down from the user's point of view.
The example here is /"irq safe"/ in that if interrupts happen during the lock then they won't be forgotten and will activate when the unlock happens, using the /flags/ variable to retain their state.
#+begin_src C file:example_spinlock.c
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
DEFINE_SPINLOCK(sl_static);
spinlock_t sl_dynamic;
static void example_spinlock_static(void)
{
unsigned long flags;
spin_lock_irqsave(&sl_static, flags);
printk("Locked static spinlock\n");
/* Do something or other safely.
Because this uses 100% CPU time this
code should take no more than a few
milliseconds to run */
spin_unlock_irqrestore(&sl_static, flags);
printk("Unlocked static spinlock\n");
}
static void example_spinlock_dynamic(void)
{
unsigned long flags;
spin_lock_init(&sl_dynamic);
spin_lock_irqsave(&sl_dynamic, flags);
printk("Locked dynamic spinlock\n");
/* Do something or other safely.
Because this uses 100% CPU time this
code should take no more than a few
milliseconds to run */
spin_unlock_irqrestore(&sl_dynamic, flags);
printk("Unlocked dynamic spinlock\n");
}
static int example_spinlock_init(void)
{
printk("example spinlock started\n");
example_spinlock_static();
example_spinlock_dynamic();
return 0;
}
static void example_spinlock_exit(void)
{
printk("example spinlock exit\n");
}
module_init(example_spinlock_init);
module_exit(example_spinlock_exit);
MODULE_AUTHOR("Bob Mottram");
MODULE_DESCRIPTION("Spinlock example");
MODULE_LICENSE("GPL");
#+end_src
* Replacing Printks
** Replacing printk
In Section 1.2.1.2, I said that X and kernel module programming don't mix. That's true for developing kernel modules, but in actual use, you want to be able to send messages to whichever tty[fn:15] the command to load the module came from.

View File

@@ -23,6 +23,7 @@ obj-m += cryptoapi.o
obj-m += completions.o
obj-m += example_tasklet.o
obj-m += devicemodel.o
obj-m += example_spinlock.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

View File

@@ -0,0 +1,63 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
DEFINE_SPINLOCK(sl_static);
spinlock_t sl_dynamic;
static void example_spinlock_static(void)
{
unsigned long flags;
spin_lock_irqsave(&sl_static, flags);
printk("Locked static spinlock\n");
/* Do something or other safely.
Because this uses 100% CPU time this
code should take no more than a few
milliseconds to run */
spin_unlock_irqrestore(&sl_static, flags);
printk("Unlocked static spinlock\n");
}
static void example_spinlock_dynamic(void)
{
unsigned long flags;
spin_lock_init(&sl_dynamic);
spin_lock_irqsave(&sl_dynamic, flags);
printk("Locked dynamic spinlock\n");
/* Do something or other safely.
Because this uses 100% CPU time this
code should take no more than a few
milliseconds to run */
spin_unlock_irqrestore(&sl_dynamic, flags);
printk("Unlocked dynamic spinlock\n");
}
static int example_spinlock_init(void)
{
printk("example spinlock started\n");
example_spinlock_static();
example_spinlock_dynamic();
return 0;
}
static void example_spinlock_exit(void)
{
printk("example spinlock exit\n");
}
module_init(example_spinlock_init);
module_exit(example_spinlock_exit);
MODULE_AUTHOR("Bob Mottram");
MODULE_DESCRIPTION("Spinlock example");
MODULE_LICENSE("GPL");

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB