next up previous contents
Next: 5.2.1 Kernel-User interface Up: 5. Implementing abstract resources Previous: 5.1.4.2 Shuttles for ix86

5.2 Portals

\Note{Must provide a prtl instance. Implement upcall too!

A portal is a communication endpoint. It can be attached to a handler and also invoked like an interrupt. Portals are contained in the portal server, an instance of the PrtlSrv class whose main task is to allocate portals.

<Off portal server. >=
// A portal server. 
//
class off_PrtlSrv : public off_AbsCompResource {
public:
  // Allocates a portal.
  off_Prtl *alloc(const off_Protection &p, 
                  natural_t n=1, off_prtl_id_t at=OFF_PRTL_NULL);
  // Deallocates a portal
  void free(off_Prtl *p, natural_t n=1);
  // Gets a portal by its number
  off_Prtl *operator+(vm_offset_t p) ;
  off_Prtl *operator+(off_prtl_id_t p);

  <Other public methods of off_PrtlSrv. >

};
Defines off_PrtlSrv (links are to index).

Portals support both protected control transfers (PCTs) and asynchronous message delivering.

<Other public methods of off_PrtlSrv. >= (<-U)
//  Delivers a message to this portal using a PCT. 
// (May reset the stack)
err_t pct(off_prtl_id_t p, vm_size_t msz, vm_size_t rsz,
          off_Msg *msg, off_Msg *reply, natural_t tmout);

// Pass the PCT to a different portal.
// Reply to the initial PCT will be issued from there. (May reset the stack)
err_t pct_pass(const off_shtl_id_t &sender, off_prtl_id_t p,
               vm_size_t msz, vm_size_t rsz,
               off_Msg *msg, off_Msg *reply, natural_t tmout );

// Returns from a PCT.
err_t pct_ret(void);

When used for PCTs, the sender shuttle changes its properties on the fly and becomes itself a flow of control in the receiver protection domain. After the handler completes, the shuttle recovers its original state and continues its execution.

Callees may, at any time, delegate the execution of PCTs to other servers. In this case, one single shuttle can cross several protection domains and come back directly to its original site. To delegate a PCT reply to a different server, pct_pass can be used.

Finally, when no reply is ever expected, deliver should be used instead. It will simply save (in the callee context) what users are unable to save safely (like eflags on Intel architectures) and install a simple activation frame for the handler on the receiver's shuttle. In this case, the caller will resume execution as soon as the callee has been notified; the message is sent but may be not delivered yet.

The handler information present in the portal is basically a program counter (pc), a pointer to a pool of stack pointers (spp), an access mode mode, and an (optional) set of properties (props). Each property value in props will cause the sender's property to be set to that value during portal invocation. Remaining sender properties will maintain their original value. As it is most likely that the address space property (see section [*]) will be present, that property is factored out of the property array to gain some performance. On nodes where the kernel is compiled without support for multiple protection domains, a null value is used the such property is ignored. When the props set is not present in the portal, it will not support PCTs but just asynchronous message delivering.

That is enough to support PCTs, but for asynchronous message delivering it is necessary that the portal have a shuttle identifier. Thus, when deliver is used, the handler (known by the portal information) will run not on the sender shuttle but on the receiver. If the receiver shuttle identifier is not specified, the portal will not support asynchronous delivering.

<Off portal. >=
// A portal.
// 
class off_Prtl : public AbsResUnit {
private:
  <Other off_Prtl private members. >
public:
  // Creates a portal.
  off_Prtl(const off_Protection &p, 
           const off_prtl_id_t &domain,
           const off_EventHandler *h,
           vm_offset_t stack_pointers_pool,
           off_mode_t mode,
           natural_t maxmsgsz=0,
           const off_ShtlProp  *props=NULL, 
           off_shtl_id_t s=OFF_SHTL_NULL   );

  // (Re)sets the portal handler.
  err_t set_hndlr(vm_offset_t pc, vm_offset_t spp, off_mode_t mode,
                  off_dtlb_id_t vas, natural_t maxmsgsz=0,
                  const off_ShtlProp  *props=NULL, 
                  off_shtl_id_t s=OFF_SHTL_NULL);

  // (Locally) delivers a message to this portal using a PCT. 
  // (May reset the stack)
  err_t pct(off_Shtl *sender, vm_offset_t msz, vm_offset_t rsz,
            Msg *msg, Msg *reply, natural_t tmout) const; 

  // Pass the PCT to a different portal.
  // Reply to the initial PCT will be issued from there. (May reset the stack)
  err_t pct_pass(off_Shtl &sender, off_prtl_id_t p) const;

  // Delivers an event to a portal (one-way PCT).
  // (May reset the stack)
  err_t deliver(off_Shtl &sender, vm_offset_t msz, 
                Msg *rq_msg, natural_t tmout) const;

  <Other public methods of off_Prtl. >

};
Defines off_Prtl (links are to index).

There are specialized versions of pct and deliver for use inside the kernel.

<Other public methods of off_Prtl. >= (<-U)
// (Locally) delivers a message to this portal using a PCT. 
// (May reset the stack)
err_t kpct(off_Shtl &sender, vm_offset_t msz, vm_offset_t rsz,
           Msg *msg, Msg *reply, natural_t tmout) const; 

// Delivers an event to a portal (one-way PCT).
// (May reset the stack)
err_t kdeliver(off_Shtl &sender, vm_offset_t msz, 
               Msg *rq_msg, natural_t tmout) const;

Portals may be used to enforce object access control. When the handler is attached to the portal, the permitted access mode through this portal is specified. The kernel does not enforce it. Instead, the access mode will be placed in a pre-specified register so that the user handler can check the validity of the access. For example, a file object may create a read-only access point using a portal specifying OFF_OP_R as the only permitted access mode. We could have omitted this access mode feature from portals, but it does not change the portal semantics and avoid those calls which will fail to proceed further.

The stack pool pointer (spp) portal member points to an array of initial stack pointers provided by the handler. Each incoming invocation will use, as its own user stack, one of the stacks found there. The pool of stacks can be of any length, but it is assumed that the last stack pointer will be invalid and its value will be 1.

Upon portal invocation, the kernel selects one of the non-zero pointers found in the pool and then resets it to 0. Since a stack pointer with value 0 will be ignored, this is a safe mechanism to avoid race conditions during stack selection. To allow the stack to be reused, the user-level handler must (atomically) write the original stack pointer value back to the stack pool.

When there are no more free stacks, any further call on the portal blocks. These blocked shuttles are queued (using shuttle identifiers instead of pointers, so that the list can span several nodes) using the p_wstack private member. When a new stack is made available, they are awakened.

<Other off_Prtl private members. >= (<-U)
  off_Bureaucrat p_wstack; // No stack available on a PCT portal

\subsection{Portals for plain users}

The portal server has a ``conventional'' wrapper.

<Off portal server for users. >=
ENTRY class off_uPrtlSrv : public off_uAbsCompResource {
public: 
  off_uPrtl *alloc(const off_Protection &prot,
                   natural_t n=1, off_prtl_id_t at=OFF_PRTL_NULL);
  void free(off_uPrtl *p, natural_t n=1, const off_Rights &r);

  off_uPrtl *operator [](off_prtl_id_t id, const off_Rights &r);
};
Defines off_uPrtlSrv (links are to index).

The portal wrapper is the most special one in the kernel. Only the non-delivering methods are exported to users as usually. Methods used for message delivering and PCT are implemented without wrapper services (because they are used to implement the portal delivering mechanism used by the wrappers).

<Off portal for users. >=
ENTRY class off_uPrtl : public uAbsResUnit {
public:
  // (Re)sets the portal handler.
  void set_hndlr(vm_offset_t pc, vm_offset_t spp, off_mode_t mode,
                 off_dtlb_id_t vas, natural_t maxmsgsz=0,
                 const off_ShtlPSet  *props=NULL, 
                 off_shtl_id_t s=OFF_SHTL_NULL,
                 const off_Rights &prtl_r, const off_Rights &shtl_r,
                 const off_Rights &dtlb_r);

};
Defines off_uPrtl (links are to index).

%\Note{Should perform access checking for properties passed in props.



 
next up previous contents
Next: 5.2.1 Kernel-User interface Up: 5. Implementing abstract resources Previous: 5.1.4.2 Shuttles for ix86
Francisco J. Ballesteros
1998-05-25