Пример #1
0
uint64_t* consume_transport()
{
  DEBUG( static uint64_t counter = 0 );

  register uint64_t node_sequence = ((*node_sequence_ptr) & MASK);

  walker = (volatile uint64_t**)follow_sequence_ptr;
  do
	{
    DEBUGVV( printf( "consume_transport:\tWaiting on node %d to release %d [%d]\n",  \
      *follow, node_sequence, (**walker) & MASK ) );
    while(node_sequence == ( (**walker) & MASK ) ) sched_yield();
  }
	while( *(++walker) );

  DEBUGVV( printf( "consume_transport:\tMessage %d consumed from slot %d\n", \
		   ring[ node_sequence ].data.value, node_sequence ) );

  DEBUG( *get_counter_ptr = ++counter );
  DEBUG( *fad_value_ptr = *fed_value_ptr / counter );
  DEBUGV( if( !( counter & DEBUG_SKIP_MASK ) )  \
       printf( "Ctr: %dm\tFed: %d\n", counter/DEBUG_SKIP_MASK, *fad_value_ptr ) );
  DEBUG( if( counter == 100 + RING_ENTRY_COUNT  ) *fed_value_ptr = 0 );

  return &ring[ node_sequence ].data.value;
}
Пример #2
0
/* Get a free binary buffer, first invalidating it in the receive
 * queue if necessary. In practice all buffers should be used
 * before they are invalidated, if BUFFERS_PER_SLAVE is large enough.
 * slave_lock is held on both entry and exit of this function. */
static void *
get_free_buf(struct slave_state *sstate)
{
	int newest = (sstate->newest_buf + 1) & (BUFFERS_PER_SLAVE - 1);
	sstate->newest_buf = newest;
	void *buf = sstate->b[newest].buf;

	if (DEBUGVV(7)) {
		char b[1024];
		snprintf(b, sizeof(b),
			 "get free %d index %d buf=%p age %d qlength %d\n", newest,
			 sstate->b[newest].queue_index, buf, queue_age, queue_length);
		logline(&sstate->client, "? ", b);
	}

	int index = sstate->b[newest].queue_index;
	if (index < 0) return buf;

	/* Invalidate the buffer if the calling thread still owns its previous
	 * entry in the receive queue. The entry may have been overwritten by
	 * another thread, but only after a new move which invalidates the
	 * entire receive queue. */
	if (receive_queue[index] && receive_queue[index]->owner == sstate->thread_id) {
		receive_queue[index] = NULL;
	}
	sstate->b[newest].queue_index = -1;
	return buf;
}
Пример #3
0
void release_transport()
{
  DEBUG( static uint64_t counter = 0 );

  DEBUGVV( register uint64_t node_sequence = ((*node_sequence_ptr) & MASK) );

  DEBUGVV( printf( "release_transport:\tmessage %d released from slot %d\n", \
		   ring[ node_sequence ].data.value, node_sequence ) );

  DEBUGVV( printf( "release_transport:\tMoving node sequence number from %d to %d\n", 
		 ((*node_sequence_ptr) & MASK), (((*node_sequence_ptr) + 1) & MASK) ) );

  BARRIER;
  ++(*node_sequence_ptr);

  DEBUG( *put_counter_ptr = ++counter );
  DEBUG( *bad_value_ptr = *bed_value_ptr / counter );
  DEBUGV( if( !( counter & DEBUG_SKIP_MASK ) )  \
       printf( "Ctr: %dm\tBed: %d\n", counter/DEBUG_SKIP_MASK, *bad_value_ptr ) );
  DEBUG( if( counter == 100 + RING_ENTRY_COUNT ) *bed_value_ptr = 0 );
}
Пример #4
0
/* Get a reply to one gtp command. Return the gtp command id,
 * or -1 if error. reply must have at least CMDS_SIZE bytes.
 * The ascii reply ends with an empty line; if the first line
 * contains "@size", a binary reply of size bytes follows the
 * empty line. @size is not standard gtp, it is only used
 * internally by Pachi for the genmoves command; it must be the
 * last parameter on the line.
 * *bin_size is the maximum size upon entry, actual size on return.
 * slave_lock is not held on either entry or exit of this function. */
static int
get_reply(FILE *f, struct in_addr client, char *reply, void *bin_reply, int *bin_size)
{
	double start = time_now();

	int reply_id = -1;
	*reply = '\0';
	if (!fgets(reply, CMDS_SIZE, f)) return -1;

	/* Check for binary reply. */
	char *s = strchr(reply, '@');
	int size = 0;
	if (s) size = atoi(s+1);
	assert(size <= *bin_size);
	*bin_size = size;

	if (DEBUGV(s, 2))
		logline(&client, "<<", reply);
	if ((*reply == '=' || *reply == '?') && isdigit(reply[1]))
		reply_id = atoi(reply+1);

	/* Read the rest of the ascii reply */
	char *line = reply + strlen(reply);
	while (fgets(line, reply + CMDS_SIZE - line, f) && *line != '\n') {
		if (DEBUGL(3))
			logline(&client, "<<", line);
		line += strlen(line);
	}
	if (*line != '\n') return -1;

	/* Read the binary reply if any. */
	int len;
	while (size && (len = fread(bin_reply, 1, size, f)) > 0) {
		bin_reply = (char *)bin_reply + len;
		size -= len;
	}
	if (*bin_size && DEBUGVV(2)) {
		char buf[1024];
		snprintf(buf, sizeof(buf), "read reply %d+%d bytes in %.4fms\n",
			 (int)strlen(reply), *bin_size,
			 (time_now() - start)*1000);
		logline(&client, "= ", buf);
	}
	return size ? -1 : reply_id;
}
Пример #5
0
/* Insert a buffer in the receive queue. It should be the most
 * recent buffer allocated by the calling thread.
 * slave_lock is held on both entry and exit of this function. */
static void
insert_buf(struct slave_state *sstate, void *buf, int size)
{
	assert(queue_length < queue_max_length);

	int newest = sstate->newest_buf;
	assert(buf == sstate->b[newest].buf);

	/* Update the buffer if necessary before making it
	 * available to other threads. */
	if (sstate->insert_hook) sstate->insert_hook(buf, size);

	if (DEBUGVV(7)) {
		char b[1024];
		snprintf(b, sizeof(b),
			 "insert newest %d age %d rq[%d]->%p owner %d\n",
			 newest, queue_age, queue_length, buf, sstate->thread_id);
			logline(&sstate->client, "? ", b);
	}
	receive_queue[queue_length] = &sstate->b[newest];
	receive_queue[queue_length]->size = size;
	receive_queue[queue_length]->queue_index = queue_length;
	queue_length++;
}