Exemple #1
0
size_t FifoBuffer<T, Container>::read(T* out, size_t num_elems)
{
   size_t read_amount = num_elems > read_avail() ? read_avail() : num_elems;
   std::copy(m_container.begin(), m_container.begin() + read_amount, out);
   m_container.erase(m_container.begin(), m_container.begin() + read_amount);
   return read_amount;
}
Exemple #2
0
	size_t read(void *dst, size_t len, bool peek = false)
	{
		size_t const avail = read_avail();
		if (avail == 0) return 0;

		size_t new_rpos = rpos;

		size_t const limit_len = len > avail ? avail : len;
		size_t const total = new_rpos + len;
		size_t first, rest;

		if (total > CAPACITY) {
			first = CAPACITY - new_rpos;
			rest  = total % CAPACITY;
		} else {
			first = limit_len;
			rest  = 0;
		}

		Genode::memcpy(dst, &_data[new_rpos], first);
		new_rpos = (new_rpos + first) % CAPACITY;

		if (rest) {
			Genode::memcpy(((char*)dst) + first, &_data[new_rpos], rest);
			new_rpos = (new_rpos + rest) % CAPACITY;
		}

		if (!peek) rpos = new_rpos;

		return limit_len;
	}
blargg_err_t Data_Reader::read_avail( void* p, long* n )
{
	int i = STATIC_CAST(int, *n);
	blargg_err_t err = read_avail( p, &i );
	*n = i;
	return err;
}
const char * Data_Reader::read_avail( void* p, long* n )
{
	int i = STATIC_CAST(int, *n);
	const char * err = read_avail( p, &i );
	*n = i;
	return err;
}
Exemple #5
0
blargg_err_t Data_Reader::read( void* p, long s )
{
	RETURN_VALIDITY_CHECK( s > 0 );

	long result = read_avail( p, s );
	if ( result != s )
	{
		if ( result >= 0 && result < s )
			return eof_error;
		
		return "Read error";
	}
	
	return 0;
}
Exemple #6
0
int recvsome(uint32_t* readoff, uint32_t* writeoff, uint32_t bufsize, char* readbuf, void* outbuf, int length) {

  int available = (int)read_avail(readoff, writeoff, bufsize);

  if(!available)
    return 0;

  int tocopy = available < length ? available : length;

  if(read_would_wrap(readoff, bufsize, tocopy)) {
    int bytestoend = (bufsize - *readoff);
    memcpy(outbuf, readbuf + (*readoff), bytestoend);
    memcpy(((char*)outbuf) + bytestoend, readbuf, tocopy - bytestoend);
  }
  else {
    memcpy(outbuf, readbuf + (*readoff), tocopy);
  }

  return tocopy;

}
Exemple #7
0
void discard_asynchronous_messages(int block) {

  uint32_t bufsize = ((uint32_t*)singleton_screen->rx_buffer)[0];
  uint32_t* readoff = &(((uint32_t*)singleton_screen->rx_buffer)[1]);
  uint32_t* writeoff = &(((uint32_t*)singleton_screen->rx_buffer)[2]);
  char* readbuf = (char*)&(((uint32_t*)singleton_screen->rx_buffer)[3]);

  if(block) {
    DBG("Discarding async messages (blocking)\n");
  }
  else {
    DBG("Discarding async messages (non-blocking)\n");
  }
  // WARNING HERE: This method assumes that no async failure notification
  // is bigger than the ring. If one were, we would wait fruitlessly until
  // the entire thing were present before deleting it from the ring.

  /* If block is set, we should wait until a synchronous message arrives.
     If block is not set, we should return as soon as we're short of data. */

  int need_more_bytes = 0;

  while(1) {

    struct message_header head;

    if(need_more_bytes) {
      if(block) {
	DBG("Insufficient data, but invoked blocking: sleeping\n");
	wait_for_rx_not_empty();
	need_more_bytes = 0;
	DBG("Woken\n");
      }
      else {
	DBG("Non-blocking discard_async_messages: exiting\n");
	return;
      }
    }

    if(drain_events(singleton_screen->socketfd) == -1) {
      printf("Socket error draining events in discard_async\n");
      return;
    }

    int bytes_peeked = recvsome(readoff, writeoff, bufsize, readbuf, (char*)&head, sizeof(struct message_header));

    if(bytes_peeked < sizeof(struct message_header)) {
      DBG("  Less than a header available (%d bytes); exiting\n", bytes_peeked);
      need_more_bytes = 1;
      continue;
    }

    if(!message_is_asynchronous(head.opcode)) {
      DBG("  Next message (%s) not asynchronous: exiting\n", optotext(head.opcode));
      return;
    }

    int bytes_available = read_avail(readoff, writeoff, bufsize);

    if(bytes_available < head.length) {
      DBG("  Message had length %d but only %d available: exiting\n", head.length, bytes_available);
      need_more_bytes = 1;
      continue;
    }

    char* message_proper = malloc(head.length);
    if(!message_proper) {
      printf("OOM checking for asynchronous failures\n");
      return;
    }

    int bytes_read = recvsome(readoff, writeoff, bufsize, readbuf, message_proper, head.length);

    if(bytes_read < head.length) {
      printf("BUG! read_avail returned %d, yet we could only actually read %d bytes\n", bytes_available, bytes_read);
      free(message_proper);
      return;
    }

    DBG("  Got a message: checking its result\n");

    check_async_result(message_proper, head.opcode);

    free(message_proper);

    discard_ring_bytes(readoff, bufsize, head.length);

  }

}
Exemple #8
0
struct message_header* get_message() {

  uint32_t bufsize = ((uint32_t*)singleton_screen->rx_buffer)[0];
  uint32_t* readoff = &(((uint32_t*)singleton_screen->rx_buffer)[1]);
  uint32_t* writeoff = &(((uint32_t*)singleton_screen->rx_buffer)[2]);
  char* readbuf = (char*)&(((uint32_t*)singleton_screen->rx_buffer)[3]);

  int size;

  DBG("Entering get_message: readoff = %u, writeoff = %u\n", *readoff, *writeoff);

  int avail;

  wait_for_synchronous_message();

  if(!read_would_wrap(readoff, bufsize, sizeof(struct message_header))) {

    DBG("Looking for a message header's worth of data\n");

    while((avail = read_avail(readoff, writeoff, bufsize)) < sizeof(struct message_header))  { 
      DBG("Waiting for more to be written (currently have %d, wanting %d\n)\n", avail, sizeof(struct message_header)); 
      wait_for_rx_not_empty(); 
    }

    size = ((struct message_header*)(readbuf + *readoff))->length;
    DBG("Found message has length %d\n", size);

    if(read_would_wrap(readoff, bufsize, size)) {
      DBG("Read would wrap; not reading in place\n");
      last_read_is_in_place = 0;
    }
    else {
      DBG("Read would not wrap; reading in place\n");
      last_read_is_in_place = 1;
    }

  }
  else {
    DBG("Reading only a message_header would wrap; not reading in place\n");
    last_read_is_in_place = 0;
  }
  
  if(last_read_is_in_place) {

    DBG("Reading in place\n");

    // Pass out a pointer to the ring buffer in-place, once it is full enough
    while((avail = read_avail(readoff, writeoff, bufsize)) < size)  {
      DBG("Waiting for more to be written (got %d, wanting %d)\n", avail, size);
      wait_for_rx_not_empty();
    }

    DBG("Got enough; passing out in-place pointer\n");
    return (struct message_header*)(readbuf + *readoff);

  }
  else {

    DBG("Not reading in place\n");

    // Malloc a temporary and progressively copy into it
    struct message_header* new_message = (struct message_header*)malloc(sizeof(struct message_header));

    int bytes_received = 0;

    partial_recv(readoff, writeoff, bufsize, readbuf, new_message, &bytes_received, sizeof(struct message_header));

    if(new_message->length < sizeof(struct message_header)) {
      printf("Unreasonably short message encountered whilst receiving (length %d)\n", new_message->length);
      exit(1);
    }

    new_message = (struct message_header*)realloc(new_message, new_message->length);

    partial_recv(readoff, writeoff, bufsize, readbuf, new_message, &bytes_received, new_message->length);
  
    DBG("Received %s (length %u)\n", optotext(new_message->opcode), new_message->length);

    return new_message;
  }

}