summaryrefslogtreecommitdiff
path: root/firmware/target/hosted
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2011-03-11 23:38:36 +0000
committerThomas Martitz <kugel@rockbox.org>2011-03-11 23:38:36 +0000
commit204ac257fe97dafdcd106c9051386ccf09710c4f (patch)
tree3465f36fa8cf34029b633eeba3f084d2f34d64ef /firmware/target/hosted
parent662ba4868af3981dcc64e271f49ee0bd72cd19e5 (diff)
downloadrockbox-204ac257fe97dafdcd106c9051386ccf09710c4f.tar.gz
rockbox-204ac257fe97dafdcd106c9051386ccf09710c4f.zip
Android: Switch to pthread_cond+SIGEV_THREAD for tick task handling.
The implementation wasn't really safe (sem_post from signal handler), and the new one simplifies things a bit. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29575 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/hosted')
-rw-r--r--firmware/target/hosted/android/kernel-android.c45
1 files changed, 19 insertions, 26 deletions
diff --git a/firmware/target/hosted/android/kernel-android.c b/firmware/target/hosted/android/kernel-android.c
index bac6d2a8fd..80ff88fd12 100644
--- a/firmware/target/hosted/android/kernel-android.c
+++ b/firmware/target/hosted/android/kernel-android.c
@@ -24,7 +24,7 @@
24#include <signal.h> 24#include <signal.h>
25#include <errno.h> 25#include <errno.h>
26#include <unistd.h> 26#include <unistd.h>
27#include <semaphore.h> 27#include <pthread.h>
28#include "config.h" 28#include "config.h"
29#include "system.h" 29#include "system.h"
30#include "button.h" 30#include "button.h"
@@ -32,12 +32,13 @@
32#include "panic.h" 32#include "panic.h"
33 33
34 34
35static sem_t wfi_sem; 35static pthread_cond_t wfi_cond = PTHREAD_COND_INITIALIZER;
36static pthread_mutex_t wfi_mtx = PTHREAD_MUTEX_INITIALIZER;
36/* 37/*
37 * call tick tasks and wake the scheduler up */ 38 * call tick tasks and wake the scheduler up */
38void timer_signal(int sig) 39void timer_signal(union sigval arg)
39{ 40{
40 (void)sig; 41 (void)arg;
41 call_tick_tasks(); 42 call_tick_tasks();
42 interrupt(); 43 interrupt();
43} 44}
@@ -48,18 +49,14 @@ void timer_signal(int sig)
48 * other mechanisms could use them as well */ 49 * other mechanisms could use them as well */
49void wait_for_interrupt(void) 50void wait_for_interrupt(void)
50{ 51{
51 sem_wait(&wfi_sem); 52 pthread_cond_wait(&wfi_cond, &wfi_mtx);
52} 53}
53 54
55/*
56 * Wakeup the kernel, if sleeping (shall not be called from a signal handler) */
54void interrupt(void) 57void interrupt(void)
55{ 58{
56 int s; 59 pthread_cond_signal(&wfi_cond);
57 /* unless idling, we usually have more interrupt() than wait_for_interrupt()
58 * don't post unecessarily because wait_for_interrupt() would need to
59 * decrement for each wasted sem_post(), instead of sleeping directly */
60 sem_getvalue(&wfi_sem, &s);
61 if (s <= 0)
62 sem_post(&wfi_sem);
63} 60}
64 61
65/* 62/*
@@ -67,30 +64,26 @@ void interrupt(void)
67void tick_start(unsigned int interval_in_ms) 64void tick_start(unsigned int interval_in_ms)
68{ 65{
69 int ret = 0; 66 int ret = 0;
70 sigset_t proc_set;
71 timer_t timerid; 67 timer_t timerid;
72 struct itimerspec ts; 68 struct itimerspec ts;
73 sigevent_t sigev = { 69 sigevent_t sigev;
74 .sigev_notify = SIGEV_SIGNAL, 70
75 .sigev_signo = SIGUSR2, 71 /* initializing in the declaration causes some weird warnings */
76 }; 72 memset(&sigev, 0, sizeof(sigevent_t));
73 sigev.sigev_notify = SIGEV_THREAD,
74 sigev.sigev_notify_function = timer_signal,
77 75
78 ts.it_value.tv_sec = ts.it_interval.tv_sec = 0; 76 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; 77 ts.it_value.tv_nsec = ts.it_interval.tv_nsec = interval_in_ms*1000*1000;
80 78
81 /* add the signal handler */
82 signal(SIGUSR2, timer_signal);
83
84 /* add the timer */ 79 /* add the timer */
85 ret |= timer_create(CLOCK_REALTIME, &sigev, &timerid); 80 ret |= timer_create(CLOCK_REALTIME, &sigev, &timerid);
86 ret |= timer_settime(timerid, 0, &ts, NULL); 81 ret |= timer_settime(timerid, 0, &ts, NULL);
87 82
88 /* unblock SIGUSR2 so the handler can run */ 83 /* Grab the mutex already now and leave it to this thread. We don't
89 ret |= sigprocmask(0, NULL, &proc_set); 84 * care about race conditions when signaling the condition (because
90 ret |= sigdelset(&proc_set, SIGUSR2); 85 * they are not critical), but a mutex is necessary due to the API */
91 ret |= sigprocmask(SIG_SETMASK, &proc_set, NULL); 86 pthread_mutex_lock(&wfi_mtx);
92
93 ret |= sem_init(&wfi_sem, 0, 0);
94 87
95 if (ret != 0) 88 if (ret != 0)
96 panicf("%s(): %s\n", __func__, strerror(errno)); 89 panicf("%s(): %s\n", __func__, strerror(errno));