⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sendvirtualizerp.nc

📁 tinyos-2.x.rar
💻 NC
字号:
// $Id: SendVirtualizerP.nc,v 1.2 2007/09/13 23:10:18 scipio Exp $
/*
* "Copyright (c) 2005 Stanford University. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose, without fee, and without written
* agreement is hereby granted, provided that the above copyright
* notice, the following two paragraphs and the author appear in all
* copies of this software.
* 
* IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
* IF STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
* 
* STANFORD UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE
* PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND STANFORD UNIVERSITY
* HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS."
*/

/**
 * A Send queue that provides a Service Instance pattern for formatted
 * packets and calls an underlying Send in a round-robin fashion. Used
 * to share L3 bandwidth between different communication clients.
 *
 * @author Philip Levis
 * @date   April 6 2007
 */ 

#include "AM.h"

generic module SendVirtualizerP(int numClients) {
    provides interface Send[uint8_t client];
    uses { 
      interface Send as SubSend;
      interface Packet;
    }
}

implementation {
    typedef struct {
        message_t* msg;
    } queue_entry_t;
  
    uint8_t current = numClients; // mark as empty
    queue_entry_t queue[numClients];
    uint8_t cancelMask[numClients/8 + 1];

    void tryToSend();
    
    void nextPacket() {
        uint8_t i;
        current = (current + 1) % numClients;
        for(i = 0; i < numClients; i++) {
            if((queue[current].msg == NULL) ||
               (cancelMask[current/8] & (1 << current%8)))
            {
                current = (current + 1) % numClients;
            }
            else {
                break;
            }
        }
        if(i >= numClients) current = numClients;
    }

    /**
     * Accepts a properly formatted AM packet for later sending.
     * Assumes that someone has filled in the AM packet fields
     * (destination, AM type).
     *
     * @param msg - the message to send
     * @param len - the length of the payload
     *
     */
    command error_t Send.send[uint8_t clientId](message_t* msg,
                                                uint8_t len) {
        if (clientId >= numClients) {
            return FAIL;
        }
        if (queue[clientId].msg != NULL) {
            return EBUSY;
        }
        dbg("AMQueue", "AMQueue: request to send from %hhu (%p): passed checks\n", clientId, msg);
        
        queue[clientId].msg = msg;
        call Packet.setPayloadLength(msg, len);
    
        if (current >= numClients) { // queue empty
            error_t err;
            current = clientId;
            
            err = call SubSend.send(msg, len);
            if (err != SUCCESS) {
	      dbg("AMQueue", "%s: underlying send failed.\n", __FUNCTION__);
	      current = numClients;
	      queue[clientId].msg = NULL;
            }
            return err;
        }
        else {
	  dbg("AMQueue", "AMQueue: request to send from %hhu (%p): queue not empty\n", clientId, msg);
        }
        return SUCCESS;
    }

    task void CancelTask() {
      uint8_t i,j,mask,last;
      message_t *msg;
      for(i = 0; i < numClients/8 + 1; i++) {
	if(cancelMask[i]) {
	  for(mask = 1, j = 0; j < 8; j++) {
	    if(cancelMask[i] & mask) {
	      last = i*8 + j;
	      msg = queue[last].msg;
		queue[last].msg = NULL;
		cancelMask[i] &= ~mask;
		signal Send.sendDone[last](msg, ECANCEL);
	    }
	    mask <<= 1;
	  }
	}
      }
    }
    
    command error_t Send.cancel[uint8_t clientId](message_t* msg) {
      if (clientId >= numClients ||         // Not a valid client    
	  queue[clientId].msg == NULL ||    // No packet pending
	  queue[clientId].msg != msg) {     // Not the right packet
	return FAIL;
      }
      if(current == clientId) {
	error_t err = call SubSend.cancel(msg);
	return err;
      }
      else {
	cancelMask[clientId/8] |= 1 << clientId % 8;
	post CancelTask();
	return SUCCESS;
      }
    }

    void sendDone(uint8_t last, message_t *msg, error_t err) {
      queue[last].msg = NULL;
      tryToSend();
      signal Send.sendDone[last](msg, err);
    }

    task void errorTask() {
      sendDone(current, queue[current].msg, FAIL);
    }
    
    // NOTE: Increments current!
    void tryToSend() {
      nextPacket();
      if (current < numClients) { // queue not empty
	error_t nextErr;
	message_t* nextMsg = queue[current].msg;
	uint8_t len = call Packet.payloadLength(nextMsg);
	nextErr = call SubSend.send(nextMsg, len);
	if(nextErr != SUCCESS) {
	  post errorTask();
	}
      }
    }
    
    event void SubSend.sendDone(message_t* msg, error_t err) {
      if(queue[current].msg == msg) {
	sendDone(current, msg, err);
      }
      else {
	dbg("PointerBug", "%s received send done for %p, signaling for %p.\n",
	    __FUNCTION__, msg, queue[current].msg);
      }
    }
    
    command uint8_t Send.maxPayloadLength[uint8_t id]() {
        return call SubSend.maxPayloadLength();
    }

    command void* Send.getPayload[uint8_t id](message_t* m, uint8_t len) {
      return call SubSend.getPayload(m, len);
    }

    default event void Send.sendDone[uint8_t id](message_t* msg, error_t err) {
        // Do nothing
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -