]> oss.titaniummirror.com Git - tinyos-2.x.git/commitdiff
Add SharedArbiterC.
authorR. Steve McKown <rsmckown@gmail.com>
Wed, 15 Sep 2010 18:44:11 +0000 (12:44 -0600)
committerR. Steve McKown <rsmckown@gmail.com>
Mon, 9 Jul 2012 16:34:43 +0000 (10:34 -0600)
tos/system/SharedArbiterC.nc [new file with mode: 0644]
tos/system/SharedArbiterP.nc [new file with mode: 0644]

diff --git a/tos/system/SharedArbiterC.nc b/tos/system/SharedArbiterC.nc
new file mode 100644 (file)
index 0000000..1949978
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universität Berlin nor the names
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * A shared arbiter that allows 1...N clients to acquire the resource
+ * simultaneously, with the intention of returning control to the default
+ * owner upon release by all clients.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+generic configuration SharedArbiterC(char resourceName[]) {
+  provides {
+    interface Resource[uint8_t id];
+    interface ResourceDefaultOwner;
+    interface ArbiterInfo;
+  }
+}
+implementation {
+  enum { CLIENTS = uniqueCount(resourceName) };
+
+  components new SharedArbiterP();
+  Resource = SharedArbiterP;
+  ResourceDefaultOwner = SharedArbiterP;
+  ArbiterInfo = SharedArbiterP;
+
+  components new BitVectorC(CLIENTS) as GrantedVectorC;
+  SharedArbiterP.GrantedVector -> GrantedVectorC;
+
+  components new BitVectorC(CLIENTS) as RequestingVectorC;
+  SharedArbiterP.RequestingVector -> RequestingVectorC;
+
+  components new StateC();
+  SharedArbiterP.State -> StateC;
+}
diff --git a/tos/system/SharedArbiterP.nc b/tos/system/SharedArbiterP.nc
new file mode 100644 (file)
index 0000000..b912fa1
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2010, Titanium Mirror, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Technische Universität Berlin nor the names
+ *   of its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * A shared arbiter that allows 1...N clients to acquire the resource
+ * simultaneously.  The purpose of this arbiter to allow access to a shared,
+ * switched subsystem.  For example, a communications bus that can handle IO
+ * for multiple clients simultaneously, but is powered down when not in use.
+ *
+ * @author R. Steve McKown <rsmckown@gmail.com>
+ */
+
+generic module SharedArbiterP() {
+  provides {
+    interface Resource[uint8_t id];
+    interface ResourceDefaultOwner;
+    interface ArbiterInfo;
+  }
+  uses {
+    interface BitVector as GrantedVector;
+    interface BitVector as RequestingVector;
+    interface State;
+  }
+}
+implementation {
+  enum {
+    S_IDLE = 0,                /* Resource is not in use; owned by default owner */
+    S_REQUESTING,      /* Requesting the resource from the default owner */
+    S_IMMREQUESTING,   /* Immediate resource request from the default owner */
+    S_GRANTED,         /* One or more clients have been granted the resource */
+
+    NO_CLIENT = 0xff,
+  };
+
+  uint8_t m_granted;   /* Count of clients granted the resource */
+  uint8_t m_requesting;        /* Count of clients requesting the resource */
+
+  uint8_t addRequesting(uint8_t id)
+  {
+    atomic {
+      call RequestingVector.set(id);
+      return ++m_requesting;
+    }
+  }
+
+  uint8_t rmRequesting(uint8_t id)
+  {
+    atomic {
+      call RequestingVector.clear(id);
+      return --m_requesting;
+    }
+  }
+
+  uint8_t addGranted(uint8_t id)
+  {
+    atomic {
+      call GrantedVector.set(id);
+      return ++m_granted;
+    }
+  }
+
+  uint8_t rmGranted(uint8_t id)
+  {
+    atomic {
+      call GrantedVector.clear(id);
+      return --m_granted;
+    }
+  }
+
+  task void grantedTask()
+  {
+    unsigned id;
+
+    atomic {
+      if (m_requesting == 0)
+       return;
+    }
+
+    for (id = 0; id < call RequestingVector.size(); id++) {
+      bool grant = FALSE;
+
+      atomic {
+       if (call RequestingVector.get(id)) {
+         rmRequesting(id);
+         addGranted(id);
+         grant = TRUE;
+       }
+      }
+      if (grant)
+       signal Resource.granted[id]();
+    }
+  }
+
+  async command error_t Resource.request[uint8_t id]()
+  {
+    /* The Resource docs do not say what happens when a user calls
+     * Resource.request() after the resource has already been granted.  We
+     * elect to call EBUSY, as if the request was still in process.
+     */
+    if (call RequestingVector.get(id) || call GrantedVector.get(id))
+      return EBUSY;
+
+    addRequesting(id);
+    if (call State.requestState(S_REQUESTING) == SUCCESS)
+      signal ResourceDefaultOwner.requested();
+    else if (call State.isState(S_GRANTED))
+      post grantedTask();
+    return SUCCESS;
+  }
+
+  async command error_t Resource.immediateRequest[uint8_t id]()
+  {
+    /* The Resource docs do not say what happens when a user calls
+     * Resource.request() after the resource has already been granted.  We
+     * elect to call EBUSY, as if the request was still in process.
+     */
+    if (call RequestingVector.get(id) || call GrantedVector.get(id))
+      return EBUSY;
+
+    if (call State.requestState(S_IMMREQUESTING) == SUCCESS) {
+      signal ResourceDefaultOwner.immediateRequested();
+      if (call State.isState(S_IMMREQUESTING))
+       call State.toIdle();
+    }
+    if (call State.isState(S_GRANTED)) {
+      addGranted(id);
+      return SUCCESS;
+    }
+    return FAIL;
+  }
+
+  async command error_t Resource.release[uint8_t id]()
+  {
+    if (!call GrantedVector.get(id))
+      return FAIL;
+
+    if (rmGranted(id) == 0) {
+      call State.toIdle();
+      signal ResourceDefaultOwner.granted();
+    }
+    return SUCCESS;
+  }
+
+  async command error_t ResourceDefaultOwner.release()
+  {
+    if (call State.isState(S_REQUESTING)) {
+      call State.forceState(S_GRANTED);
+      post grantedTask();
+      return SUCCESS;
+    } else if (call State.isState(S_IMMREQUESTING)) {
+      call State.forceState(S_GRANTED);
+      return SUCCESS;
+    } else
+      return FAIL;
+  }
+
+  async command bool ArbiterInfo.inUse()
+  {
+    atomic {
+      if (m_granted)
+        return TRUE;
+    }
+    return FALSE;
+  }
+
+  /* The ArbiterInfo interface doesn't work so well for a shared resource, as
+   * 1+ users may hold the resource at any time.
+   */
+  async command uint8_t ArbiterInfo.userId()
+  {
+    atomic {
+      if (m_granted)
+        return 1;
+    }
+    return NO_CLIENT;
+  }
+
+  async command uint8_t Resource.isOwner[uint8_t id]()
+  {
+    atomic return call GrantedVector.get(id);
+  }
+
+  async command uint8_t ResourceDefaultOwner.isOwner()
+  {
+    atomic return !(call State.isState(S_GRANTED));
+  }
+
+  default event void Resource.granted[uint8_t id]() {}
+  default async event void ResourceDefaultOwner.granted() {}
+  default async event void ResourceDefaultOwner.requested()
+  {
+    call ResourceDefaultOwner.release();
+  }
+  default async event void ResourceDefaultOwner.immediateRequested()
+  {
+    call ResourceDefaultOwner.release();
+  }
+}