Main Page | Modules | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

receiver.h

Go to the documentation of this file.
00001 // AUTOMATICALLY GENERATED -- DO NOT EDIT!         -*- c++ -*-
00002 
00003 #ifndef receiver_h
00004 #define receiver_h
00005 
00006 #include "context.h"
00007 #include "timeout.h"
00008 
00009 //
00010 // INTERFACE definition follows 
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   // DATA
00036   Sender*           _partner;   // IPC partner I'm waiting for/involved with
00037   Sys_ipc_frame    *_rcv_regs; // registers used for receive
00038   Address           _pagein_addr; // sender requests page in of this page
00039   Mword             _pagein_error_code;
00040   Thread*           _pagein_applicant;
00041   Sender*           _sender_first;
00042 
00043 protected:
00044   // XXX Timeout for both, sender and receiver! In normal case we would have
00045   // to define own timeouts in Receiver and Sender but because only one
00046   // timeout can be set at one time we use the same timeout. The timeout
00047   // has to be defined here because Dirq::hit has to be able to reset the
00048   // timeout (Irq::_irq_thread is of type Receiver).
00049   Timeout *          _timeout;
00050 
00051   void maybe_enable_lipc();
00052   void allow_lipc();
00053 
00054 public:  
00055   // Interface for senders
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   // Interface for receivers
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   // MANIPULATORS
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 // IMPLEMENTATION includes follow (for use by inline functions)
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 // IMPLEMENTATION of inline functions (and needed classes)
00205 //
00206 
00207 
00208 
00209 // Interface for senders
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   // If Thread_send_in_progress is still set, we're still in the send phase
00325   if (EXPECT_FALSE (ipc_state != (Thread_receiving | Thread_ipc_in_progress)))
00326     return false;
00327 
00328   // Check open wait; test if this sender is really the first in queue
00329   if (EXPECT_TRUE(!partner()))
00330 #if 0
00331     // disabled until Rene proposes a working patch for the wakeup problem
00332     && (!_sender_first || sender == _sender_first)
00333 #endif
00334     return true;
00335 
00336   // Check closed wait; test if this sender is really who we specified
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         Mark for the receiver that someone is waiting for him.
00377         If the receiver wants to do the next LIPC, 
00378         it will check, if someone is waiting for him.
00379         If yes, then abort LIPC and use normal kernel IPC.
00380       */
00381       deny_lipc_snd();
00382       thread_lock()->clear();
00383       return -1;
00384     }
00385 
00386   return 0;                     // OK
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 // Interface for receivers
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 // MANIPULATORS
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);  // message should be poked in here
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

Generated on Mon Sep 26 14:20:11 2005 for Fiasco by  doxygen 1.4.2