📄 sendvirtualizerp.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 + -