summaryrefslogtreecommitdiff
path: root/uisimulator/sdl/kernel-sdl.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-03-25 02:34:12 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-03-25 02:34:12 +0000
commit27cf67733936abd75fcb1f8da765977cd75906ee (patch)
treef894211a8a0c77b402dd3250b2bee2d17dcfe13f /uisimulator/sdl/kernel-sdl.c
parentbc2f8fd8f38a3e010cd67bbac358f6e9991153c6 (diff)
downloadrockbox-27cf67733936abd75fcb1f8da765977cd75906ee.tar.gz
rockbox-27cf67733936abd75fcb1f8da765977cd75906ee.zip
Add a complete priority inheritance implementation to the scheduler (all mutex ownership and queue_send calls are inheritable). Priorities are differential so that dispatch depends on the runnable range of priorities. Codec priority can therefore be raised in small steps (pcmbuf updated to enable). Simplify the kernel functions to ease implementation and use the same kernel.c for both sim and target (I'm tired of maintaining two ;_). 1) Not sure if a minor audio break at first buffering issue will exist on large-sector disks (the main mutex speed issue was genuinely resolved earlier). At this point it's best dealt with at the buffering level. It seems a larger filechunk could be used again. 2) Perhaps 64-bit sims will have some minor issues (finicky) but a backroll of the code of concern there is a 5-minute job. All kernel objects become incompatible so a full rebuild and update is needed.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16791 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'uisimulator/sdl/kernel-sdl.c')
-rw-r--r--uisimulator/sdl/kernel-sdl.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/uisimulator/sdl/kernel-sdl.c b/uisimulator/sdl/kernel-sdl.c
new file mode 100644
index 0000000000..b6e6a34551
--- /dev/null
+++ b/uisimulator/sdl/kernel-sdl.c
@@ -0,0 +1,168 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Felix Arends
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <stdlib.h>
21#include <SDL.h>
22#include <SDL_thread.h>
23#include "memory.h"
24#include "system-sdl.h"
25#include "uisdl.h"
26#include "kernel.h"
27#include "thread-sdl.h"
28#include "thread.h"
29#include "debug.h"
30
31static SDL_TimerID tick_timer_id;
32long start_tick;
33
34/* Condition to signal that "interrupts" may proceed */
35static SDL_cond *sim_thread_cond;
36/* Mutex to serialize changing levels and exclude other threads while
37 * inside a handler */
38static SDL_mutex *sim_irq_mtx;
39static int interrupt_level = HIGHEST_IRQ_LEVEL;
40static int handlers_pending = 0;
41static int status_reg = 0;
42
43extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
44
45/* Nescessary logic:
46 * 1) All threads must pass unblocked
47 * 2) Current handler must always pass unblocked
48 * 3) Threads must be excluded when irq routine is running
49 * 4) No more than one handler routine should execute at a time
50 */
51int set_irq_level(int level)
52{
53 SDL_LockMutex(sim_irq_mtx);
54
55 int oldlevel = interrupt_level;
56
57 if (status_reg == 0 && level == 0 && oldlevel != 0)
58 {
59 /* Not in a handler and "interrupts" are being reenabled */
60 if (handlers_pending > 0)
61 SDL_CondSignal(sim_thread_cond);
62 }
63
64 interrupt_level = level; /* save new level */
65
66 SDL_UnlockMutex(sim_irq_mtx);
67 return oldlevel;
68}
69
70void sim_enter_irq_handler(void)
71{
72 SDL_LockMutex(sim_irq_mtx);
73 handlers_pending++;
74
75 if(interrupt_level != 0)
76 {
77 /* "Interrupts" are disabled. Wait for reenable */
78 SDL_CondWait(sim_thread_cond, sim_irq_mtx);
79 }
80
81 status_reg = 1;
82}
83
84void sim_exit_irq_handler(void)
85{
86 if (--handlers_pending > 0)
87 SDL_CondSignal(sim_thread_cond);
88
89 status_reg = 0;
90 SDL_UnlockMutex(sim_irq_mtx);
91}
92
93bool sim_kernel_init(void)
94{
95 sim_irq_mtx = SDL_CreateMutex();
96 if (sim_irq_mtx == NULL)
97 {
98 fprintf(stderr, "Cannot create sim_handler_mtx\n");
99 return false;
100 }
101
102 sim_thread_cond = SDL_CreateCond();
103 if (sim_thread_cond == NULL)
104 {
105 fprintf(stderr, "Cannot create sim_thread_cond\n");
106 return false;
107 }
108
109 return true;
110}
111
112void sim_kernel_shutdown(void)
113{
114 SDL_RemoveTimer(tick_timer_id);
115 SDL_DestroyMutex(sim_irq_mtx);
116 SDL_DestroyCond(sim_thread_cond);
117}
118
119Uint32 tick_timer(Uint32 interval, void *param)
120{
121 long new_tick;
122
123 (void) interval;
124 (void) param;
125
126 new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ);
127
128 if(new_tick != current_tick)
129 {
130 long t;
131 for(t = new_tick - current_tick; t > 0; t--)
132 {
133 int i;
134
135 sim_enter_irq_handler();
136
137 /* Run through the list of tick tasks */
138 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
139 {
140 if(tick_funcs[i])
141 {
142 tick_funcs[i]();
143 }
144 }
145
146 sim_exit_irq_handler();
147 }
148
149 current_tick = new_tick;
150 }
151
152 return 1;
153}
154
155void tick_start(unsigned int interval_in_ms)
156{
157 if (tick_timer_id != NULL)
158 {
159 SDL_RemoveTimer(tick_timer_id);
160 tick_timer_id = NULL;
161 }
162 else
163 {
164 start_tick = SDL_GetTicks();
165 }
166
167 tick_timer_id = SDL_AddTimer(interval_in_ms, tick_timer, NULL);
168}