I'm writing a kernel module for linux, and I want my timer to re-set itself. To this end, I thought to call mod_timer from inside the timer's callback function, as shown:
static void sched_send(unsigned long data)
{
send_now();
mod_timer(&test_timer, jiffies+(get_interval()*HZ));
}
static void timer_start(void)
{
set_log_msg("Meep meep!");
test_timer.function = sched_send;
test_timer.expires = jiffies + HZ*get_interval();
}
However, I've read mod_timer deletes the timer and re-adds it. Will it cause problems? If so, is there a better way to create a repeating timer for kernel modules?
It is safe to execute mod_timer from the timer callback.
From the kernel source (kernel/timer.c):
/* mod_timer(timer, expires) is equivalent to:
*
* del_timer(timer); timer->expires = expires; add_timer(timer);
* ...
*/
As for del_timer,
/*
* del_timer - deactive a timer.
* #timer: the timer to be deactivated
*
* del_timer() deactivates a timer - this works on both active and inactive
* timers.
* ...
*/
As noted by Peter, you need to invoke add_timer anytime you want to start/restart the timer.
Your function timer_start() will have to call add_timer() after it sets up the function and the expiration time. Once the timer function triggers, your timer is no longer active, so all you have to do is reset the .expires field to your new value and call add_timer() again. Be sure you provide a clean way to stop rescheduling the timer, for example on module unload.
send_now();
if(!terminate_timer) {
test_timer.expires = jiffies + HZ*get_interval();
add_timer(&test_timer);
}
Related
Is there a way to attach data to a coroutine, or at least to somehow identify different coroutines?
I am trying to implement a timer API where the timers are controlled by the host, that looks something like the following on the Lua side:
function callback()
local timer = ElapsedTimer()
...
end
function main()
local timer = CreateTimer(...)
StartTimer(timer, callback, ...)
end
The StartTimer() call sends the timer and callback to the C side, and the C side will eventually call the callback in a new coroutine.
The call to ElapsedTimer() needs to return data that is specific to this coroutine/thread, i.e. in this case the timer.
In pseudo code:
int StartTimer(lua_State* L) {
auto timer = ...;
auto coroutine = ???
coroutine.userdata = &timer; // But probably store an actual structure with more pointers
return 0;
}
int ElapsedTimer(lua_State* L) {
auto coroutine = ???
auto timer = (Timer*)coroutine.userdata;
lua_pushlightuserdata(L, timer)
return 1;
}
This is what userdata is for:
int StartTimer(lua_State* L) {
TimerStruct timer = (TimerStruct*)lua_newuserdata(L, sizeof(TimerStruct));
//allocates some memory and returns pointer to it
timer->//...
// lua_setuservalue will let you bind the callback to the timer
return 1; //actually return it
}
Also it is going to be easier to pass the timer along
function callback(timer)
...
end
That way the lua code doesn't need to query that value. It already got it.
I just now realized I need to use lua_newthread to create the coroutine, which means I have a separate lua_State object.
This means I can always create a mapping between the coroutine's state and whatever data I want in the host language (e.g. in a map data structure)
To clarify a question assume that we have:
Static Button object: static Button_T sButton = {0};
Function to get Button: void GetButton(Button_T * p_button); that is called from main loop context
ISR handler: void ButtonISRHandler(void);
Assumptions:
GetButton execution can be interrupted by any interrupt that does not execute ButtonISRHandler
ButtonISRHandler execution can be interrupted by other iterrupts
GetButton execution takes less time than the minimum time between two ButtonISRHandler interrupts call.
Button interrupt is a cyclic interrupt triggered for instance every 10 ms.
In ButtonISRHandler we have procedures like checking button PIN state or detecting if button is touched (in touch button case). If a given PIN state is stable in e.g. for 5 consequtive calls then sButton object state is updated.
Button_T is generic object - it could be classic tact switch or touch button etc.
ScanButtonAndUpdate could handle a list of Button_T objects but GetButton function operates only on the one button object.
The problem is: classic case when an interrupt can occur when program counter is inside GetButton
The question is: How to synchronize GetButton with ButtonISRHandler without disableing Interrupts?
My target processor is Cortex M0 without LDREX/STREX operation so I cannot use atomics from C11 that would be great solution in this case.
My Proposed Solution
Use Critical Section in GetButton.
If an interrupt occured when the program counter is inside Critical Section then do not handle ScanButtonAndUpdate in interrupt but handle it on ExitCriticalSection. Defer ScanButtonAndUpdate execution.
There is no possibility to call ScanButtonAndUpdate function from interrupt and main context in the same time - this behaviour is protected by semaphore
Implementation
#define SEMAPHORE_GIVEN 0
#define SEMAPHORE_TAKEN 1
typedef uint32_t BaseType_T;
typedef struct Button_T;
static volatile BaseType_T sSemaphore = SEMAPHORE_GIVEN;
static volatile bool sIsPendingISR = false;
static volatile Button_T sButton = {0};
void GetButton(Button_T * p_button)
{
EnterCriticalSection();
memcpy(p_button, &sButton, sizeof(Button_T))
/* Other procedures on sButton... */
ExitCriticalSection();
}
/* Cyclic executed handler */
void ButtonISRHandler(void)
{
if (!BinarySemaphoreTake()) {
SetISRPending();
}
else {
ScanButtonAndUpdate();
BinarySemaphoreGive();
}
}
void ScanButtonAndUpdate(void)
{
/* Scan for instance a current PIN state and update sButton object
if state is stable in next calls */
}
static void EnterCriticalSection(void)
{
while(false == BinarySemaphoreTake()) continue;
}
static void ExitCriticalSection(void)
{
BinarySemaphoreGive();
if (IsPendingISR()){
ScanButtonAndUpdate();
ResetISRPending();
}
}
static bool BinarySemaphoreTake(void)
{
if (SEMAPHORE_GIVEN == sSemaphore) {
/* Value Store operation is atomic on the architecture native type */
sSemaphore = SEMAPHORE_TAKEN;
return true;
}
else {
return false;
}
}
static void BinarySemaphoreGive(void)
{
sSemaphore = SEMAPHORE_GIVEN;
}
static void SetISRPending(void)
{
sIsPendingISR = true;
}
static void ResetISRPending(void)
{
sIsPendingISR = false;
}
static bool IsPendingISR(void)
{
return sIsPendingISR;
}
This solution was tested and works great without problems but I am not sure that this is the best solution without hidden bugs.
EDIT 1: Updated Assumptions and added missing ScanButtonAndUpdate function
There is a hidden synchronization which affects whether you have a race condition or not: what gates the Interrupt? The two most common scenarios are edge and level triggered; an edge trigger means that the interrupt will be inhibited until the device is cleared, whereas a level trigger means that the interrupt will repeatedly re-assert until the device is cleared.
If your code uses level triggered interrupts, then you have omitted this synchronization entirely, or you are pretending that sIsPendingISR is the mask & status flag. In that case, you look alright
If it is level triggered, then it can re-assert during /* Update sButton object */, causing the device handling code to be executing in two contexts (interrupt + normal). Most device code is not designed to do this.
Btw, there is a software protocol called “Dekkers Algorithm” which provides a general solution to mutual exclusion without hardware support. You have sort of integrated a version of it here.
I am writing a linux kernel module which schedules a task using schedule_delayed_work at a particular time which in turn send a signal to a user space program to do some task.
What I did is manually given the time in milliseconds (say 5000ms) and changed it to jiffies using "msec to jiffies" function and tested it and worked.
My use case is that the user will give a time (say 5 pm) and the module has to schedule it to send the signal everyday at 5 pm to the user program. I am totally confused in how to calculate the milliseconds from the user given time for everyday basis.
I used workqueue to create a queue and then the task to accomplish and doing the scheduling.
My kernel module:
static void wq_handler_function(struct work_struct *work);
static unsigned long delay;
static struct workqueue_struct *my_wq; // my workqueue
static DECLARE_DELAYED_WORK(my_work, wq_handler_function); //my work/task
static void wq_handler_function(struct work_struct *work)
{
printk(KERN_DEBUG "handler function called\n");
if(my_wq)
{
/*Do some work like sending signal to user space*/
schedule_delayed_work(&my_work, delay); /*reschedule after the first scheduled time finished*/
}
}
int sig_init_module(void)
{
printk(KERN_DEBUG "signal module initiated\n");
delay = msecs_to_jiffies(5000); //Manually given 5000ms (5 sec) for scheuling
if(!my_wq)
my_wq = create_workqueue("my_queue");
if(my_wq)
{
schedule_delayed_work(&my_work, delay); /*schedule for the first time while module initiates*/
}
return 0;
}
void sig_cleanup_module(void)
{
flush_scheduled_work();
cancel_delayed_work_sync(&my_work);
flush_workqueue(my_wq);
destroy_workqueue(my_wq);
printk(KERN_DEBUG "signal module removed\n");
}
module_init(sig_init_module);
module_exit(sig_cleanup_module);
Kindly help me to have a solution for this. Thanks in advance!!!.
I don't understand why kernel modification would be desirable or necessary. If you want something periodically done (e.g. log rotation), add it to cron. Another option would be to use timerfd.
use mktime() function in kernel code which takes the wall time as arguments and directly returns the jiffies value.
For info about mktime, see this http://www.makelinux.net/ldd3/chp-7-sect-2
Attempting to use mbed OS scheduler for a small project.
As mbed os is Asynchronous I need to avoid blocking code.
However the library for my wireless receiver uses a blocking line of:
while (!(wireless.isRxData()));
Is there an alternative way to do this that won't block all the code until a message is received?
static void listen(void) {
wireless.quickRxSetup(channel, addr1);
sprintf(ackData,"Ack data \r\n");
wireless.acknowledgeData(ackData, strlen(ackData), 1);
while (!(wireless.isRxData()));
len = wireless.getRxData(msg);
}
static void motor(void) {
pc.printf("Motor\n");
m.speed(1);
n.speed(1);
led1 = 1;
wait(0.5);
m.speed(0);
n.speed(0);
}
static void sendData() {
wireless.quickTxSetup(channel, addr1);
strcpy(accelData, "Robot");
wireless.transmitData(accelData ,strlen(accelData));
}
void app_start(int, char**) {
minar::Scheduler::postCallback(listen).period(minar::milliseconds(500)).tolerance(minar::milliseconds(1000));
minar::Scheduler::postCallback(motor).period(minar::milliseconds(500));
minar::Scheduler::postCallback(sendData).period(minar::milliseconds(500)).delay(minar::milliseconds(3000));
}
You should remove the while (!(wireless.isRxData())); loop in your listen function. Replace it with:
if (wireless.isRxData()) {
len = wireless.getRxData(msg);
// Process data
}
Then, you can process your data in that if statement, or you can call postCallback on another function that will do your processing.
Instead of looping until data is available, you'll want to poll for data. If RX data is not available, exit the function and set a timer to go off after a short interval. When the timer goes off, check for data again. Repeat until data is available. I'm not familiar with your OS so I can't offer any specific code. This may be as simple as adding a short "sleep" call inside the while loop, or may involve creating another callback from the scheduler.
So, the main loop of my game is based on a SDL_WaitEvent type, where it waits for the user to enter new letters while trying to discover a random word. My game need this to work properly but it looks like SDL_WaitEvent stays idle until user press something. The problem is I need my timer to continuosly refresh in order for the player to keep track of it, but when the game reaches the event loop, my timer stays idle and I am not able to find a away to keep it refreshing, any tips would be very appreciated.
Summarizing:
Timer starts: 59 (seconds)
.
.
.
It only will refresh and show the time elapsed when and IF I press something.
SDL_AddTimer() with a callback that uses SDL_PushEvent() to post a user message to the event queue:
/* Start the timer; the callback below will be executed after the delay */
Uint32 delay = (33 / 10) * 10; /* To round it down to the nearest 10 ms */
SDL_TimerID my_timer_id = SDL_AddTimer(delay, my_callbackfunc, my_callback_param);
...
Uint32 my_callbackfunc(Uint32 interval, void *param)
{
SDL_Event event;
SDL_UserEvent userevent;
/* In this example, our callback pushes an SDL_USEREVENT event
into the queue, and causes our callback to be called again at the
same interval: */
userevent.type = SDL_USEREVENT;
userevent.code = 0;
userevent.data1 = NULL;
userevent.data2 = NULL;
event.type = SDL_USEREVENT;
event.user = userevent;
SDL_PushEvent(&event);
return(interval);
}