diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/hosted/android/kernel-android.c | 45 |
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 | ||
35 | static sem_t wfi_sem; | 35 | static pthread_cond_t wfi_cond = PTHREAD_COND_INITIALIZER; |
36 | static 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 */ |
38 | void timer_signal(int sig) | 39 | void 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 */ |
49 | void wait_for_interrupt(void) | 50 | void 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) */ | ||
54 | void interrupt(void) | 57 | void 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) | |||
67 | void tick_start(unsigned int interval_in_ms) | 64 | void 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)); |