next up previous contents
Next: 2.4.3 Resource availability Up: 2.4 System resources Previous: 2.4.1 Identifiers

2.4.2 Containers and resource units

Resources are arranged as recursive containers, being the node the outermost one2.9. Resource containers are identified with off_id_t. Such identifier will usually correspond with the identifier of the portal used by the container to accept user requests.

These containers delegate allocation to an Allocator object which can (and will) be further wrapped2.10 to delegate usage statistics to a bookkeeper. See figure [*].


  
Figure 2.4: Containers and allocators

<Off compound resource. >= (U->)
// Compound resource. Uses an allocator to allocate resource units. 
class off_CompResource : public off_Resource {
protected:
  <Other protected members of off_CompResource. >
  <Other protected methods of off_CompResource. >
public:
  // Dumps it.
  friend OStr &operator<<(OStr &s, const off_CompResource &r);

};

Defines off_CompResource (links are to index).

<Off compound resource dependencies. >= (U->) [D->]
#include <klib/ids.h>           // for off_id_t et al.
#include <klib/Resource.h>      // for off_Resource
#include <klib/Allocator.h>     // for off_Allocator.

As any other resource, resource containers are created with a given protection and domain. However, for resource containers a portal identifier (corresponding to a valid portal) must be provided too. It will be used as the resource container identifier.

<Other protected methods of off_CompResource. >= (<-U) [D->]
// Creates a CompResource.
off_CompResource::off_CompResource(const off_Protection &p, 
                                   const off_prtl_id_t &domain,
                                   const off_prtl_id_t &id,
                                   const off_magic_t magic        ) :
                  off_Resource(p,domain,id,magic)
{do_debug(putchar('c'));}

<Off compound resource dependencies. >+= (U->) [<-D->]
#include <flux/debug.h>         // for do_debug et al.

Specific resource units maintain a reference to their container. Concrete subclasses also redefine the new operator so that it could be used to allocate resource units from a container's pool. This way we can avoid memory fragmentation.

<Off elementary resource unit. >= (U->)
// Elementary resource unit.
class off_ResUnit : public off_Resource {
private:
  off_CompResource *r_container; // Container for this resource unit. 
protected:
  void set_container(off_CompResource *c) { r_container=c; }
  //Creates a resource unit.
  off_ResUnit(const off_Protection &p, const off_prtl_id_t &domain, 
              const off_id_t &id,
              const off_magic_t magic,
              off_CompResource *container ):
    off_Resource(p,domain,id,magic),
    r_container(container)
  {;}

  <Other protected methods of off_ResUnit. >
public:
  off_CompResource *get_container(void) const { return r_container; }

  <Other public methods of off_ResUnit. >
};

Defines off_ResUnit (links are to index).

<Off elementary resource unit dependencies. >= (U->)
#include <klib/Resource.h>      // for off_Resource
#include <klib/CompResource.h>  // for off_CompResource

Resource units should be pre-initialized by their containers so that only a protection and domain be needed at resource allocation time (the identifier, magic number and container reference will always remain the same but for cached resource units). Be they pre-initialized, this constructor shall be used.

<Other protected methods of off_ResUnit. >= (<-U) [D->]
// Creates a pre-initialized resource unit. 
off_ResUnit(const off_Protection &p,  const off_prtl_id_t &domain) :
  off_Resource(p,domain)
{;}

A new Resource constructor is needed.

<Other protected methods of off_Resource. >+= (<-U) [<-D->]
// Creates a pre-initialized resource. 
off_Resource(const off_Protection &p,  const off_prtl_id_t &domain) :
  r_domain(domain)
{
   <Off initialization for p protected objects. >
}

To pre-initialize a resource unit, this constructor is given so that the reference to the container, domain and magic number can be pre-set.

<Other protected methods of off_ResUnit. >+= (<-U) [<-D->]
// Pre-initializes a resource unit. 
off_ResUnit(const  off_id_t &id,
            const off_magic_t magic,
            off_CompResource *container ) :
  off_Resource(id,magic),
  r_container(container)
{;}

A new constructor is now needed for Resources.

<Other protected methods of off_Resource. >+= (<-U) [<-D->]
// Pre-initializes a resource
off_Resource(const off_id_t &id, const off_magic_t magic) :
  <Off initialization for integrity checked resources with magic. >,
  r_id(id)
{;}

When resource units are destroyed, their domain is reset to a null domain and protection is reset.

<Other public methods of off_ResUnit. >= (<-U) [D->]
// Destroyes the resource.
virtual ~off_ResUnit(void);

<off_ResUnit::~off_ResUnit implementation. >= (U->)
// Destroyes the resource.
off_ResUnit::~off_ResUnit(void)
{
  set_domain(OFF_PRTL_NULL);
  protect(off_Protection());
}

The make_available method is provided by containers to allow remote resource units to be available (by caching them) in the local node. All make_available does is to implement the algorithm shown in section [*]. It uses is_local to determine if the specified resource unit is local or not.

<Implementation of off_CompResource::make_available. >=
// We may wish to cache a resource unit.
// Returns error code if the resource is not available. Zero otherwise.
err_t make_available(off_id_t &u ) 
{
  <Body of off_CompResource::make_available. >
}

<Body of off_CompResource::make_available. >= (<-U)
if ( is_local(u)                          ||   // It is local
     c_reloc.is_relocated(u) && is_local(u))   // It is cached
  return EOK;
else 
  return c_reloc.missing(OFF_PRTL_NULL,get_umagic(),u); // XXX use ex. prtl.
     // Usr. could fetch the unit.

Where get_umagic is a new virtual method to be provided by resource containers. It returns the magic for contained resource units.

<Other protected methods of off_CompResource. >+= (<-U) [<-D]
virtual off_magic_t get_umagic(void)=0;

<Off compound resource dependencies. >+= (U->) [<-D->]
#include <klib/Magic.h>         // for off_Magic
#include <klib/err.h>           // for err_t and error numbers.

To do so, the container needs a relocation table. Such table maintains the correspondence between the remote resource unit and the local resource unit used as a cache (remember that the kernel does not implement any particular coherence or concurrency control protocol). There is a single relocation table per node which is shared among every container.

<Other protected members of off_CompResource. >= (<-U)
static off_RelocTbl c_reloc;  // relocation table.

<Off compound resource dependencies. >+= (U->) [<-D->]
#include <klib/RelocTbl.h>    // for off_RelocTbl

The relocation table uses the kernel virtual memory manager, KVM, and the core memory bank, MBank, to allocate page frames. They will be described later.

<Off compound resource static members. >= (U->)

off_RelocTbl off_CompResource::c_reloc;

<Off compound resource implementation dependencies. >= (U->)
#include <hw/MBank.h>           // for off_MBank
#include <dmm/KVM.h>            // for off_KVM

Now that we have shown how make_available is implemented, we have to say that it is not implemented by CompResource. It is implemented by subclasses of CompResource instead. The rationale is that make available depends on is_local, which must be implemented by the allocator containing the resource units. Taking into account that there will be few subclasses of CompResource, we can avoid dynamic dispatching plus extra indirections to access the allocator by moving both the allocator and is_local to CompResource subclasses.

Some debug aids are provided.

<off_CompResource::operator<< implementation. >= (U->)
// Dumps the resource.
OStr &operator<<(OStr &s, const off_CompResource &r)
{
  s << *(off_Resource*)&r;
  return s;
}

Names and URLs for resource units are obtained using those of their containers.

<Other public methods of off_ResUnit. >+= (<-U) [<-D]
// Get the resource unit URL.
const char *get_url(void);
// Returns the resource unit name. 
// The caller should delete the given name after use. 
const char *nameof(void);

The name of a resource unit is that of its container complemented with a printable representation of its address. The URL is built in a similar way.

Names for resource units are created on demand. The caller of nameof must delete the name after using it.

<off_ResUnit::nameof implementation. >= (U->)
// Returns the resource name. 
const char *off_ResUnit::nameof(void)
{
  extern void *operator new(size_t s);
  char *name;

  name = new char[strlen(get_container()->nameof())+10]; 
                                                   // '/'+ 8 hex digits + 0
  if (name)
    sprintf(name,"%s/%08lx",get_container()->nameof(),(natural_t)get_id());
  return name;
}

Since every concrete resource unit instance shares the URL with other instances of the same resource, the URL is synthesized on demand and is kept in a static member of every concrete Resource unit. A reference to such static member is obtained through this private method. Besides, the relative URL for the container must be known; it is supplied by another protected method.

<Other protected methods of off_ResUnit. >+= (<-U) [<-D]
virtual char *&get_url_holder(void)=0;
virtual const char *get_rurl(void) const =0;

<off_ResUnit::get_url implementation. >= (U->)
// Get the resource unit URL.
const char *off_ResUnit::get_url(void)
{

  if (!get_url_holder()){
    get_url_holder() = new 
      char[strlen(get_container()->get_url())+strlen(get_rurl())]; 
    if (get_url_holder())
      sprintf(get_url_holder(),"%s%s",get_container()->get_url(),get_rurl());
  }
  return get_url_holder();
}

\subsubsection{Compound resources and resource units for plain users}

Compound resources export to users the allocation information found in the CompResource allocator. They also export get_id.

<Off compound resource for users. >= (U->)
// Compoud resource for users.
//
class off_uCompResource : public off_uResource {
public:
  off_id_t  get_id(const off_Rights &r) const;
};

Defines off_uCompResource (links are to index).

We do not export to users anything besides that exported by a Resource in ResUnit system objects.

<Off elementary resource unit for users. >= (U->)
// Elementary resource unit for users.
//
class off_uResUnit : public off_uResource {
};

Defines off_uResUnit (links are to index).

\subsubsection{Compound resources and resource units \cpp{} source files}

Compound resource source code is kept in CompResource.h and CompResource.C.

<CompResource.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_COMP_RESOURCE_H
#define __OFF_COMP_RESOURCE_H 1

<Off compound resource dependencies. >

#ifdef __KERNEL__
<Off compound resource. >
#endif
<Off compound resource for users. >

#endif // __OFF_COMP_RESOURCE_H

<CompResource.C*>=
<Read the literate code instead warning. >

#include <klib/CompResource.h>  // Exported interface
<Off compound resource implementation dependencies. >

<Off compound resource static members. >

<off_CompResource::operator<< implementation. >

Resource unit code is kept in ResUnit.h and ResUnit.C.

<ResUnit.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_RES_UNIT_H
#define __OFF_RES_UNIT_H 1

<Off elementary resource unit dependencies. >

#ifdef __KERNEL__
<Off elementary resource unit. >
#endif
<Off elementary resource unit for users. >

#endif // __OFF_RES_UNIT_H

<ResUnit.C*>=
<Read the literate code instead warning. >

#include <klib/ResUnit.h>       // Exported interface

<off_ResUnit::~off_ResUnit implementation. >
<off_ResUnit::nameof implementation. >
<off_ResUnit::get_url implementation. >


next up previous contents
Next: 2.4.3 Resource availability Up: 2.4 System resources Previous: 2.4.1 Identifiers
Francisco J. Ballesteros
1998-05-25