mirror of
https://github.com/bashrc/LKMPG.git
synced 2018-06-11 03:06:54 +02:00
Spinlocks
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
63
4.9.11/examples/example_spinlock.c
Normal file
63
4.9.11/examples/example_spinlock.c
Normal 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 |
Reference in New Issue
Block a user