summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-10-27 16:30:24 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-10-27 16:30:24 +0000
commita9e69d935cb5c2e5ffca1bbc977252ce7661d343 (patch)
tree8ac65804b294cfe7cc55febe445f904a1b33cb0e
parente5d72ac5f767a66b11c7a46dfb4edd322f7a723d (diff)
downloadrockbox-a9e69d935cb5c2e5ffca1bbc977252ce7661d343.tar.gz
rockbox-a9e69d935cb5c2e5ffca1bbc977252ce7661d343.zip
Strange little kernel optimization to ease targeting the timer tick and to limit the number of loops in the tick function to the number of tasks added rather than always looping the max number.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18893 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/kernel.h12
-rw-r--r--firmware/kernel.c72
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c12
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c14
-rw-r--r--firmware/target/arm/tcc77x/timer-tcc77x.c14
-rw-r--r--firmware/target/arm/tcc780x/timer-tcc780x.c15
-rw-r--r--firmware/target/arm/tms320dm320/kernel-dm320.c13
-rw-r--r--firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c11
8 files changed, 37 insertions, 126 deletions
diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h
index 51eb635004..9438f6d308 100644
--- a/firmware/export/kernel.h
+++ b/firmware/export/kernel.h
@@ -207,6 +207,18 @@ int tick_add_task(void (*f)(void));
int tick_remove_task(void (*f)(void));
extern void tick_start(unsigned int interval_in_ms);
+/* inline helper for implementing target interrupt handler */
+static inline void call_tick_tasks(void)
+{
+ extern void (*tick_funcs[MAX_NUM_TICK_TASKS+1])(void);
+ int i;
+
+ current_tick++;
+
+ for (i = 0; tick_funcs[i] != NULL; i++)
+ tick_funcs[i]();
+}
+
struct timeout;
/* timeout callback type
diff --git a/firmware/kernel.c b/firmware/kernel.c
index fb9c5e2449..70b3e03615 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -54,7 +54,9 @@
volatile long current_tick SHAREDDATA_ATTR = 0;
#endif
-void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
+/* List of tick tasks - final element always NULL for termination */
+void (*tick_funcs[MAX_NUM_TICK_TASKS+1])(void);
+static int num_tick_funcs = 0;
extern struct core_entry cores[NUM_CORES];
@@ -128,18 +130,8 @@ void tick_start(unsigned int interval_in_ms)
void IMIA0(void) __attribute__ ((interrupt_handler));
void IMIA0(void)
{
- int i;
-
/* Run through the list of tick tasks */
- for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
- {
- if(tick_funcs[i])
- {
- tick_funcs[i]();
- }
- }
-
- current_tick++;
+ call_tick_tasks();
TSR0 &= ~0x01;
}
@@ -178,18 +170,8 @@ void tick_start(unsigned int interval_in_ms)
void TIMER0(void) __attribute__ ((interrupt_handler));
void TIMER0(void)
{
- int i;
-
/* Run through the list of tick tasks */
- for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
- {
- if(tick_funcs[i])
- {
- tick_funcs[i]();
- }
- }
-
- current_tick++;
+ call_tick_tasks();
TER0 = 0xff; /* Clear all events */
}
@@ -199,27 +181,17 @@ void TIMER0(void)
#ifndef BOOTLOADER
void TIMER1(void)
{
- int i;
-
/* Run through the list of tick tasks (using main core) */
TIMER1_VAL; /* Read value to ack IRQ */
/* Run through the list of tick tasks using main CPU core -
wake up the COP through its control interface to provide pulse */
- for (i = 0;i < MAX_NUM_TICK_TASKS;i++)
- {
- if (tick_funcs[i])
- {
- tick_funcs[i]();
- }
- }
+ call_tick_tasks();
#if NUM_CORES > 1
/* Pulse the COP */
core_wake(COP);
#endif /* NUM_CORES */
-
- current_tick++;
}
#endif
@@ -243,16 +215,8 @@ void tick_start(unsigned int interval_in_ms)
void timer_handler(void)
{
- int i;
-
/* Run through the list of tick tasks */
- for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
- {
- if(tick_funcs[i])
- tick_funcs[i]();
- }
-
- current_tick++;
+ call_tick_tasks();
TIMER0.clr = 0;
}
@@ -274,19 +238,16 @@ void tick_start(unsigned int interval_in_ms)
int tick_add_task(void (*f)(void))
{
- int i;
int oldlevel = disable_irq_save();
/* Add a task if there is room */
- for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
+ if(num_tick_funcs < MAX_NUM_TICK_TASKS)
{
- if(tick_funcs[i] == NULL)
- {
- tick_funcs[i] = f;
- restore_irq(oldlevel);
- return 0;
- }
+ tick_funcs[num_tick_funcs++] = f;
+ restore_irq(oldlevel);
+ return 0;
}
+
restore_irq(oldlevel);
panicf("Error! tick_add_task(): out of tasks");
return -1;
@@ -298,11 +259,16 @@ int tick_remove_task(void (*f)(void))
int oldlevel = disable_irq_save();
/* Remove a task if it is there */
- for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
+ for(i = 0;i < num_tick_funcs;i++)
{
if(tick_funcs[i] == f)
{
- tick_funcs[i] = NULL;
+ /* Compact function list - propagates NULL-terminator as well */
+ for(; i < num_tick_funcs; i++)
+ tick_funcs[i] = tick_funcs[i+1];
+
+ num_tick_funcs--;
+
restore_irq(oldlevel);
return 0;
}
diff --git a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c b/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c
index e7bce8dc2c..3d7c577e3c 100644
--- a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c
@@ -27,22 +27,12 @@
#include "kernel.h"
#include "thread.h"
-extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
-
static __attribute__((interrupt("IRQ"))) void EPIT1_HANDLER(void)
{
- int i;
-
EPITSR1 = EPITSR_OCIF; /* Clear the pending status */
/* Run through the list of tick tasks */
- for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
- {
- if(tick_funcs[i])
- tick_funcs[i]();
- }
-
- current_tick++;
+ call_tick_tasks();
}
void tick_start(unsigned int interval_in_ms)
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
index 4f878d4ed3..76917c8c82 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c
@@ -24,8 +24,6 @@
#include "timer.h"
#include "thread.h"
-extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
-
void tick_start(unsigned int interval_in_ms)
{
/*
@@ -62,18 +60,8 @@ void tick_start(unsigned int interval_in_ms)
void TIMER4(void)
{
- int i;
-
/* Run through the list of tick tasks */
- for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
- {
- if(tick_funcs[i])
- {
- tick_funcs[i]();
- }
- }
-
- current_tick++;
+ call_tick_tasks();
SRCPND = TIMER4_MASK;
INTPND = TIMER4_MASK;
diff --git a/firmware/target/arm/tcc77x/timer-tcc77x.c b/firmware/target/arm/tcc77x/timer-tcc77x.c
index 4645e388cc..924ddda625 100644
--- a/firmware/target/arm/tcc77x/timer-tcc77x.c
+++ b/firmware/target/arm/tcc77x/timer-tcc77x.c
@@ -51,24 +51,12 @@ void __timer_unregister(void)
/* Timer interrupt processing - all timers (inc. tick) have a single IRQ */
-
-extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
-
void TIMER(void)
{
if (TIREQ & TF0) /* Timer0 reached ref value */
{
- int i;
-
/* Run through the list of tick tasks */
- for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
- {
- if(tick_funcs[i])
- {
- tick_funcs[i]();
- }
- }
- current_tick++;
+ call_tick_tasks();
/* reset Timer 0 IRQ & ref flags */
TIREQ |= TI0 | TF0;
diff --git a/firmware/target/arm/tcc780x/timer-tcc780x.c b/firmware/target/arm/tcc780x/timer-tcc780x.c
index c08520116a..17956131c0 100644
--- a/firmware/target/arm/tcc780x/timer-tcc780x.c
+++ b/firmware/target/arm/tcc780x/timer-tcc780x.c
@@ -46,25 +46,12 @@ void __timer_unregister(void)
/* Timer interrupt processing - all timers (inc. tick) have a single IRQ */
-
-extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
-
void TIMER0(void)
{
if (TIREQ & TF0) /* Timer0 reached ref value */
{
- int i;
-
/* Run through the list of tick tasks */
- for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
- {
- if(tick_funcs[i])
- {
- tick_funcs[i]();
- }
- }
-
- current_tick++;
+ call_tick_tasks();
/* reset Timer 0 IRQ & ref flags */
TIREQ |= TI0 | TF0;
diff --git a/firmware/target/arm/tms320dm320/kernel-dm320.c b/firmware/target/arm/tms320dm320/kernel-dm320.c
index 42f9773d36..b5eb4233e4 100644
--- a/firmware/target/arm/tms320dm320/kernel-dm320.c
+++ b/firmware/target/arm/tms320dm320/kernel-dm320.c
@@ -25,8 +25,6 @@
#include "timer.h"
#include "thread.h"
-extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
-
void tick_start(unsigned int interval_in_ms)
{
/* TODO: set up TIMER1 clock settings
@@ -53,16 +51,7 @@ void tick_start(unsigned int interval_in_ms)
void TIMER1(void)
{
IO_INTC_IRQ0 = INTR_IRQ0_TMR1;
-
- int i;
/* Run through the list of tick tasks */
- for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
- {
- if(tick_funcs[i])
- {
- tick_funcs[i]();
- }
- }
- current_tick++;
+ call_tick_tasks();
}
diff --git a/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c b/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c
index 62176cee24..dcfdfd6a38 100644
--- a/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c
@@ -24,8 +24,6 @@
#include "kernel.h"
#include "jz4740.h"
-extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
-
#define USE_RTC_CLOCK 0
void tick_start(unsigned int interval_in_ms)
{
@@ -70,13 +68,6 @@ void TCU0(void)
{
__tcu_clear_full_match_flag(0);
- int i;
-
/* Run through the list of tick tasks */
- for(i = 0; i < MAX_NUM_TICK_TASKS; i++)
- {
- if(tick_funcs[i])
- tick_funcs[i]();
- }
- current_tick++;
+ call_tick_tasks();
}