00001
00002
00003 #ifndef receiver_h
00004 #define receiver_h
00005
00006 #include "context.h"
00007 #include "timeout.h"
00008
00009
00010
00011
00012
00013
00014 class Sys_ipc_frame;
00015 class Sender;
00016 class Thread;
00017 class Space;
00018
00027 class Receiver : public Context
00028 {
00029 public:
00030 bool sender_ok (const Sender* sender) const;
00031 void deny_lipc();
00032 void deny_lipc_snd();
00033
00034 private:
00035
00036 Sender* _partner;
00037 Sys_ipc_frame *_rcv_regs;
00038 Address _pagein_addr;
00039 Mword _pagein_error_code;
00040 Thread* _pagein_applicant;
00041 Sender* _sender_first;
00042
00043 protected:
00044
00045
00046
00047
00048
00049 Timeout * _timeout;
00050
00051 void maybe_enable_lipc();
00052 void allow_lipc();
00053
00054 public:
00055
00056
00062 inline Sys_ipc_frame* rcv_regs() const;
00063
00073 inline void set_pagein_request(Address address, Mword error_code, Thread *notify);
00074
00080 inline bool in_long_ipc(Sender* sender) const;
00081
00085 inline Sender** sender_list();
00086
00087 inline void set_timeout(Timeout *t);
00088
00089 inline void reset_timeout();
00090
00099 inline int ipc_try_lock(const Sender* sender);
00100
00104 inline void ipc_init(Sender* sender);
00105
00107 inline void ipc_unlock();
00108
00109 protected:
00110
00111
00116 inline Receiver(Thread_lock *thread_lock, Space* space, unsigned short prio, unsigned short mcp, Unsigned64 quantum);
00117
00121 inline Sender* partner() const;
00122
00127 inline void restore_receiver_state(Sender* partner, Sys_ipc_frame* regs);
00128
00133 inline void save_receiver_state(Sender** out_partner, Sys_ipc_frame** out_regs);
00134
00137 inline void clear_pagein_request();
00138
00141 inline Address pagein_addr() const;
00142
00146 inline Mword pagein_error_code() const;
00147
00151 inline Thread* pagein_applicant();
00152
00153
00154 inline void set_rcv_regs(Sys_ipc_frame* regs);
00155
00159 inline void set_partner(Sender* partner);
00160
00170 inline void setup_receiver(Sender* sender, Sys_ipc_frame* regs);
00171
00180 inline unsigned setup_receiver_state(Sender* sender, Sys_ipc_frame* regs, bool = false);
00181
00185 inline void reload_ip_sp_from_utcb();
00186 };
00187
00188
00189
00190
00191
00192
00193 #include "l4_types.h"
00194 #include <cassert>
00195
00196 #include "globals.h"
00197 #include "sender.h"
00198 #include "thread_lock.h"
00199 #include "entry_frame.h"
00200 #include "std_macros.h"
00201 #include "thread_state.h"
00202
00203
00204
00205
00206
00207
00208
00209
00210
00217 inline Sys_ipc_frame*
00218 Receiver::rcv_regs() const
00219 {
00220 assert (state () & Thread_ipc_receiving_mask);
00221
00222 return _rcv_regs;
00223 }
00224
00225
00236 inline void
00237 Receiver::set_pagein_request(Address address, Mword error_code, Thread *notify)
00238 {
00239 assert (address != (Address) -1);
00240
00241 _pagein_applicant = notify;
00242 _pagein_addr = address;
00243 _pagein_error_code = error_code;
00244
00245 state_change (~Thread_busy_long, Thread_ready);
00246 }
00247
00248
00253 inline Sender*
00254 Receiver::partner() const
00255 {
00256 return _partner;
00257 }
00258
00259
00266 inline bool
00267 Receiver::in_long_ipc(Sender* sender) const
00268 {
00269 if (((state() & (Thread_rcvlong_in_progress|Thread_ipc_in_progress))
00270 != (Thread_rcvlong_in_progress|Thread_ipc_in_progress))
00271 || partner() != sender)
00272 return false;
00273
00274 return true;
00275 }
00276
00277
00278
00283 inline Sender**
00284 Receiver::sender_list()
00285 {
00286 return &_sender_first;
00287 }
00288
00289
00290
00291 inline void
00292 Receiver::set_timeout(Timeout *t)
00293 {
00294 _timeout = t;
00295 }
00296
00297
00298
00299 inline void
00300 Receiver::reset_timeout()
00301 {
00302 if (EXPECT_TRUE(!_timeout))
00303 return;
00304
00305 _timeout->reset();
00306 _timeout = 0;
00307 }
00308
00309
00317 inline bool
00318 Receiver::sender_ok(const Sender *sender) const
00319 {
00320 unsigned ipc_state = state() & (Thread_receiving |
00321 Thread_send_in_progress |
00322 Thread_ipc_in_progress);
00323
00324
00325 if (EXPECT_FALSE (ipc_state != (Thread_receiving | Thread_ipc_in_progress)))
00326 return false;
00327
00328
00329 if (EXPECT_TRUE(!partner()))
00330 #if 0
00331
00332 && (!_sender_first || sender == _sender_first)
00333 #endif
00334 return true;
00335
00336
00337 if (EXPECT_TRUE (sender == partner()))
00338 return true;
00339
00340 return false;
00341 }
00342
00343
00347 inline void
00348 Receiver::clear_pagein_request()
00349 {
00350 _pagein_addr = (Address) -1;
00351 _pagein_error_code = 0;
00352 }
00353
00354
00355
00365 inline int
00366 Receiver::ipc_try_lock(const Sender* sender)
00367 {
00368 if (EXPECT_FALSE (state() == Thread_invalid))
00369 return Ipc_err::Enot_existent;
00370
00371 thread_lock()->lock();
00372
00373 if (EXPECT_FALSE (!sender_ok (sender)))
00374 {
00375
00376
00377
00378
00379
00380
00381 deny_lipc_snd();
00382 thread_lock()->clear();
00383 return -1;
00384 }
00385
00386 return 0;
00387 }
00388
00389
00394 inline void
00395 Receiver::set_partner(Sender* partner)
00396 {
00397 _partner = partner;
00398 }
00399
00400
00405 inline void
00406 Receiver::ipc_init(Sender* sender)
00407 {
00408 deny_lipc();
00409 set_partner (sender);
00410 rcv_regs()->rcv_src (sender->id());
00411 clear_pagein_request();
00412 }
00413
00414
00417 inline void
00418 Receiver::ipc_unlock()
00419 {
00420 assert (thread_lock()->lock_owner() == current());
00421
00422 thread_lock()->clear();
00423 }
00424
00425
00426
00427
00433 inline Receiver::Receiver(Thread_lock *thread_lock,
00434 Space* space,
00435 unsigned short prio,
00436 unsigned short mcp,
00437 Unsigned64 quantum)
00438 : Context (thread_lock, space, prio, mcp, quantum)
00439 {}
00440
00441
00442
00443
00444 inline void
00445 Receiver::set_rcv_regs(Sys_ipc_frame* regs)
00446 {
00447 _rcv_regs = regs;
00448 }
00449
00450
00456 inline void
00457 Receiver::restore_receiver_state(Sender* partner,
00458 Sys_ipc_frame* regs)
00459 {
00460 set_partner (partner);
00461 set_rcv_regs (regs);
00462 }
00463
00464
00470 inline void
00471 Receiver::save_receiver_state(Sender** out_partner,
00472 Sys_ipc_frame** out_regs)
00473 {
00474 *out_partner = _partner;
00475 *out_regs = _rcv_regs;
00476 }
00477
00478
00482 inline Address
00483 Receiver::pagein_addr() const
00484 {
00485 return _pagein_addr;
00486 }
00487
00488
00493 inline Mword
00494 Receiver::pagein_error_code() const
00495 {
00496 return _pagein_error_code;
00497 }
00498
00499
00504 inline Thread*
00505 Receiver::pagein_applicant()
00506 {
00507 return _pagein_applicant;
00508 }
00509
00510
00520 inline unsigned
00521 Receiver::setup_receiver_state(Sender* sender,
00522 Sys_ipc_frame* regs,
00523 bool)
00524 {
00525 set_rcv_regs (regs);
00526 set_partner (sender);
00527 return Thread_receiving;
00528 }
00529
00530
00541 inline void
00542 Receiver::setup_receiver(Sender* sender,
00543 Sys_ipc_frame* regs)
00544 {
00545 state_add (setup_receiver_state(sender, regs));
00546 }
00547
00548
00553 inline void
00554 Receiver::reload_ip_sp_from_utcb() {}
00555
00556
00561 inline void
00562 Receiver::maybe_enable_lipc() {}
00563
00564
00565
00570 inline void
00571 Receiver::deny_lipc() {}
00572
00573
00578 inline void
00579 Receiver::allow_lipc() {}
00580
00581
00586 inline void
00587 Receiver::deny_lipc_snd() {}
00588
00589 #endif // receiver_h