irq.hpp
00001 #if !defined(__IRQ_HPP__)
00002 #define __IRQ_HPP__
00003
00004
00005
00006
00007 #include "core/common.hpp"
00008
00009
00010
00011
00012 namespace detail
00013 {
00014
00015
00016
00017 struct semaphore_irq
00018 {
00019 l4_threadid_t client;
00020 struct semaphore semaphore;
00021
00022 inline semaphore_irq(void)
00023 : client(L4_INVALID_ID), semaphore(L4SEMAPHORE_LOCKED)
00024 {}
00025
00026 inline unsigned timeout2us(const l4_timeout_t timeout)
00027 {
00028
00029 assert_logd(L4VMM_DEBUG_IRQS, !l4_timeout_is_absolute(timeout.p.rcv),
00030 "invalid absolute timeout. can only handle relative timeouts up to 4294s.\n");
00031
00032 const l4_kernel_clock_t us=l4_timeout_rel_get(timeout.p.rcv);
00033
00034
00035 assert_logd(L4VMM_DEBUG_IRQS, (timeout.raw == L4_IPC_NEVER.raw) ||
00036 (us <= integer_traits<unsigned>::const_max),
00037 "timeout %lluus (0x%llx) too large. can only handle 4294s.\n", us, us);
00038
00039 return us;
00040 }
00041
00042 inline void do_wait(const l4_threadid_t client, const l4_timeout_t timeout)
00043 {
00044 this->client=client;
00045 logd(L4VMM_DEBUG_IRQS >= 3, L4VMM_DEBUG": %s: "l4util_idfmt"\n",
00046 __func__, l4util_idstr(client));
00047
00048 semaphore.down(timeout2us(timeout));
00049 this->client=L4_INVALID_ID;
00050 }
00051
00052 inline void do_assert(void)
00053 {
00054 logd(L4VMM_DEBUG_IRQS >= 2, L4VMM_DEBUG": %s: "l4util_idfmt" -> "l4util_idfmt"\n",
00055 __func__, l4util_idstr(l4_myself()), l4util_idstr(client));
00056
00057 semaphore.up();
00058 }
00059 };
00060
00061 struct ipc_irq
00062 {
00063 l4_threadid_t client;
00064
00065 inline ipc_irq(void)
00066 : client(L4_INVALID_ID)
00067 {}
00068
00069 inline void do_wait(const l4_threadid_t client, const l4_timeout_t timeout)
00070 {
00071 this->client=client;
00072 logd(L4VMM_DEBUG_IRQS >= 3, L4VMM_DEBUG": %s: "l4util_idfmt"\n",
00073 __func__, l4util_idstr(client));
00074
00075 l4_threadid_t src;
00076 l4_umword_t dummy;
00077 l4_msgdope_t result;
00078 do {
00079 l4_ipc_wait(&src, L4_IPC_SHORT_MSG, &dummy, &dummy, timeout, &result);
00080 } while (!l4_task_equal(src, client));
00081
00082 this->client=L4_INVALID_ID;
00083 }
00084
00085 inline void do_assert(void)
00086 {
00087 logd(L4VMM_DEBUG_IRQS >= 2, L4VMM_DEBUG": %s: "l4util_idfmt" -> "l4util_idfmt"\n",
00088 __func__, l4util_idstr(l4_myself()), l4util_idstr(client));
00089
00090
00091 l4_msgdope_t dope;
00092 l4_ipc_send(client, L4_IPC_SHORT_MSG, 0, 0, L4_IPC_BOTH_TIMEOUT_0, &dope);
00093 }
00094 };
00095 }
00096
00100 struct irq
00101 #if L4VMM_IRQ_SAFE_LOCKS
00102 : private detail::semaphore_irq
00103 #else
00104 : private detail::ipc_irq
00105 #endif
00106 {
00107 protected:
00108 enum state_bits
00109 {
00111 PENDING = 0,
00113 MASKED = 1
00114 };
00115
00119 bitops state;
00120
00121 public:
00128 inline irq(void)
00129 : state(1 << MASKED)
00130 {}
00131
00132
00133
00134
00138 inline bool is_pending(void) const
00139 {
00140 return state.test_bit(PENDING);
00141 }
00142
00146 inline bool is_masked(void) const
00147 {
00148 return state.test_bit(MASKED);
00149 }
00150
00154 inline l4_umword_t get_state(void) const
00155 {
00156 return state;
00157 }
00158
00162 inline void consume(void)
00163 {
00164 state.clear_bit(PENDING);
00165 }
00166
00170 inline void mask(void)
00171 {
00172 state.set_bit(MASKED);
00173 }
00174
00179 inline void unmask(void)
00180 {
00181 const bitops old_state=state;
00182 state.clear_bit(MASKED);
00183 if (old_state.test_bit(PENDING) && old_state.test_bit(MASKED))
00184 do_assert();
00185 }
00186
00191 inline void wait(const l4_threadid_t client, const l4_timeout_t timeout)
00192 {
00193 const bitops old_state=state;
00194 if (!old_state.test_bit(PENDING) || old_state.test_bit(MASKED))
00195 do_wait(client, timeout);
00196 consume();
00197 }
00198
00203 inline void assert_irq(void)
00204 {
00205 const bitops old_state=state;
00206 state.set_bit(PENDING);
00207 if (!old_state.test_bit(PENDING) && !old_state.test_bit(MASKED))
00208 do_assert();
00209 }
00210 };
00211
00212 #endif
00213
00214
00215