]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/system/FcfsArbiterC.nc
Add SharedArbiterC.
[tinyos-2.x.git] / tos / system / FcfsArbiterC.nc
index 386976c6ccf93da5981af520d2b5294f68d2a3e7..8476d4209c000e590c3103096ab1261b3caf3b9e 100644 (file)
  * Please refer to TEP 108 for more information about this component and its
  * intended use.<br><br>
  *
- * This component provides the Resource, ArbiterInfo, and Resource
- * Controller interfaces and uses the ResourceConfigure interface as
+ * This component provides the Resource, ArbiterInfo, and ResourceDefaultOwner
+ * interfaces and uses the ResourceConfigure interface as
  * described in TEP 108.  It provides arbitration to a shared resource in
  * an FCFS fashion.  An array is used to keep track of which users have put
  * in requests for the resource.  Upon the release of the resource by one
  * of these users, the array is checked and the next user (in FCFS order)
  * that has a pending request will ge granted control of the resource.  If
- * there are no pending requests, then the resource becomes idle and any
- * user can put in a request and immediately receive access to the
- * Resource.
+ * there are no pending requests, then the resource is granted to the default 
+ * user.  If a new request is made, the default user will release the resource, 
+ * and it will be granted to the requesting cleint.
  *
  * @param <b>resourceName</b> -- The name of the Resource being shared
  * 
  * @author Kevin Klues (klues@tkn.tu-berlin.de)
- * @author Philip Levis
  */
  
-generic module FcfsArbiterC(char resourceName[]) {
+generic configuration FcfsArbiterC(char resourceName[]) {
   provides {
-    interface Init;
     interface Resource[uint8_t id];
-    interface ResourceController;
+    interface ResourceRequested[uint8_t id];
+    interface ResourceDefaultOwner;
     interface ArbiterInfo;
   }
-  uses {
-    interface ResourceConfigure[uint8_t id];
-  }
+  uses interface ResourceConfigure[uint8_t id];
 }
 implementation {
+  components MainC;
+  components new FcfsResourceQueueC(uniqueCount(resourceName)) as Queue;
+  components new ArbiterP(uniqueCount(resourceName)) as Arbiter;
 
-  enum {RES_IDLE, RES_GRANTING, RES_BUSY};
-  enum {NO_RES = 0xFF};
-  enum {CONTROLLER_ID = uniqueCount(resourceName) + 1};
-
-  uint8_t state = RES_IDLE;
-  uint8_t resId = NO_RES;
-  uint8_t reqResId = NO_RES;
-  uint8_t resQ[uniqueCount(resourceName)];
-  uint8_t qHead = NO_RES;
-  uint8_t qTail = NO_RES;
-  bool irp = FALSE;
-  
-  task void grantedTask();
-  task void requestedTask();
-  error_t queueRequest(uint8_t id);
-  void grantNextRequest();
-  
-  bool requested(uint8_t id) {
-    return resQ[id] != NO_RES || qTail == id;
-  }
-
-  /**  
-    Initialize the Arbiter to the idle state
-  */
-  command error_t Init.init() {
-    memset( resQ, NO_RES, sizeof( resQ ) );
-    return SUCCESS;
-  }  
-  
-  /**
-    Request the use of the shared resource
-    
-    If the user has not already requested access to the 
-    resource, the request will be either served immediately 
-    or queued for later service in an FCFS fashion.  
-    A SUCCESS value will be returned and the user will receive 
-    the granted() event in synchronous context once it has 
-    been given access to the resource.
-    
-    Whenever requests are queued, the current owner of the bus 
-    will receive a requested() event, notifying him that another
-    user would like to have access to the resource.
-    
-    If the user has already requested access to the resource and
-    is waiting on a pending granted() event, an EBUSY value will 
-    be returned to the caller.
-  */
-  async command error_t Resource.request[uint8_t id]() {
-    atomic {
-      if( state == RES_IDLE ) {
-        state = RES_GRANTING;
-        reqResId = id;
-        post grantedTask();
-        return SUCCESS;
-      }
-      if(resId == CONTROLLER_ID)
-        post requestedTask();
-      return queueRequest( id );
-    }
-  } 
-
-  async command error_t ResourceController.request() {
-    return call Resource.request[CONTROLLER_ID]();
-  }
-  
-  /**
-  * Request immediate access to the shared resource.  Requests are
-  * not queued, and no granted event is returned.  A return value 
-  * of SUCCESS signifies that the resource has been granted to you,
-  * while a return value of EBUSY signifies that the resource is 
-  * currently being used.
-  */
-  uint8_t tryImmediateRequest(uint8_t id) {
-    atomic {
-      if( state == RES_IDLE ) {
-        state = RES_BUSY;
-        resId = id;
-        return id;
-      }
-      return resId;
-    }     
-  }
-  async command error_t Resource.immediateRequest[uint8_t id]() {
-    uint8_t ownerId = tryImmediateRequest(id);
-
-    if(ownerId == id) {
-      call ResourceConfigure.configure[id]();
-      return SUCCESS;
-    }
-    else if(ownerId == CONTROLLER_ID){
-      atomic {
-        irp = TRUE;  //indicate that immediateRequest is pending
-        reqResId = id; //Id to grant resource to if can
-      }  
-      signal ResourceController.requested();
-      atomic {
-        ownerId = resId;   //See if I have been granted the resource
-        irp = FALSE;  //Indicate that immediate request no longer pending
-      }
-      if(ownerId == id) {
-        call ResourceConfigure.configure[id]();
-        return SUCCESS;
-      }
-      return EBUSY;
-    }
-    else return EBUSY;
-  }  
-  async command error_t ResourceController.immediateRequest() {
-    return call Resource.immediateRequest[CONTROLLER_ID]();
-  }
-  /**
-    Release the use of the shared resource
-    
-    The resource will only actually be released if
-    there are no pending requests for the resource.
-    If requests are pending, then the next pending request
-    will be serviced, according to a Fist come first serve
-    arbitration scheme.  If no requests are currently 
-    pending, then the resource is released, and any 
-    users can put in a request for immediate access to 
-    the resource.
-  */
-  async command void Resource.release[uint8_t id]() {
-    uint8_t currentState;
-    atomic {
-      if (state == RES_BUSY && resId == id) {
-        if (irp)
-          resId = reqResId;
-       else grantNextRequest();
-       call ResourceConfigure.unconfigure[id]();
-      }
-      currentState = state;
-    }
-    if(currentState == RES_IDLE)
-      signal ResourceController.idle();
-  } 
-  async command void ResourceController.release() {
-    call Resource.release[CONTROLLER_ID]();
-  }
-    
-  /**
-    Check if the Resource is currently in use
-  */    
-  async command bool ArbiterInfo.inUse() {
-    atomic {
-      if ( state == RES_IDLE )
-        return FALSE;
-    }
-    return TRUE;
-  }
-
-  /**
-    Returns the current user of the Resource.
-    If there is no current user, the return value
-    will be 0xFF
-  */      
-  async command uint8_t ArbiterInfo.userId() {
-    atomic return resId;
-  }
+  MainC.SoftwareInit -> Queue;
 
-  /**
-   * Returns my user id.
-   */      
-  async command uint8_t Resource.isOwner[uint8_t id]() {
-    atomic {
-      if(resId == id) return TRUE;
-      else return FALSE;
-    }
-  }
-  async command uint8_t ResourceController.isOwner() {
-    return call Resource.isOwner[CONTROLLER_ID]();
-  }
-  
-  //Grant a request to the next Pending user
-    //in FCFS order
-  void grantNextRequest() {
-    resId = NO_RES;
-    if(qHead != NO_RES) {
-      uint8_t id = qHead;
-      qHead = resQ[qHead];
-      if(qHead == NO_RES)
-        qTail = NO_RES;
-      resQ[id] = NO_RES;
-      reqResId = id;
-      state = RES_GRANTING;
-      post grantedTask();
-    }
-    else {
-      state = RES_IDLE;
-    }
-  }
-  
-  //Queue the requests so that they can be granted
-    //in FCFS order after release of the resource
-  error_t queueRequest(uint8_t id) {
-    atomic {
-      if( !requested( id ) ) { 
-             if(qHead == NO_RES )
-               qHead = id;
-             else
-               resQ[qTail] = id;
-             qTail = id;
-        return SUCCESS;
-      }
-      return EBUSY;
-    }
-  }
-  
-  //Task for pulling the Resource.granted() signal
-    //into synchronous context  
-  task void grantedTask() {
-    uint8_t tmpId;
-    atomic {
-      tmpId = resId = reqResId;
-      state = RES_BUSY;
-    }
-    call ResourceConfigure.configure[tmpId]();
-    signal Resource.granted[tmpId]();
-  }
+  Resource = Arbiter;
+  ResourceRequested = Arbiter;
+  ResourceDefaultOwner = Arbiter;
+  ArbiterInfo = Arbiter;
+  ResourceConfigure = Arbiter;
 
-  //Task for pulling the ResourceController.requested() signal
-    //into synchronous context  
-  task void requestedTask() {
-    uint8_t tmpId;
-    atomic {
-      tmpId = resId;
-    }
-    if(tmpId == CONTROLLER_ID)
-      signal ResourceController.requested();
-  }
-  
-  //Default event/command handlers for all of the other
-    //potential users/providers of the parameterized interfaces 
-    //that have not been connected to.  
-  default event void Resource.granted[uint8_t id]() {
-    signal ResourceController.granted();
-  }
-  default event void ResourceController.granted() {
-  }
-  default async event void ResourceController.requested() {
-  }
-  default async event void ResourceController.idle() {
-  }
-  default async command void ResourceConfigure.configure[uint8_t id]() {
-  }
-  default async command void ResourceConfigure.unconfigure[uint8_t id]() {
-  }
+  Arbiter.Queue -> Queue;
 }