Precautions for using spin locks:
①.
The critical area protected by the spin lock should be as short as possible
, so apply for the spin lock in
the open
function, and then in
the release
function
The method of releasing the spin lock in the number is not advisable. We can use a variable to represent the usage of the device, if the device is
If it is used, the variable will be incremented by one, and the variable will be decremented by one
after the device is released
. We only need to use
the spin lock to protect this variable
that is
Can.
②. Consider the compatibility of the driver and choose the API function
reasonably
.
To sum up, in this section of the routine, we define a variable
dev_stats
to indicate the usage of the device,
dev_stats
When it is
0
, it means that the device is not used, and
when
dev_stats
is greater than
0 , it means that the device is used.
In the driver
open
function first
Determine
whether
dev_stats is
0 , that is, determine whether the device is available, if it is 0 , use the device, and set dev_stats
Add
1
to indicate that the device is in use. After use,
decrement dev_stats by 1 in the
release
function
, indicating that the device is not used
up.
Therefore, it is the variable dev_stats
that actually realizes mutual exclusive access to the device
, but we need to use a spin lock to
protect
dev_stats
protect.
Device structure:
/* gpioled
device structure
*/
34
struct
gpioled_dev
{
35
dev_t devid
;
/*
device number
*/
36
struct
cdev cdev
;
/* cdev */
37
struct
class
*
class
;
/*
类
*/
38
struct
device
*
device
;
/*
device
*/
39
int
major
;
/*
Major device number
*/
40
int
minor
;
/*
minor device number
*/
41
struct
device_node
*
nd
;
/*
device node
*/
42
int
led_gpio
;
/*
GPIO number
used by led
*/
43
int
dev_stats
;
/*
Device status,
0
, the device is not used
; >0,
the device has been used
*/
44
spinlock_t lock
;
/*
spin lock
*/
45
};
open function:
spin_lock_irqsave
(&
gpioled
.
lock
,
flags
);
/*
上锁
*
/* Call
the spin_lock_irqsave
function to obtain
To take the lock, in order to consider the driver compatibility,
the spin_lock
function is not used to acquire the lock. */
if
(
gpioled
.
dev_stats
) {
/*
if the device is used
spin_unlock_irqrestore
(&
gpioled
.
lock
,
flags
);
/*
解锁
*/
return
-
EBUSY
;
}
gpioled
.
dev_stats
++;
/*
If the device is not open, then mark it is open
*/
spin_unlock_irqrestore
(&
gpioled
.
lock
,
flags
);
/*
unlock
*/ *
Determine whether dev_stats is greater than
0
, if yes, it means that the device has been used, then call
the spin_unlock_irqrestore function to release the lock, and return -EBUSY
. If the device is not in use,
add 1 to dev_stats on line
66
, indicating that the device is about to be used, and then call the spin_unlock_irqrestore function to release the lock. The job of the spin lock is to protect the dev_stats variable, and it is dev_stats that actually realizes mutual exclusive access to the device .
release
function:
/*
Decrease dev_stats by 1
when closing the driver file
*/
spin_lock_irqsave
(&
dev
->
lock
,
flags
);
/*
lock
*/
if
(
dev
->
dev_stats
)
{
dev
->
dev_stats
--;
}
spin_unlock_irqrestore
(&
dev
->
lock
,
flags
);
/*
unlock
*/
Decrease
dev_stats
by
1
, indicating that the device is released and can be used by other applications.
When decrementing
dev_stats
by 1
, a spin lock is required to protect it.
init
function:
/*
Initialize the spinlock
*/
spin_lock_init
(&
gpioled
.
lock
);