コード例 #1
0
ファイル: cmd.c プロジェクト: open-cpu/pslse
// Handle randomly selected pending write
void handle_buffer_read(struct cmd *cmd)
{
	struct cmd_event *event;

	// Check that cmd struct is valid buffer read is available
	if ((cmd == NULL) || (cmd->buffer_read != NULL))
		return;

	// Randomly select a pending write (or none)
	event = cmd->list;
	while (event != NULL) {
		if ((event->type == CMD_WRITE) &&
		    (event->state == MEM_TOUCHED) &&
		    ((event->client_state != CLIENT_VALID) ||
		     !allow_reorder(cmd->parms))) {
			break;
		}
		event = event->_next;
	}

	// Test for client disconnect
	if ((event == NULL) || (_get_client(cmd, event) == NULL))
		return;

	// Send buffer read request to AFU.  Setting cmd->buffer_read
	// will block any more buffer read requests until buffer read
	// data is returned and handled in handle_buffer_data().
	if (psl_buffer_read(cmd->afu_event, event->tag, event->addr,
			    CACHELINE_BYTES) == PSL_SUCCESS) {
		cmd->buffer_read = event;
		debug_cmd_buffer_read(cmd->dbg_fp, cmd->dbg_id, event->tag);
		event->state = MEM_BUFFER;
	}
}
コード例 #2
0
ファイル: rpcudp.cpp プロジェクト: sismvg/ndisk
void rpcudp::_package_process(const udpaddr& addr,
	int len, shared_memory memory, size_t memory_size)
{
	/*
		要最先发送ack
		*/
	const_memory_block blk(memory);
	blk.size = memory_size;
	packages_analysis sis(blk);
	rpcudp_detail::__slice_head_attacher attacher(sis);


	complete_result job;

	job.user_key = get_slice;
	job.key = 0;

	auto* arg = new _complete_argument(addr, memory);
	job.argument = arg;

	auto wlock = ISU_AUTO_LOCK(_spinlock);
	arg->client = &_get_client(addr);
	wlock.unlock();

	if (attacher.udp_ex != nullptr)
	{
		arg->client->_send_ack(
			addr, attacher.udp_ex->group_id,
			attacher.udp_ex->slice_id);
	}

	_process_port.post(job);
}
コード例 #3
0
ファイル: cmd.c プロジェクト: open-cpu/pslse
// Decide what to do with a client memory acknowledgement
void handle_mem_return(struct cmd *cmd, struct cmd_event *event, int fd)
{
	struct client *client;

	// Test for client disconnect
	if ((event == NULL) || ((client = _get_client(cmd, event)) == NULL))
		return;

	// Randomly cause paged response
	if (((event->type != CMD_WRITE) || (event->state != MEM_REQUEST)) &&
	    (client->flushing == FLUSH_NONE) && !_page_cached(cmd, event->addr)
	    && allow_paged(cmd->parms)) {
		if (event->type == CMD_READ)
			_handle_mem_read(cmd, event, fd);
		event->resp = PSL_RESPONSE_PAGED;
		event->state = MEM_DONE;
		client->flushing = FLUSH_PAGED;
		debug_cmd_update(cmd->dbg_fp, cmd->dbg_id, event->tag,
				 event->context, event->resp);
		return;
	}

	_update_age(cmd, event->addr);

	if (event->type == CMD_READ)
		_handle_mem_read(cmd, event, fd);
	else if (event->type == CMD_TOUCH)
		event->state = MEM_DONE;
	else if (event->state == MEM_TOUCH)	// Touch before write
		event->state = MEM_TOUCHED;
	else			// Write after touch
		event->state = MEM_DONE;
	debug_cmd_return(cmd->dbg_fp, cmd->dbg_id, event->tag, event->context);
}
コード例 #4
0
/***
 * Manage UDP packets
 */
void NetGameServer::_handle_udp() {
	DVector<uint8_t> raw;
	NetGameServerConnection *cd;

	// Flush packets queue
	while(udp_queue.size() > 0) {
		// Only this thread removes from the queue
		// it is safe to lock here
		udp_mutex->lock();
		QueuedPacket *qp = udp_queue.get(0);
		udp_queue.remove(0);
		udp_mutex->unlock();

		NetGameServerConnection *cd = _get_client(qp->id);
		if(cd != NULL) {
			udp_server->set_send_address(cd->udp_host,
							cd->udp_port);
			udp_server->put_packet_buffer(cd->build_pkt(qp));
		}
		memdelete(qp);
	}

	// Handle incoming packets
	if(udp_server->get_available_packet_count() > 0) {
		udp_server->get_packet_buffer(raw);

		if(raw.size() < 1) {
			WARN_PRINT("Invalid UDP Packet!");
			return;
		}

		cd = _get_client(raw.get(0));
		if(cd == NULL) {
			WARN_PRINT("Invalid UDP Auth!");
			return;
		}

		cd->handle_udp(raw,
				udp_server->get_packet_address(),
				udp_server->get_packet_port());
	}
}
コード例 #5
0
ファイル: rpcudp.cpp プロジェクト: sismvg/ndisk
int rpcudp::sendto(const void* buf, size_t bufsize,
	int flag, const udpaddr& addr)
{
	_spinlock.lock();
	auto& client = _get_client(addr);
	_spinlock.unlock();

	const_shared_memory memory(
		deep_copy(const_memory_block(buf, bufsize)));
	return client.sendto(memory, addr);
}
コード例 #6
0
ファイル: cmd.c プロジェクト: open-cpu/pslse
void handle_mem_write(struct cmd *cmd)
{
	struct cmd_event **head;
	struct cmd_event *event;
	struct client *client;
	uint64_t *addr;
	uint8_t *buffer;
	uint64_t offset;

	// Make sure cmd structure is valid
	if (cmd == NULL)
		return;

	// Send any ready write data to client immediately
	head = &cmd->list;
	while (*head != NULL) {
		if (((*head)->type == CMD_WRITE) &&
		    ((*head)->state == MEM_RECEIVED))
			break;
		head = &((*head)->_next);
	}
	event = *head;

	// Test for client disconnect
	if ((event == NULL) || ((client = _get_client(cmd, event)) == NULL))
		return;

	// Check that memory request can be driven to client
	if (client->mem_access != NULL)
		return;

	// Send data to client and clear event to allow
	// the next buffer read to occur.  The request will now await
	// confirmation from the client that the memory write was
	// successful before generating a response.  The client
	// response will cause a call to either handle_aerror() or
	// handle_mem_return().
	buffer = (uint8_t *) malloc(event->size + 10);
	offset = event->addr & ~CACHELINE_MASK;
	buffer[0] = (uint8_t) PSLSE_MEMORY_WRITE;
	buffer[1] = (uint8_t) event->size;
	addr = (uint64_t *) & (buffer[2]);
	*addr = htonll(event->addr);
	memcpy(&(buffer[10]), &(event->data[offset]), event->size);
	event->abort = &(client->abort);
	if (put_bytes(client->fd, event->size + 10, buffer, cmd->dbg_fp,
		      cmd->dbg_id, client->context) < 0) {
		client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
	}
	debug_cmd_client(cmd->dbg_fp, cmd->dbg_id, event->tag, event->context);
	event->state = MEM_REQUEST;
	client->mem_access = (void *)event;
}
コード例 #7
0
Error NetGameServer::put_tcp_packet(int id, const DVector<uint8_t> &pkt, int cmd) {
	Error out;

	conn_mutex->lock();
	NetGameServerConnection *cd = _get_client(id);
	if(cd == NULL) {
		conn_mutex->unlock();
		return ERR_DOES_NOT_EXIST;
	}
	out = cd->enqueue_tcp(pkt, cmd);
	conn_mutex->unlock();
	return out;
}
コード例 #8
0
Error NetGameServer::kick_client(CID id) {
	conn_mutex->lock();
	NetGameServerConnection *conn = _get_client(id);
	if(conn == NULL) {
		conn_mutex->unlock();
		return ERR_DOES_NOT_EXIST;
	}

	this->connections.erase(conn->id);
	conn_mutex->unlock();

	_delete_client(conn);
	return OK;
}
コード例 #9
0
Error NetGameServer::put_udp_packet(int id, const DVector<uint8_t> &pkt,
					int cmd, bool timed) {
	conn_mutex->lock();
	NetGameServerConnection *cd = _get_client(id);
	if(cd == NULL) {
		conn_mutex->unlock();
		return ERR_DOES_NOT_EXIST;
	}
	if(cd->state != READY) {
		conn_mutex->unlock();
		return ERR_CONNECTION_ERROR;
	}
	conn_mutex->unlock();
	return _enqueue_udp(id, pkt, cmd, timed);
}
コード例 #10
0
ファイル: cmd.c プロジェクト: open-cpu/pslse
// Handle randomly selected memory touch
void handle_touch(struct cmd *cmd)
{
	struct cmd_event *event;
	struct client *client;
	uint8_t buffer[10];
	uint64_t *addr;

	// Make sure cmd structure is valid
	if (cmd == NULL)
		return;

	// Randomly select a pending touch (or none)
	event = cmd->list;
	while (event != NULL) {
		if (((event->type == CMD_TOUCH) || (event->type == CMD_WRITE))
		    && (event->state == MEM_IDLE)
		    && ((event->client_state != CLIENT_VALID)
			|| !allow_reorder(cmd->parms))) {
			break;
		}
		event = event->_next;
	}

	// Test for client disconnect
	if ((event == NULL) || ((client = _get_client(cmd, event)) == NULL))
		return;

	// Check that memory request can be driven to client
	if (client->mem_access != NULL)
		return;

	// Send memory touch request to client
	buffer[0] = (uint8_t) PSLSE_MEMORY_TOUCH;
	buffer[1] = (uint8_t) event->size;
	addr = (uint64_t *) & (buffer[2]);
	*addr = htonll(event->addr & CACHELINE_MASK);
	event->abort = &(client->abort);
	if (put_bytes(client->fd, 10, buffer, cmd->dbg_fp, cmd->dbg_id,
		      event->context) < 0) {
		client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
	}
	event->state = MEM_TOUCH;
	client->mem_access = (void *)event;
	debug_cmd_client(cmd->dbg_fp, cmd->dbg_id, event->tag, event->context);
}
コード例 #11
0
ファイル: cmd.c プロジェクト: open-cpu/pslse
// Add new command to list
static void _add_cmd(struct cmd *cmd, uint32_t context, uint32_t tag,
		     uint32_t command, uint32_t abort, enum cmd_type type,
		     uint64_t addr, uint32_t size, enum mem_state state,
		     uint32_t resp, uint8_t unlock)
{
	struct cmd_event **head;
	struct cmd_event *event;

	if (cmd == NULL)
		return;

	event = (struct cmd_event *)calloc(1, sizeof(struct cmd_event));
	event->context = context;
	event->command = command;
	event->tag = tag;
	event->abt = abort;
	event->type = type;
	event->addr = addr;
	event->size = size;
	event->state = state;
	event->resp = resp;
	event->unlock = unlock;
	event->data = (uint8_t *) malloc(CACHELINE_BYTES);
	memset(event->data, 0xFF, CACHELINE_BYTES);
	event->parity = (uint8_t *) malloc(DWORDS_PER_CACHELINE / 8);
	memset(event->parity, 0xFF, DWORDS_PER_CACHELINE / 8);

	// Test for client disconnect
	if (_get_client(cmd, event) == NULL) {
		event->resp = PSL_RESPONSE_FAILED;
		event->state = MEM_DONE;
	}

	head = &(cmd->list);
	while ((*head != NULL) && !allow_reorder(cmd->parms))
		head = &((*head)->_next);
	event->_next = *head;
	*head = event;
	debug_cmd_add(cmd->dbg_fp, cmd->dbg_id, tag, context, command);
}
コード例 #12
0
ファイル: cmd.c プロジェクト: open-cpu/pslse
// Send pending interrupt to client as soon as possible
void handle_interrupt(struct cmd *cmd)
{
	struct cmd_event **head;
	struct cmd_event *event;
	struct client *client;
	uint16_t irq;
	uint8_t buffer[3];

	// Make sure cmd structure is valid
	if (cmd == NULL)
		return;

	// Send any interrupts to client immediately
	head = &cmd->list;
	while (*head != NULL) {
		if (((*head)->type == CMD_INTERRUPT) &&
		    ((*head)->state == MEM_IDLE))
			break;
		head = &((*head)->_next);
	}
	event = *head;

	// Test for client disconnect
	if ((event == NULL) || ((client = _get_client(cmd, event)) == NULL))
		return;

	// Send interrupt to client
	buffer[0] = PSLSE_INTERRUPT;
	irq = htons(cmd->irq);
	memcpy(&(buffer[1]), &irq, 2);
	event->abort = &(client->abort);
	if (put_bytes(client->fd, 3, buffer, cmd->dbg_fp, cmd->dbg_id,
		      event->context) < 0) {
		client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
	}
	debug_cmd_client(cmd->dbg_fp, cmd->dbg_id, event->tag, event->context);
	event->state = MEM_DONE;
}
コード例 #13
0
Error NetGameServer::auth_client(CID id) {
	conn_mutex->lock();
	NetGameServerConnection *conn = _get_client(id);
	if(conn == NULL) {
		conn_mutex->unlock();
		return ERR_DOES_NOT_EXIST;
	}
	if(conn->authed) {
		conn_mutex->unlock();
		return ERR_ALREADY_EXISTS;
	}
	conn->authed = true;

	// Assign id to client
	unsigned char raw[4];
	raw[0] = CMD_MAX;
	raw[1] = PCMD_AUTH;
	raw[2] = conn->id;
	raw[3] = conn->secret;
	conn->tcp->put_packet(raw, 4);

	conn_mutex->unlock();
	return OK;
}
コード例 #14
0
ファイル: cmd.c プロジェクト: open-cpu/pslse
// Send a randomly selected pending response back to AFU
void handle_response(struct cmd *cmd)
{
	struct cmd_event **head;
	struct cmd_event *event;
	struct client *client;
	int rc;

	// Select a random pending response (or none)
	client = NULL;
	head = &cmd->list;
	while (*head != NULL) {
		// Fast track error responses
		if (((*head)->resp == PSL_RESPONSE_PAGED) ||
		    ((*head)->resp == PSL_RESPONSE_NRES) ||
		    ((*head)->resp == PSL_RESPONSE_NLOCK) ||
		    ((*head)->resp == PSL_RESPONSE_FAILED) ||
		    ((*head)->resp == PSL_RESPONSE_FLUSHED)) {
			event = *head;
			goto drive_resp;
		}
		if (((*head)->state == MEM_DONE) && !allow_reorder(cmd->parms)) {
			break;
		}
		head = &((*head)->_next);
	}

	// Randomly decide not to drive response yet
	event = *head;
	if ((event == NULL) || ((event->client_state == CLIENT_VALID)
				&& !allow_resp(cmd->parms))) {
		return;
	}
	// Test for client disconnect
	if ((event == NULL) || ((client = _get_client(cmd, event)) == NULL))
		return;

	// Send response, remove command from list and free memory
	if ((event->resp == PSL_RESPONSE_PAGED) ||
	    (event->resp == PSL_RESPONSE_AERROR) ||
	    (event->resp == PSL_RESPONSE_DERROR)) {
		client->flushing = FLUSH_FLUSHING;
		_update_pending_resps(cmd, PSL_RESPONSE_FLUSHED);
	}

 drive_resp:
	// Check for pending buffer activity
	if (event == cmd->buffer_read) {
		fatal_msg("Driving response when buffer read still active");
		_print_event(event);
		assert(event != cmd->buffer_read);
	}

	rc = psl_response(cmd->afu_event, event->tag, event->resp, 1, 0, 0);
	if (rc == PSL_SUCCESS) {
		debug_msg("%s:RESPONSE tag=0x%02x code=0x%x", cmd->afu_name,
			  event->tag, event->resp);
		debug_cmd_response(cmd->dbg_fp, cmd->dbg_id, event->tag);
		if ((client != NULL) && (event->command == PSL_COMMAND_RESTART))
			client->flushing = FLUSH_NONE;
		*head = event->_next;
		free(event->data);
		free(event->parity);
		free(event);
		cmd->credits++;
	}
}
コード例 #15
0
ファイル: cmd.c プロジェクト: open-cpu/pslse
// Handle randomly selected pending read by either generating early buffer
// write with bogus data, send request to client for real data or do final
// buffer write with valid data after it has been received from client.
void handle_buffer_write(struct cmd *cmd)
{
	struct cmd_event *event;
	struct client *client;
	uint8_t buffer[10];
	uint64_t *addr;
	int quadrant, byte;

	// Make sure cmd structure is valid
	if (cmd == NULL)
		return;

	// Randomly select a pending read (or none)
	event = cmd->list;
	while (event != NULL) {
		if ((event->type == CMD_READ) &&
		    (event->state != MEM_DONE) &&
		    ((event->client_state != CLIENT_VALID) ||
		     !allow_reorder(cmd->parms))) {
			break;
		}
		event = event->_next;
	}

	// Test for client disconnect
	if ((event == NULL) || ((client = _get_client(cmd, event)) == NULL))
		return;

	// After the client returns data with a call to the function
	// _handle_mem_read() issue buffer write with valid data and
	// prepare for response.
	if (event->state == MEM_RECEIVED) {
		if (psl_buffer_write(cmd->afu_event, event->tag, event->addr,
				     CACHELINE_BYTES, event->data,
				     event->parity) == PSL_SUCCESS) {
			debug_msg("%s:BUFFER WRITE tag=0x%02x", cmd->afu_name,
				  event->tag);
			for (quadrant = 0; quadrant < 4; quadrant++) {
				DPRINTF("DEBUG: Q%d 0x", quadrant);
				for (byte = 0; byte < CACHELINE_BYTES / 4;
				     byte++) {
					DPRINTF("%02x", event->data[byte]);
				}
				DPRINTF("\n");
			}
			event->resp = PSL_RESPONSE_DONE;
			event->state = MEM_DONE;
			debug_cmd_buffer_write(cmd->dbg_fp, cmd->dbg_id,
					       event->tag);
			debug_cmd_update(cmd->dbg_fp, cmd->dbg_id, event->tag,
					 event->context, event->resp);
		}
	}

	if (event->state != MEM_IDLE)
		return;

	if (!event->buffer_activity && allow_buffer(cmd->parms)) {
		// Buffer write with bogus data, but only once
		debug_cmd_buffer_write(cmd->dbg_fp, cmd->dbg_id, event->tag);
		psl_buffer_write(cmd->afu_event, event->tag, event->addr,
				 CACHELINE_BYTES, event->data, event->parity);
		event->buffer_activity = 1;
	} else if (client->mem_access == NULL) {
		// Send read request to client, set client->mem_access
		// to point to this event blocking any other memory
		// accesses to client until data is returned by call
		// to the _handle_mem_read() function.
		buffer[0] = (uint8_t) PSLSE_MEMORY_READ;
		buffer[1] = (uint8_t) event->size;
		addr = (uint64_t *) & (buffer[2]);
		*addr = htonll(event->addr);
		event->abort = &(client->abort);
		if (put_bytes(client->fd, 10, buffer, cmd->dbg_fp,
			      cmd->dbg_id, event->context) < 0) {
			client_drop(client, PSL_IDLE_CYCLES, CLIENT_NONE);
		}
		event->state = MEM_REQUEST;
		debug_cmd_client(cmd->dbg_fp, cmd->dbg_id, event->tag,
				 event->context);
		client->mem_access = (void *)event;
	}
}