summaryrefslogtreecommitdiff
path: root/firmware/target/hosted/android/kernel-android.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/android/kernel-android.c')
-rw-r--r--firmware/target/hosted/android/kernel-android.c110
1 files changed, 60 insertions, 50 deletions
diff --git a/firmware/target/hosted/android/kernel-android.c b/firmware/target/hosted/android/kernel-android.c
index c0d927d026..bac6d2a8fd 100644
--- a/firmware/target/hosted/android/kernel-android.c
+++ b/firmware/target/hosted/android/kernel-android.c
@@ -20,73 +20,83 @@
20 ****************************************************************************/ 20 ****************************************************************************/
21 21
22 22
23#include <jni.h> 23#include <time.h>
24#include <signal.h>
25#include <errno.h>
26#include <unistd.h>
27#include <semaphore.h>
24#include "config.h" 28#include "config.h"
25#include "system.h" 29#include "system.h"
26#include "button.h" 30#include "button.h"
27#include "audio.h" 31#include "audio.h"
32#include "panic.h"
28 33
29extern JNIEnv *env_ptr;
30 34
31extern jobject RockboxService_instance; 35static sem_t wfi_sem;
36/*
37 * call tick tasks and wake the scheduler up */
38void timer_signal(int sig)
39{
40 (void)sig;
41 call_tick_tasks();
42 interrupt();
43}
32 44
33static jclass RockboxTimer_class;
34static jobject RockboxTimer_instance;
35static jmethodID java_wait_for_interrupt;
36static bool initialized = false;
37/* 45/*
38 * This is called from the separate Timer java thread. I have not added any 46 * wait on the sem which the signal handler posts to save cpu time (aka sleep)
39 * interrupt simulation to it (like the sdl counterpart does),
40 * I think this is probably not needed, unless code calls disable_interrupt()
41 * in order to be protected from tick tasks, but I can't remember a place right
42 * now.
43 * 47 *
44 * No synchronisation mechanism either. This could possibly be problematic, 48 * other mechanisms could use them as well */
45 * but we'll see :) 49void wait_for_interrupt(void)
46 */
47JNIEXPORT void JNICALL
48Java_org_rockbox_RockboxTimer_timerTask(JNIEnv *env, jobject this)
49{ 50{
50 (void)env; 51 sem_wait(&wfi_sem);
51 (void)this;
52 call_tick_tasks();
53} 52}
54 53
55void tick_start(unsigned int interval_in_ms) 54void interrupt(void)
56{ 55{
57 JNIEnv e = *env_ptr; 56 int s;
58 /* first, create a new Timer instance */ 57 /* unless idling, we usually have more interrupt() than wait_for_interrupt()
59 RockboxTimer_class = e->FindClass(env_ptr, "org/rockbox/RockboxTimer"); 58 * don't post unecessarily because wait_for_interrupt() would need to
60 jmethodID constructor = e->GetMethodID(env_ptr, 59 * decrement for each wasted sem_post(), instead of sleeping directly */
61 RockboxTimer_class, 60 sem_getvalue(&wfi_sem, &s);
62 "<init>", 61 if (s <= 0)
63 "(Landroid/content/Context;J)V"); 62 sem_post(&wfi_sem);
64 /* the constructor will do the tick_start */
65 RockboxTimer_instance = e->NewObject(env_ptr,
66 RockboxTimer_class,
67 constructor,
68 RockboxService_instance,
69 (jlong)interval_in_ms);
70
71 /* get our wfi func also */
72 java_wait_for_interrupt = e->GetMethodID(env_ptr,
73 RockboxTimer_class,
74 "java_wait_for_interrupt",
75 "()V");
76 /* it's now safe to call java_wait_for_interrupt */
77 initialized = true;
78} 63}
79 64
80void wait_for_interrupt(void) 65/*
66 * setup a hrtimer to send a signal to our process every tick */
67void tick_start(unsigned int interval_in_ms)
81{ 68{
82 if (LIKELY(initialized)) 69 int ret = 0;
83 { 70 sigset_t proc_set;
84 (*env_ptr)->CallVoidMethod(env_ptr, 71 timer_t timerid;
85 RockboxTimer_instance, 72 struct itimerspec ts;
86 java_wait_for_interrupt); 73 sigevent_t sigev = {
87 } 74 .sigev_notify = SIGEV_SIGNAL,
75 .sigev_signo = SIGUSR2,
76 };
77
78 ts.it_value.tv_sec = ts.it_interval.tv_sec = 0;
79 ts.it_value.tv_nsec = ts.it_interval.tv_nsec = interval_in_ms*1000*1000;
80
81 /* add the signal handler */
82 signal(SIGUSR2, timer_signal);
83
84 /* add the timer */
85 ret |= timer_create(CLOCK_REALTIME, &sigev, &timerid);
86 ret |= timer_settime(timerid, 0, &ts, NULL);
87
88 /* unblock SIGUSR2 so the handler can run */
89 ret |= sigprocmask(0, NULL, &proc_set);
90 ret |= sigdelset(&proc_set, SIGUSR2);
91 ret |= sigprocmask(SIG_SETMASK, &proc_set, NULL);
92
93 ret |= sem_init(&wfi_sem, 0, 0);
94
95 if (ret != 0)
96 panicf("%s(): %s\n", __func__, strerror(errno));
88} 97}
89 98
99
90bool timer_register(int reg_prio, void (*unregister_callback)(void), 100bool timer_register(int reg_prio, void (*unregister_callback)(void),
91 long cycles, void (*timer_callback)(void)) 101 long cycles, void (*timer_callback)(void))
92{ 102{