--- /dev/null
+/*
+ * Copyright (c) 2004, Technische Universitat Berlin
+ * 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 Universitat 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.
+*/
+
+/**
+ * Please refer to TEP 108 for more information about this component and its
+ * intended use.<br><br>
+ *
+ * This component provides the Resource, ResourceRequested, ArbiterInfo,
+ * and ResourceController interfaces and uses the ResourceConfigure interface as
+ * described in TEP 108. It provides arbitration to a shared resource.
+ * An Queue 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 queue is checked and the next user
+ * that has a pending request will ge granted control of the resource. If
+ * there are no pending requests, then the user of the ResourceController
+ * interface gains access to the resource, and holds onto it until
+ * another user makes a request.
+ *
+ * @param <b>resourceName</b> -- The name of the Resource being shared
+ *
+ * @author Kevin Klues (klues@tkn.tu-berlin.de)
+ * @author Philip Levis
+ */
+
+generic module ArbiterP(uint8_t controller_id) {
+ provides {
+ interface Resource[uint8_t id];
+ interface ResourceRequested[uint8_t id];
+ interface ResourceController;
+ interface ArbiterInfo;
+ }
+ uses {
+ interface ResourceConfigure[uint8_t id];
+ interface ResourceQueue as Queue;
+ interface Leds;
+ }
+}
+implementation {
+
+ enum {RES_CONTROLLED, RES_GRANTING, RES_IMM_GRANTING, RES_BUSY};
+ enum {CONTROLLER_ID = controller_id};
+
+ uint8_t state = RES_CONTROLLED;
+ norace uint8_t resId = CONTROLLER_ID;
+ norace uint8_t reqResId;
+
+ task void grantedTask();
+
+ async command error_t Resource.request[uint8_t id]() {
+ signal ResourceRequested.requested[resId]();
+ atomic {
+ if(state == RES_CONTROLLED) {
+ state = RES_GRANTING;
+ reqResId = id;
+ }
+ else return call Queue.enqueue(id);
+ }
+ signal ResourceController.requested();
+ return SUCCESS;
+ }
+
+ async command error_t Resource.immediateRequest[uint8_t id]() {
+ signal ResourceRequested.immediateRequested[resId]();
+ atomic {
+ if(state == RES_CONTROLLED) {
+ state = RES_IMM_GRANTING;
+ reqResId = id;
+ }
+ else return FAIL;
+ }
+ signal ResourceController.immediateRequested();
+ if(resId == id) {
+ call ResourceConfigure.configure[resId]();
+ return SUCCESS;
+ }
+ atomic state = RES_CONTROLLED;
+ return FAIL;
+ }
+
+ async command error_t Resource.release[uint8_t id]() {
+ atomic {
+ if(state == RES_BUSY && resId == id) {
+ if(call Queue.isEmpty() == FALSE) {
+ reqResId = call Queue.dequeue();
+ state = RES_GRANTING;
+ post grantedTask();
+ }
+ else {
+ resId = CONTROLLER_ID;
+ state = RES_CONTROLLED;
+ signal ResourceController.granted();
+ }
+ call ResourceConfigure.unconfigure[id]();
+ }
+ }
+ return FAIL;
+ }
+
+ async command error_t ResourceController.release() {
+ atomic {
+ if(resId == CONTROLLER_ID) {
+ if(state == RES_GRANTING) {
+ post grantedTask();
+ return SUCCESS;
+ }
+ else if(state == RES_IMM_GRANTING) {
+ resId = reqResId;
+ state = RES_BUSY;
+ return SUCCESS;
+ }
+ }
+ }
+ return FAIL;
+ }
+
+ /**
+ Check if the Resource is currently in use
+ */
+ async command bool ArbiterInfo.inUse() {
+ 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;
+ }
+
+ /**
+ * 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]();
+ }
+
+ task void grantedTask() {
+ atomic {
+ resId = reqResId;
+ state = RES_BUSY;
+ }
+ call ResourceConfigure.configure[resId]();
+ signal Resource.granted[resId]();
+ }
+
+ //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]() {
+ }
+ default async event void ResourceRequested.requested[uint8_t id]() {
+ }
+ default async event void ResourceRequested.immediateRequested[uint8_t id]() {
+ }
+ default async event void ResourceController.granted() {
+ }
+ default async event void ResourceController.requested() {
+ call ResourceController.release();
+ }
+ default async event void ResourceController.immediateRequested() {
+ call ResourceController.release();
+ }
+ default async command void ResourceConfigure.configure[uint8_t id]() {
+ }
+ default async command void ResourceConfigure.unconfigure[uint8_t id]() {
+ }
+}