#include <click/config.h>
#include "cpuqueue.hh"
#include <click/error.hh>
#include <click/confparse.hh>

CPUQueue::CPUQueue()
  : _last(0), _drops(0)
{
  memset(&_q, 0, sizeof(_q));
}

CPUQueue::~CPUQueue()
{
}

int
CPUQueue::configure(Vector<String> &conf, ErrorHandler *errh)
{
  unsigned new_capacity = 128;
  if (cp_va_parse(conf, this, errh, 
	          cpOptional, 
		  cpUnsigned, "maximum queue length", &new_capacity,
		  cpEnd) < 0) 
    return -1; 
  _capacity = new_capacity;
  return 0;
}
  
int 
CPUQueue::initialize(ErrorHandler *errh)
{
  for (int i=0; i<NUM_CLICK_CPUS; i++)
    if (!(_q[i]._q = new Packet*[_capacity+1]))
      return errh->error("out of memory!");
  _drops = 0;
  _last = 0;
  return 0;
}

void
CPUQueue::cleanup(CleanupStage)
{
  for (int i=0; i<NUM_CLICK_CPUS; i++) {
    for (int j = _q[i]._head; j != _q[i]._tail; j = next_i(j))
      _q[i]._q[j]->kill();
    delete[] _q[i]._q;
    _q[i]._q = 0;
  }
}

inline Packet *
CPUQueue::deq(int n)
{
  if (_q[n]._head != _q[n]._tail) {
    Packet *p = _q[n]._q[_q[n]._head];
    _q[n]._head = next_i(_q[n]._head);
    return p;
  } else
    return 0;
}

void
CPUQueue::push(int, Packet *p)
{
  int n = click_current_processor();
  int next = next_i(_q[n]._tail);
  if (next != _q[n]._head) {
    _q[n]._q[_q[n]._tail] = p;
    _q[n]._tail = next;
  } else {
    p->kill();
    _drops++;
  }
}

Packet *
CPUQueue::pull(int port)
{
    int n = _last;
    Packet *p = 0;
    for (int i = 0; i < NUM_CLICK_CPUS; i++) {
	p = deq(n);
	n++;
	if (n == NUM_CLICK_CPUS)
	    n = 0;
	if (p) {
	    _last = n;
	    return p;
	}
    }
    return 0;
}

String
CPUQueue::read_handler(Element *e, void *thunk)
{
  CPUQueue *q = static_cast<CPUQueue *>(e);
  switch (reinterpret_cast<intptr_t>(thunk)) {
   case 0:
    return String(q->capacity());
   case 1:
    return String(q->drops());
   default:
    return "";
  }
}

void
CPUQueue::add_handlers()
{
  add_read_handler("capacity", read_handler, (void *)0);
  add_read_handler("drops", read_handler, (void *)1);
}

ELEMENT_REQUIRES(linuxmodule)
EXPORT_ELEMENT(CPUQueue)
ELEMENT_MT_SAFE(CPUQueue)


syntax highlighted by Code2HTML, v. 0.9.1