Overview   API Reference  

irq.hpp

00001 #if !defined(__IRQ_HPP__)
00002 #define __IRQ_HPP__
00003 
00004 //
00005 // local includes
00006 //
00007 #include "core/common.hpp"
00008 
00009 //
00010 // classes to implement different locking strategies using a semaphore or IPC respectively.
00011 //
00012 namespace detail
00013 {
00014     //
00015     // does not support a client-server model, deprecated
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             // the timeout cannot be absolute
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             // the code later on uses unsigned to specify a timeout, so check for overflows
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             // use no send timeout, because the invoking thread may be the receiver too (sic!)
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     // query functions
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 // ***** end of source ***** //
00215 

L4vmm Reference Manual, written by Mario Schwalbe  © 2006-2008