summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2010-12-10 15:14:18 +0000
committerThomas Martitz <kugel@rockbox.org>2010-12-10 15:14:18 +0000
commitc47d81345151166083ab10d6f5d11e56462056d5 (patch)
treef01d6b866113ca8998147d98425fa700db42ca48
parent44cdce9b290d4ae9e1a436ef85c5b0ed56827784 (diff)
downloadrockbox-c47d81345151166083ab10d6f5d11e56462056d5.tar.gz
rockbox-c47d81345151166083ab10d6f5d11e56462056d5.zip
Android: Replace the java based tick timer implemented with a not as bloated and more accurate linux hrtimer based one. Further reduces idle cpu usage (0% on my phone but still 1-2% on a Samsung Galaxy S).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28784 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--android/src/org/rockbox/RockboxTimer.java76
-rw-r--r--firmware/target/hosted/android/kernel-android.c110
-rw-r--r--firmware/target/hosted/android/system-target.h2
-rw-r--r--firmware/target/hosted/android/thread-android-arm.c2
4 files changed, 63 insertions, 127 deletions
diff --git a/android/src/org/rockbox/RockboxTimer.java b/android/src/org/rockbox/RockboxTimer.java
deleted file mode 100644
index ff48b3f53a..0000000000
--- a/android/src/org/rockbox/RockboxTimer.java
+++ /dev/null
@@ -1,76 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Thomas Martitz
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22package org.rockbox;
23
24import java.util.Timer;
25import java.util.TimerTask;
26
27import android.content.Context;
28import android.util.Log;
29
30public class RockboxTimer extends Timer
31{
32 private class RockboxTimerTask extends TimerTask {
33 private RockboxTimer timer;
34 public RockboxTimerTask(RockboxTimer parent)
35 {
36 super();
37 timer = parent;
38 }
39
40 @Override
41 public void run()
42 {
43 timerTask();
44 synchronized(timer) {
45 timer.notify();
46 }
47 }
48 }
49
50 public RockboxTimer(Context c, long period_inverval_in_ms)
51 {
52 super("tick timer");
53 schedule(new RockboxTimerTask(this), 0, period_inverval_in_ms);
54 }
55
56 @SuppressWarnings("unused")
57 private void LOG(CharSequence text)
58 {
59 Log.d("Rockbox", (String) text);
60 }
61
62
63 /* methods called from native, keep them simple */
64 public void java_wait_for_interrupt()
65 {
66 synchronized(this)
67 {
68 try {
69 this.wait();
70 } catch (InterruptedException e) {
71 /* Not an error: wakeup and return */
72 }
73 }
74 }
75 public native void timerTask();
76}
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{
diff --git a/firmware/target/hosted/android/system-target.h b/firmware/target/hosted/android/system-target.h
index 0bd6d78fe0..3938ad5fba 100644
--- a/firmware/target/hosted/android/system-target.h
+++ b/firmware/target/hosted/android/system-target.h
@@ -27,6 +27,8 @@
27#define restore_irq(level) (void)level 27#define restore_irq(level) (void)level
28 28
29void power_off(void); 29void power_off(void);
30void wait_for_interrupt(void);
31void interrupt(void);
30 32
31#endif /* __SYSTEM_TARGET_H__ */ 33#endif /* __SYSTEM_TARGET_H__ */
32 34
diff --git a/firmware/target/hosted/android/thread-android-arm.c b/firmware/target/hosted/android/thread-android-arm.c
index baf8b84b65..0bfd2b6c44 100644
--- a/firmware/target/hosted/android/thread-android-arm.c
+++ b/firmware/target/hosted/android/thread-android-arm.c
@@ -23,6 +23,7 @@
23 ****************************************************************************/ 23 ****************************************************************************/
24 24
25#include <jni.h> 25#include <jni.h>
26#include <system.h>
26/*--------------------------------------------------------------------------- 27/*---------------------------------------------------------------------------
27 * Start the thread running and terminate it if it returns 28 * Start the thread running and terminate it if it returns
28 *--------------------------------------------------------------------------- 29 *---------------------------------------------------------------------------
@@ -89,7 +90,6 @@ static inline void load_context(const void* addr)
89 * wait_for_interrupt is implemented in kernel-android.c 90 * wait_for_interrupt is implemented in kernel-android.c
90 **/ 91 **/
91 92
92extern void wait_for_interrupt(void);
93static inline void core_sleep(void) 93static inline void core_sleep(void)
94{ 94{
95 wait_for_interrupt(); 95 wait_for_interrupt();