5 #include "member_offs.h"
14 /** A receiver. This is a role class, and real receiver's must inherit from
15 it. The protected interface is intended for the receiver, and the public
16 interface is intended for the sender.
18 The only reason this class inherits from Context is to force a specific
19 layout for Thread. Otherwise, Receiver could just embed or reference
22 class Receiver : public Context, public Ref_cnt_obj
29 Rs_not_receiving = false,
30 Rs_ipc_receive = true,
31 Rs_irq_receive = true + 1
41 Rcv_state sender_ok(const Sender* sender) const;
43 virtual ~Receiver() {}
47 Sender* _partner; // IPC partner I'm waiting for/involved with
48 Syscall_frame *_rcv_regs; // registers used for receive
50 Iteratable_prio_list _sender_list;
53 typedef Context_ptr_base<Receiver> Receiver_ptr;
62 #include "lock_guard.h"
65 #include "thread_lock.h"
66 #include "entry_frame.h"
67 #include "std_macros.h"
68 #include "thread_state.h"
70 // Interface for receivers
73 @param thread_lock the lock used for synchronizing access to this receiver
74 @param space_context the space context
78 : Context(), _caller(0)
83 Receiver::caller() const
84 { return reinterpret_cast<Receiver*>(_caller & ~0x03UL); }
88 Receiver::caller_rights() const
89 { return _caller & 0x3; }
94 Receiver::set_caller(Receiver *caller, unsigned char rights)
96 register Mword nv = Mword(caller) | (rights & 0x3);
97 reinterpret_cast<Mword volatile &>(_caller) = nv;
99 /** IPC partner (sender).
100 @return sender of ongoing or previous IPC operation
104 Receiver::partner() const
110 // Interface for senders
112 /** Return a reference to receiver's IPC registers.
113 Senders call this function to poke values into the receiver's register set.
114 @pre state() & Thread_ipc_receiving_mask
115 @return pointer to receiver's IPC registers.
117 PUBLIC inline NEEDS[<cassert>]
119 Receiver::rcv_regs() const
121 //assert (state () & Thread_ipc_receiving_mask);
126 /** Head of sender list.
127 @return a reference to the receiver's list of senders
130 Iteratable_prio_list *
131 Receiver::sender_list()
133 return &_sender_list;
140 Receiver::set_rcv_regs(Syscall_frame* regs)
147 Receiver::set_timeout(Timeout *t)
154 Receiver::dequeue_timeout()
157 _timeout->dequeue(_timeout->has_hit());
162 Receiver::enqueue_timeout_again()
165 _timeout->set_again(current_cpu());
170 Receiver::reset_timeout()
172 if (EXPECT_TRUE(!_timeout))
180 void Receiver::prepare_receive(Sender *partner, Syscall_frame *regs)
182 set_rcv_regs(regs); // message should be poked in here
183 set_partner(partner);
187 bool Receiver::prepared() const
188 { return _rcv_regs; }
190 /** Set the IPC partner (sender).
191 @param partner IPC partner
195 Receiver::set_partner(Sender* partner)
202 Receiver::in_ipc(Sender *sender)
204 return (state() & Thread_receive_in_progress) && (partner() == sender);
208 /** Return whether the receiver is ready to accept a message from the
210 @param sender thread that wants to send a message to this receiver
211 @return true if receiver is in correct state to accept a message
212 right now (open wait, or closed wait and waiting for sender).
214 IMPLEMENT inline NEEDS["std_macros.h", "thread_state.h", "sender.h",
215 Receiver::partner, Receiver::vcpu_async_ipc]
217 Receiver::sender_ok(const Sender *sender) const
219 unsigned ipc_state = state() & Thread_ipc_mask;
221 // If Thread_send_in_progress is still set, we're still in the send phase
222 if (EXPECT_FALSE(ipc_state != Thread_receive_wait))
223 return vcpu_async_ipc(sender);
225 // Check open wait; test if this sender is really the first in queue
226 if (EXPECT_TRUE(!partner()
227 && (!_sender_list.head()
228 || sender->is_head_of(&_sender_list))))
229 return Rs_ipc_receive;
231 // Check closed wait; test if this sender is really who we specified
232 if (EXPECT_TRUE(sender == partner()))
233 return Rs_ipc_receive;
235 return Rs_not_receiving;
238 //-----------------------------------------------------------------------------
243 Receiver::vcpu_async_ipc(Sender const *sender) const
245 if (EXPECT_FALSE(state() & Thread_ipc_mask))
246 return Rs_not_receiving;
248 Vcpu_state *vcpu = vcpu_state().access();
250 if (EXPECT_FALSE(!vcpu_irqs_enabled(vcpu)))
251 return Rs_not_receiving;
253 Receiver *self = const_cast<Receiver*>(this);
255 if (this == current())
256 self->spill_user_state();
258 if (self->vcpu_enter_kernel_mode(vcpu))
259 vcpu = vcpu_state().access();
261 LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt,
262 Vcpu_log *l = tbe->payload<Vcpu_log>();
264 l->state = vcpu->_saved_state;
265 l->ip = Mword(sender);
266 l->sp = regs()->sp();
267 l->space = ~0; //vcpu_user_space() ? static_cast<Task*>(vcpu_user_space())->dbg_id() : ~0;
270 self->_rcv_regs = &vcpu->_ipc_regs;
271 vcpu->_ts.set_ipc_upcall();
272 self->set_partner(const_cast<Sender*>(sender));
273 self->state_add_dirty(Thread_receive_wait);
274 self->vcpu_save_state_and_upcall();
275 return Rs_irq_receive;
281 Receiver::vcpu_update_state()
283 if (EXPECT_TRUE(!(state() & Thread_vcpu_enabled)))
286 if (!sender_list()->head())
287 vcpu_state().access()->sticky_flags &= ~Vcpu_state::Sf_irq_pending;
291 // --------------------------------------------------------------------------
293 struct Ipc_remote_dequeue_request
297 Receiver::Abort_state state;
302 Receiver::handle_remote_abort_send(Drq *, Context *, void *_rq)
304 Ipc_remote_dequeue_request *rq = (Ipc_remote_dequeue_request*)_rq;
305 if (rq->sender->in_sender_list())
307 // really cancled IPC
308 rq->state = Abt_ipc_cancel;
309 rq->sender->sender_dequeue(rq->partner->sender_list());
310 rq->partner->vcpu_update_state();
312 else if (rq->partner->in_ipc(rq->sender))
313 rq->state = Abt_ipc_in_progress;
318 Receiver::Abort_state
319 Receiver::abort_send(Sender *sender)
321 Ipc_remote_dequeue_request rq;
324 rq.state = Abt_ipc_done;
325 if (current_cpu() != cpu())
326 drq(handle_remote_abort_send, &rq);
328 handle_remote_abort_send(0, 0, &rq);