示例#1
0
文件: io.c 项目: cmatei/yalfs
void io_close_port(object port)
{
	if (!is_port_closed(port)) {
		fclose(port_implementation(port));
		set_port_closed(port);
	}
}
示例#2
0
文件: port.cpp 项目: mariuz/haiku
status_t
_get_next_port_info(team_id team, int32* _cookie, struct port_info* info,
	size_t size)
{
	TRACE(("get_next_port_info(team = %ld)\n", team));

	if (info == NULL || size != sizeof(port_info) || _cookie == NULL
		|| team < B_OK)
		return B_BAD_VALUE;
	if (!sPortsActive)
		return B_BAD_PORT_ID;

	int32 slot = *_cookie;
	if (slot >= sMaxPorts)
		return B_BAD_PORT_ID;

	if (team == B_CURRENT_TEAM)
		team = team_get_current_team_id();

	info->port = -1; // used as found flag

	while (slot < sMaxPorts) {
		MutexLocker locker(sPorts[slot].lock);

		if (sPorts[slot].id != -1 && !is_port_closed(slot)
			&& sPorts[slot].owner == team) {
			// found one!
			fill_port_info(&sPorts[slot], info, size);
			slot++;
			break;
		}

		slot++;
	}

	if (info->port == -1)
		return B_BAD_PORT_ID;

	*_cookie = slot;
	return B_OK;
}
示例#3
0
文件: port.cpp 项目: mariuz/haiku
status_t
select_port(int32 id, struct select_info* info, bool kernel)
{
	if (id < 0)
		return B_BAD_PORT_ID;

	int32 slot = id % sMaxPorts;

	MutexLocker locker(sPorts[slot].lock);

	if (sPorts[slot].id != id || is_port_closed(slot))
		return B_BAD_PORT_ID;
	if (!kernel && sPorts[slot].owner == team_get_kernel_team_id()) {
		// kernel port, but call from userland
		return B_NOT_ALLOWED;
	}

	info->selected_events &= B_EVENT_READ | B_EVENT_WRITE | B_EVENT_INVALID;

	if (info->selected_events != 0) {
		uint16 events = 0;

		info->next = sPorts[slot].select_infos;
		sPorts[slot].select_infos = info;

		// check for events
		if ((info->selected_events & B_EVENT_READ) != 0
			&& !sPorts[slot].messages.IsEmpty()) {
			events |= B_EVENT_READ;
		}

		if (sPorts[slot].write_count > 0)
			events |= B_EVENT_WRITE;

		if (events != 0)
			notify_select_events(info, events);
	}

	return B_OK;
}
示例#4
0
文件: port.cpp 项目: mariuz/haiku
status_t
writev_port_etc(port_id id, int32 msgCode, const iovec* msgVecs,
	size_t vecCount, size_t bufferSize, uint32 flags, bigtime_t timeout)
{
	if (!sPortsActive || id < 0)
		return B_BAD_PORT_ID;
	if (bufferSize > PORT_MAX_MESSAGE_SIZE)
		return B_BAD_VALUE;

	// mask irrelevant flags (for acquire_sem() usage)
	flags &= B_CAN_INTERRUPT | B_KILL_CAN_INTERRUPT | B_RELATIVE_TIMEOUT
		| B_ABSOLUTE_TIMEOUT;
	if ((flags & B_RELATIVE_TIMEOUT) != 0
		&& timeout != B_INFINITE_TIMEOUT && timeout > 0) {
		// Make the timeout absolute, since we have more than one step where
		// we might have to wait
		flags = (flags & ~B_RELATIVE_TIMEOUT) | B_ABSOLUTE_TIMEOUT;
		timeout += system_time();
	}

	bool userCopy = (flags & PORT_FLAG_USE_USER_MEMCPY) > 0;

	int32 slot = id % sMaxPorts;
	status_t status;
	port_message* message = NULL;

	MutexLocker locker(sPorts[slot].lock);

	if (sPorts[slot].id != id) {
		TRACE(("write_port_etc: invalid port_id %ld\n", id));
		return B_BAD_PORT_ID;
	}
	if (is_port_closed(slot)) {
		TRACE(("write_port_etc: port %ld closed\n", id));
		return B_BAD_PORT_ID;
	}

	if (sPorts[slot].write_count <= 0) {
		if ((flags & B_RELATIVE_TIMEOUT) != 0 && timeout <= 0)
			return B_WOULD_BLOCK;

		sPorts[slot].write_count--;

		// We need to block in order to wait for a free message slot
		ConditionVariableEntry entry;
		sPorts[slot].write_condition.Add(&entry);

		locker.Unlock();

		status = entry.Wait(flags, timeout);

		locker.Lock();

		if (sPorts[slot].id != id || is_port_closed(slot)) {
			// the port is no longer there
			T(Write(sPorts[slot], 0, 0, B_BAD_PORT_ID));
			return B_BAD_PORT_ID;
		}

		if (status != B_OK)
			goto error;
	} else
		sPorts[slot].write_count--;

	status = get_port_message(msgCode, bufferSize, flags, timeout,
		&message);
	if (status != B_OK)
		goto error;

	// sender credentials
	message->sender = geteuid();
	message->sender_group = getegid();
	message->sender_team = team_get_current_team_id();

	if (bufferSize > 0) {
		uint32 i;
		if (userCopy) {
			// copy from user memory
			for (i = 0; i < vecCount; i++) {
				size_t bytes = msgVecs[i].iov_len;
				if (bytes > bufferSize)
					bytes = bufferSize;

				status_t status = user_memcpy(message->buffer,
					msgVecs[i].iov_base, bytes);
				if (status != B_OK) {
					put_port_message(message);
					goto error;
				}

				bufferSize -= bytes;
				if (bufferSize == 0)
					break;
			}
		} else {
			// copy from kernel memory
			for (i = 0; i < vecCount; i++) {
				size_t bytes = msgVecs[i].iov_len;
				if (bytes > bufferSize)
					bytes = bufferSize;

				memcpy(message->buffer, msgVecs[i].iov_base, bytes);

				bufferSize -= bytes;
				if (bufferSize == 0)
					break;
			}
		}
	}

	sPorts[slot].messages.Add(message);
	sPorts[slot].read_count++;

	T(Write(sPorts[slot], message->code, message->size, B_OK));

	notify_port_select_events(slot, B_EVENT_READ);
	sPorts[slot].read_condition.NotifyOne();
	return B_OK;

error:
	// Give up our slot in the queue again, and let someone else
	// try and fail
	T(Write(sPorts[slot], 0, 0, status));
	sPorts[slot].write_count++;
	notify_port_select_events(slot, B_EVENT_WRITE);
	sPorts[slot].write_condition.NotifyOne();

	return status;
}
示例#5
0
文件: port.cpp 项目: mariuz/haiku
ssize_t
read_port_etc(port_id id, int32* _code, void* buffer, size_t bufferSize,
	uint32 flags, bigtime_t timeout)
{
	if (!sPortsActive || id < 0)
		return B_BAD_PORT_ID;
	if ((buffer == NULL && bufferSize > 0) || timeout < 0)
		return B_BAD_VALUE;

	bool userCopy = (flags & PORT_FLAG_USE_USER_MEMCPY) != 0;
	bool peekOnly = !userCopy && (flags & B_PEEK_PORT_MESSAGE) != 0;
		// TODO: we could allow peeking for user apps now

	flags &= B_CAN_INTERRUPT | B_KILL_CAN_INTERRUPT | B_RELATIVE_TIMEOUT
		| B_ABSOLUTE_TIMEOUT;

	int32 slot = id % sMaxPorts;

	MutexLocker locker(sPorts[slot].lock);

	if (sPorts[slot].id != id
		|| (is_port_closed(slot) && sPorts[slot].messages.IsEmpty())) {
		T(Read(sPorts[slot], 0, B_BAD_PORT_ID));
		TRACE(("read_port_etc(): %s port %ld\n",
			sPorts[slot].id == id ? "closed" : "invalid", id));
		return B_BAD_PORT_ID;
	}

	while (sPorts[slot].read_count == 0) {
		if ((flags & B_RELATIVE_TIMEOUT) != 0 && timeout <= 0)
			return B_WOULD_BLOCK;

		// We need to wait for a message to appear
		ConditionVariableEntry entry;
		sPorts[slot].read_condition.Add(&entry);

		locker.Unlock();

		// block if no message, or, if B_TIMEOUT flag set, block with timeout
		status_t status = entry.Wait(flags, timeout);

		locker.Lock();

		if (sPorts[slot].id != id
			|| (is_port_closed(slot) && sPorts[slot].messages.IsEmpty())) {
			// the port is no longer there
			T(Read(sPorts[slot], 0, B_BAD_PORT_ID));
			return B_BAD_PORT_ID;
		}

		if (status != B_OK) {
			T(Read(sPorts[slot], 0, status));
			return status;
		}
	}

	// determine tail & get the length of the message
	port_message* message = sPorts[slot].messages.Head();
	if (message == NULL) {
		panic("port %ld: no messages found\n", sPorts[slot].id);
		return B_ERROR;
	}

	if (peekOnly) {
		size_t size = copy_port_message(message, _code, buffer, bufferSize,
			userCopy);

		T(Read(sPorts[slot], message->code, size));

		sPorts[slot].read_condition.NotifyOne();
			// we only peeked, but didn't grab the message
		return size;
	}

	sPorts[slot].messages.RemoveHead();
	sPorts[slot].total_count++;
	sPorts[slot].write_count++;
	sPorts[slot].read_count--;

	notify_port_select_events(slot, B_EVENT_WRITE);
	sPorts[slot].write_condition.NotifyOne();
		// make one spot in queue available again for write

	locker.Unlock();

	size_t size = copy_port_message(message, _code, buffer, bufferSize,
		userCopy);
	T(Read(sPorts[slot], message->code, size));

	put_port_message(message);
	return size;
}
示例#6
0
文件: port.cpp 项目: mariuz/haiku
status_t
_get_port_message_info_etc(port_id id, port_message_info* info,
	size_t infoSize, uint32 flags, bigtime_t timeout)
{
	if (info == NULL || infoSize != sizeof(port_message_info))
		return B_BAD_VALUE;
	if (!sPortsActive || id < 0)
		return B_BAD_PORT_ID;

	flags &= B_CAN_INTERRUPT | B_KILL_CAN_INTERRUPT | B_RELATIVE_TIMEOUT
		| B_ABSOLUTE_TIMEOUT;
	int32 slot = id % sMaxPorts;

	MutexLocker locker(sPorts[slot].lock);

	if (sPorts[slot].id != id
		|| (is_port_closed(slot) && sPorts[slot].messages.IsEmpty())) {
		T(Info(sPorts[slot], 0, B_BAD_PORT_ID));
		TRACE(("_get_port_message_info_etc(): %s port %ld\n",
			sPorts[slot].id == id ? "closed" : "invalid", id));
		return B_BAD_PORT_ID;
	}

	while (sPorts[slot].read_count == 0) {
		// We need to wait for a message to appear
		if ((flags & B_RELATIVE_TIMEOUT) != 0 && timeout <= 0)
			return B_WOULD_BLOCK;

		ConditionVariableEntry entry;
		sPorts[slot].read_condition.Add(&entry);

		locker.Unlock();

		// block if no message, or, if B_TIMEOUT flag set, block with timeout
		status_t status = entry.Wait(flags, timeout);

		if (status != B_OK) {
			T(Info(sPorts[slot], 0, status));
			return status;
		}

		locker.Lock();

		if (sPorts[slot].id != id
			|| (is_port_closed(slot) && sPorts[slot].messages.IsEmpty())) {
			// the port is no longer there
			T(Info(sPorts[slot], 0, B_BAD_PORT_ID));
			return B_BAD_PORT_ID;
		}
	}

	// determine tail & get the length of the message
	port_message* message = sPorts[slot].messages.Head();
	if (message == NULL) {
		panic("port %ld: no messages found\n", sPorts[slot].id);
		return B_ERROR;
	}

	info->size = message->size;
	info->sender = message->sender;
	info->sender_group = message->sender_group;
	info->sender_team = message->sender_team;

	T(Info(sPorts[slot], message->code, B_OK));

	// notify next one, as we haven't read from the port
	sPorts[slot].read_condition.NotifyOne();

	return B_OK;
}