1
0
Fork 0
forked from len0rd/rockbox

kernel: Break out kernel primitives into separate files and move to separate dir.

No code changed, just shuffling stuff around. This should make it easier to
build only select parts kernel and use different implementations.

Change-Id: Ie1f00f93008833ce38419d760afd70062c5e22b5
This commit is contained in:
Thomas Martitz 2013-12-04 17:06:17 +01:00
parent 8bae5f2644
commit 382d1861af
30 changed files with 1564 additions and 756 deletions

97
firmware/kernel/timeout.c Normal file
View file

@ -0,0 +1,97 @@
/****************************************************************************
* Tick-based interval timers/one-shots - be mindful this is not really
* intended for continuous timers but for events that need to run for a short
* time and be cancelled without further software intervention.
****************************************************************************/
#include "config.h"
#include "system.h" /* TIME_AFTER */
#include "kernel.h"
#include "timeout.h"
#include "general.h"
/* list of active timeout events */
static struct timeout *tmo_list[MAX_NUM_TIMEOUTS+1];
/* timeout tick task - calls event handlers when they expire
* Event handlers may alter expiration, callback and data during operation.
*/
static void timeout_tick(void)
{
unsigned long tick = current_tick;
struct timeout **p = tmo_list;
struct timeout *curr;
for(curr = *p; curr != NULL; curr = *(++p))
{
int ticks;
if(TIME_BEFORE(tick, curr->expires))
continue;
/* this event has expired - call callback */
ticks = curr->callback(curr);
if(ticks > 0)
{
curr->expires = tick + ticks; /* reload */
}
else
{
timeout_cancel(curr); /* cancel */
}
}
}
/* Cancels a timeout callback - can be called from the ISR */
void timeout_cancel(struct timeout *tmo)
{
int oldlevel = disable_irq_save();
int rc = remove_array_ptr((void **)tmo_list, tmo);
if(rc >= 0 && *tmo_list == NULL)
{
tick_remove_task(timeout_tick); /* Last one - remove task */
}
restore_irq(oldlevel);
}
/* Adds a timeout callback - calling with an active timeout resets the
interval - can be called from the ISR */
void timeout_register(struct timeout *tmo, timeout_cb_type callback,
int ticks, intptr_t data)
{
int oldlevel;
void **arr, **p;
if(tmo == NULL)
return;
oldlevel = disable_irq_save();
/* See if this one is already registered */
arr = (void **)tmo_list;
p = find_array_ptr(arr, tmo);
if(p - arr < MAX_NUM_TIMEOUTS)
{
/* Vacancy */
if(*p == NULL)
{
/* Not present */
if(*tmo_list == NULL)
{
tick_add_task(timeout_tick); /* First one - add task */
}
*p = tmo;
}
tmo->callback = callback;
tmo->data = data;
tmo->expires = current_tick + ticks;
}
restore_irq(oldlevel);
}