mirror of
https://github.com/0xAX/linux-insides.git
synced 2024-12-22 22:58:08 +00:00
Merge pull request #672 from sjp38/sync_primitives_fix
Fix nits under SyncPrim/
This commit is contained in:
commit
d062df5113
@ -22,7 +22,7 @@ clocksource_select();
|
|||||||
mutex_unlock(&clocksource_mutex);
|
mutex_unlock(&clocksource_mutex);
|
||||||
```
|
```
|
||||||
|
|
||||||
from the [kernel/time/clocksource.c](https://github.com/torvalds/linux/master/kernel/time/clocksource.c) source code file. This code is from the `__clocksource_register_scale` function which adds the given [clocksource](https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-2.html) to the clock sources list. This function produces different operations on a list with registered clock sources. For example, the `clocksource_enqueue` function adds the given clock source to the list with registered clocksources - `clocksource_list`. Note that these lines of code wrapped to two functions: `mutex_lock` and `mutex_unlock` which takes one parameter - the `clocksource_mutex` in our case.
|
from the [kernel/time/clocksource.c](https://github.com/torvalds/linux/blob/master/kernel/time/clocksource.c) source code file. This code is from the `__clocksource_register_scale` function which adds the given [clocksource](https://0xax.gitbooks.io/linux-insides/content/Timers/linux-timers-2.html) to the clock sources list. This function produces different operations on a list with registered clock sources. For example, the `clocksource_enqueue` function adds the given clock source to the list with registered clocksources - `clocksource_list`. Note that these lines of code wrapped to two functions: `mutex_lock` and `mutex_unlock` which takes one parameter - the `clocksource_mutex` in our case.
|
||||||
|
|
||||||
These functions represent locking and unlocking based on [mutex](https://en.wikipedia.org/wiki/Mutual_exclusion) synchronization primitive. As `mutex_lock` will be executed, it allows us to prevent the situation when two or more threads will execute this code while the `mutex_unlock` will not be executed by process-owner of the mutex. In other words, we prevent parallel operations on a `clocksource_list`. Why do we need `mutex` here? What if two parallel processes will try to register a clock source. As we already know, the `clocksource_enqueue` function adds the given clock source to the `clocksource_list` list right after a clock source in the list which has the biggest rating (a registered clock source which has the highest frequency in the system):
|
These functions represent locking and unlocking based on [mutex](https://en.wikipedia.org/wiki/Mutual_exclusion) synchronization primitive. As `mutex_lock` will be executed, it allows us to prevent the situation when two or more threads will execute this code while the `mutex_unlock` will not be executed by process-owner of the mutex. In other words, we prevent parallel operations on a `clocksource_list`. Why do we need `mutex` here? What if two parallel processes will try to register a clock source. As we already know, the `clocksource_enqueue` function adds the given clock source to the `clocksource_list` list right after a clock source in the list which has the biggest rating (a registered clock source which has the highest frequency in the system):
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ typedef struct spinlock {
|
|||||||
} spinlock_t;
|
} spinlock_t;
|
||||||
```
|
```
|
||||||
|
|
||||||
and located in the [include/linux/spinlock_types.h](https://github.com/torvalds/linux/master/include/linux/spinlock_types.h) header file. We may see that its implementation depends on the state of the `CONFIG_DEBUG_LOCK_ALLOC` kernel configuration option. We will skip this now, because all debugging related stuff will be in the end of this part. So, if the `CONFIG_DEBUG_LOCK_ALLOC` kernel configuration option is disabled, the `spinlock_t` contains [union](https://en.wikipedia.org/wiki/Union_type#C.2FC.2B.2B) with one field which is - `raw_spinlock`:
|
and located in the [include/linux/spinlock_types.h](https://github.com/torvalds/linux/blob/master/include/linux/spinlock_types.h) header file. We may see that its implementation depends on the state of the `CONFIG_DEBUG_LOCK_ALLOC` kernel configuration option. We will skip this now, because all debugging related stuff will be in the end of this part. So, if the `CONFIG_DEBUG_LOCK_ALLOC` kernel configuration option is disabled, the `spinlock_t` contains [union](https://en.wikipedia.org/wiki/Union_type#C.2FC.2B.2B) with one field which is - `raw_spinlock`:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
typedef struct spinlock {
|
typedef struct spinlock {
|
||||||
@ -89,7 +89,7 @@ typedef struct spinlock {
|
|||||||
} spinlock_t;
|
} spinlock_t;
|
||||||
```
|
```
|
||||||
|
|
||||||
The `raw_spinlock` structure defined in the [same](https://github.com/torvalds/linux/master/include/linux/spinlock_types.h) header file represents the implementation of `normal` spinlock. Let's look how the `raw_spinlock` structure is defined:
|
The `raw_spinlock` structure defined in the [same](https://github.com/torvalds/linux/blob/master/include/linux/spinlock_types.h) header file represents the implementation of `normal` spinlock. Let's look how the `raw_spinlock` structure is defined:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
typedef struct raw_spinlock {
|
typedef struct raw_spinlock {
|
||||||
@ -104,7 +104,7 @@ typedef struct raw_spinlock {
|
|||||||
} raw_spinlock_t;
|
} raw_spinlock_t;
|
||||||
```
|
```
|
||||||
|
|
||||||
where the `arch_spinlock_t` represents architecture-specific `spinlock` implementation. As we mentioned above, we will skip debugging kernel configuration options. As we focus on [x86_64](https://en.wikipedia.org/wiki/X86-64) architecture in this book, the `arch_spinlock_t` that we will consider is defined in the [include/asm-generic/qspinlock_types.h](https://github.com/torvalds/linux/master/include/asm-generic/qspinlock_types.h) header file and looks:
|
where the `arch_spinlock_t` represents architecture-specific `spinlock` implementation. As we mentioned above, we will skip debugging kernel configuration options. As we focus on [x86_64](https://en.wikipedia.org/wiki/X86-64) architecture in this book, the `arch_spinlock_t` that we will consider is defined in the [include/asm-generic/qspinlock_types.h](https://github.com/torvalds/linux/blob/master/include/asm-generic/qspinlock_types.h) header file and looks:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
typedef struct qspinlock {
|
typedef struct qspinlock {
|
||||||
@ -122,18 +122,18 @@ typedef struct qspinlock {
|
|||||||
} arch_spinlock_t;
|
} arch_spinlock_t;
|
||||||
```
|
```
|
||||||
|
|
||||||
We will not stop on this structures for now. Let's look at the operations on a spinlock. The Linux kernel provides following main operations on a `spinlock`:
|
We will not stop on this structures for now. Let's look at the operations on a `spinlock`. The Linux kernel provides following main operations on a `spinlock`:
|
||||||
|
|
||||||
* `spin_lock_init` - produces initialization of the given `spinlock`;
|
* `spin_lock_init` - produces initialization of the given `spinlock`;
|
||||||
* `spin_lock` - acquires given `spinlock`;
|
* `spin_lock` - acquires given `spinlock`;
|
||||||
* `spin_lock_bh` - disables software [interrupts](https://en.wikipedia.org/wiki/Interrupt) and acquire given `spinlock`.
|
* `spin_lock_bh` - disables software [interrupts](https://en.wikipedia.org/wiki/Interrupt) and acquire given `spinlock`;
|
||||||
* `spin_lock_irqsave` and `spin_lock_irq` - disable interrupts on local processor and preserve/not preserve previous interrupt state in the `flags`;
|
* `spin_lock_irqsave` and `spin_lock_irq` - disable interrupts on local processor, preserve/not preserve previous interrupt state in the `flags` and acquire given `spinlock`;
|
||||||
* `spin_unlock` - releases given `spinlock`;
|
* `spin_unlock` - releases given `spinlock`;
|
||||||
* `spin_unlock_bh` - releases given `spinlock` and enables software interrupts;
|
* `spin_unlock_bh` - releases given `spinlock` and enables software interrupts;
|
||||||
* `spin_is_locked` - returns the state of the given `spinlock`;
|
* `spin_is_locked` - returns the state of the given `spinlock`;
|
||||||
* and etc.
|
* and etc.
|
||||||
|
|
||||||
Let's look on the implementation of the `spin_lock_init` macro. As I already wrote, this and other macro are defined in the [include/linux/spinlock.h](https://github.com/torvalds/linux/master/include/linux/spinlock.h) header file and the `spin_lock_init` macro looks:
|
Let's look on the implementation of the `spin_lock_init` macro. As I already wrote, this and other macro are defined in the [include/linux/spinlock.h](https://github.com/torvalds/linux/blob/master/include/linux/spinlock.h) header file and the `spin_lock_init` macro looks:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
#define spin_lock_init(_lock) \
|
#define spin_lock_init(_lock) \
|
||||||
@ -161,7 +161,7 @@ do { \
|
|||||||
} while (0) \
|
} while (0) \
|
||||||
```
|
```
|
||||||
|
|
||||||
assigns the value of the `__RAW_SPIN_LOCK_UNLOCKED` with the given `spinlock` to the given `raw_spinlock_t`. As we may understand from the name of the `__RAW_SPIN_LOCK_UNLOCKED` macro, this macro does initialization of the given `spinlock` and set it to `released` state. This macro is defined in the [include/linux/spinlock_types.h](https://github.com/torvalds/linux/master/include/linux/spinlock_types.h) header file and expands to the following macros:
|
assigns the value of the `__RAW_SPIN_LOCK_UNLOCKED` with the given `spinlock` to the given `raw_spinlock_t`. As we may understand from the name of the `__RAW_SPIN_LOCK_UNLOCKED` macro, this macro does initialization of the given `spinlock` and set it to `released` state. This macro is defined in the [include/linux/spinlock_types.h](https://github.com/torvalds/linux/blob/master/include/linux/spinlock_types.h) header file and expands to the following macros:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
#define __RAW_SPIN_LOCK_UNLOCKED(lockname) \
|
#define __RAW_SPIN_LOCK_UNLOCKED(lockname) \
|
||||||
@ -198,7 +198,7 @@ static __always_inline void spin_lock(spinlock_t *lock)
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
function which allows us to `acquire` a spinlock. The `raw_spin_lock` macro is defined in the same header file and expnads to the call of `_raw_spin_lock`:
|
function which allows us to `acquire` a `spinlock`. The `raw_spin_lock` macro is defined in the same header file and expands to the call of `_raw_spin_lock`:
|
||||||
|
|
||||||
```C
|
```C
|
||||||
#define raw_spin_lock(lock) _raw_spin_lock(lock)
|
#define raw_spin_lock(lock) _raw_spin_lock(lock)
|
||||||
|
@ -124,3 +124,4 @@ Thank you to all contributors:
|
|||||||
* [Dragonly](https://github.com/dragonly)
|
* [Dragonly](https://github.com/dragonly)
|
||||||
* [Blameying](https://github.com/Blameying)
|
* [Blameying](https://github.com/Blameying)
|
||||||
* [Junsoo Lee](https://github.com/junsooo)
|
* [Junsoo Lee](https://github.com/junsooo)
|
||||||
|
* [SeongJae Park](https://github.com/sjp38)
|
||||||
|
Loading…
Reference in New Issue
Block a user