]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/system/RoundRobinArbiterC.nc
Update of files to align them with TEP108 changes to ResourceController interface...
[tinyos-2.x.git] / tos / system / RoundRobinArbiterC.nc
index 921bd5249d80532c78524e8e4c11022097f14977..9f52ed8f0b3f592a3a77048a323ef91f1fc2c1a9 100644 (file)
  *
  * This component provides the Resource, ArbiterInfo, and Resource
  * Controller interfaces and uses the ResourceConfigure interface as
- * described in TEP 108.  It provides arbitration to a shared resource in a
- * round robin 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 round
- * robin 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 round robin order * Resource.
+ * 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.
  *
  * @param <b>resourceName</b> -- The name of the Resource being shared
  * 
  * @author Kevin Klues (klues@tkn.tu-berlin.de)
- * @author Philip Levis
  */
  
-generic module RoundRobinArbiterC(char resourceName[]) {
+generic configuration RoundRobinArbiterC(char resourceName[]) {
   provides {
-    interface Init @atleastonce();
     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 {
-  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;
-  uint8_t request[(uniqueCount(resourceName)-1)/8 + 1];
-  bool irp = FALSE;
-  
-  task void grantedTask();
-  task void requestedTask();
-  void grantNextRequest();
-  
-  /**  
-       Initialize the Arbiter to the idle state
-  */
-  command error_t Init.init() {
-    return SUCCESS;
-  }
-
-  uint8_t requested(uint8_t id) {
-    return request[id / 8] & (1 << (id % 8));
-  }
-
-  void clearRequest(uint8_t id) {
-    request[id / 8] &= ~(1 << (id % 8));
-  }
-  
-  error_t queueRequest(uint8_t id) {
-    if (!requested(id)){
-           request[id / 8] |=  1 << (id % 8);
-      return SUCCESS;
-    }
-    return EBUSY;
-  }
-  
-  /**
-     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 a round robin 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 round robin 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();
-  }
+  components MainC;
+  components new RoundRobinResourceQueueC(uniqueCount(resourceName)) as Queue;
+  components new ArbiterP(uniqueCount(resourceName)) as Arbiter;
 
-  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 Round-Robin order
-  void grantNextRequest() {
-    int i;
-    
-    for (i = resId + 1; ; i++) {
-           if (i >= (uniqueCount(resourceName) + 1))
-             i = 0;
-           if (i == resId)
-             break;
-           if (requested(i)) {
-             reqResId = i;
-             clearRequest(i);
-        resId = NO_RES;
-        state = RES_GRANTING;
-             post grantedTask();
-             return;
-           }  
-    }
-    resId = NO_RES;
-    state = RES_IDLE;
-  }
-  
-  //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;
 }