static struct task_struct *control = NULL;
static long call_ioctl(struct file *filp, unsigned int iocmd, unsigned long arg)
{
switch (iocmd)
{
case SETMODE:
/* get buffer data from userspace which is either 0 or 1 */
/* 0: Manual 1: Automatic*/
switch (buffer)
{
case MANUAL:
if (control)
{
kthread_stop(control);
control = NULL;
printk(KERN_ALERT "Switching to MANUAL disabling kernel thread for Automatic\n");
}
mode = MANUAL_MODE;
printk(KERN_ALERT "IN MANUAL \n");
break;
case AUTOMATIC:
if (automatic_fan_control() != 0)
{
printk(KERN_ALERT "Failed to set fan to AUTOMATIC!!! \n");
return -1;
}
break;
default:
printk(KERN_ALERT "Entered value is incorrect\n");
return -EINVAL;
}
break;
}
}
static inline int automatic_fan_control(void)
{
control = kthread_run(sense_cpu_temperature, NULL, "Temperature Thread");
if (control)
{
printk(KERN_ALERT "Kthread Created Successfully\n");
}
else
{
printk(KERN_ALERT "Failed to create kthread. \n");
control = NULL;
return -1;
}
return 0;
}
int temperature(void *arg)
{
while (!kthread_should_stop())
{
mutex_lock(&mutex);
get_temperature();
mutex_unlock(&mutex);
/* Process the temperature value */
msleep_interruptible(polling_interval);
}
return 0;
}
This the above code that i have written for a driver:
Let's look at the source of msleep_interruptible
:
unsigned long msleep_interruptible(unsigned int msecs)
{
unsigned long timeout = msecs_to_jiffies(msecs) + 1;
while (timeout && !signal_pending(current))
timeout = schedule_timeout_interruptible(timeout);
return jiffies_to_msecs(timeout);
}
schedule_timeout_interruptible
puts the asleep until the timeout expires, or a signal is delivered, or it is explicitly woken up. It returns the remaining time in jiffies. As can be seen above, msleep_interruptible
will go back to sleep if woken early and no signal is pending.
kthread_stop
wakes up the thread task explicitly, but does not send a signal, so msleep_interruptible
will run to completion, putting the thread task back to sleep if woken early.
In this case, a simple fix would be to replace this call in temperature
:
msleep_interruptible(polling_interval);
with the following call:
schedule_timeout_uninterruptible(msecs_to_jiffies(polling_interval) + 1);
Then, if woken up early, it won't go back to sleep.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.