Exemplo n.º 1
0
static void
deselect_select_infos(file_descriptor* descriptor, select_info* infos,
	bool putSyncObjects)
{
	TRACE(("deselect_select_infos(%p, %p)\n", descriptor, infos));

	select_info* info = infos;
	while (info != NULL) {
		select_sync* sync = info->sync;

		// deselect the selected events
		uint16 eventsToDeselect = info->selected_events & ~B_EVENT_INVALID;
		if (descriptor->ops->fd_deselect != NULL && eventsToDeselect != 0) {
			for (uint16 event = 1; event < 16; event++) {
				if ((eventsToDeselect & SELECT_FLAG(event)) != 0) {
					descriptor->ops->fd_deselect(descriptor, event,
						(selectsync*)info);
				}
			}
		}

		notify_select_events(info, B_EVENT_INVALID);
		info = info->next;

		if (putSyncObjects)
			put_select_sync(sync);
	}
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
status_t
select_sem(int32 id, struct select_info* info, bool kernel)
{
	cpu_status state;
	int32 slot;
	status_t error = B_OK;

	if (id < 0)
		return B_BAD_SEM_ID;

	slot = id % sMaxSems;

	state = disable_interrupts();
	GRAB_SEM_LOCK(sSems[slot]);

	if (sSems[slot].id != id) {
		// bad sem ID
		error = B_BAD_SEM_ID;
	} else if (!kernel
		&& sSems[slot].u.used.owner == team_get_kernel_team_id()) {
		// kernel semaphore, but call from userland
		error = B_NOT_ALLOWED;
	} else {
		info->selected_events &= B_EVENT_ACQUIRE_SEMAPHORE | B_EVENT_INVALID;

		if (info->selected_events != 0) {
			info->next = sSems[slot].u.used.select_infos;
			sSems[slot].u.used.select_infos = info;

			if (sSems[slot].u.used.count > 0)
				notify_select_events(info, B_EVENT_ACQUIRE_SEMAPHORE);
		}
	}

	RELEASE_SEM_LOCK(sSems[slot]);
	restore_interrupts(state);

	return error;
}
Exemplo n.º 4
0
status_t
select_fd(int32 fd, struct select_info* info, bool kernel)
{
	TRACE(("select_fd(fd = %ld, info = %p (%p), 0x%x)\n", fd, info,
		info->sync, info->selected_events));

	FDGetter fdGetter;
		// define before the context locker, so it will be destroyed after it

	io_context* context = get_current_io_context(kernel);
	MutexLocker locker(context->io_mutex);

	struct file_descriptor* descriptor = fdGetter.SetTo(context, fd, true);
	if (descriptor == NULL || (descriptor->open_mode & O_DISCONNECTED) != 0)
		return B_FILE_ERROR;

	uint16 eventsToSelect = info->selected_events & ~B_EVENT_INVALID;

	if (descriptor->ops->fd_select == NULL && eventsToSelect != 0) {
		// if the I/O subsystem doesn't support select(), we will
		// immediately notify the select call
		return notify_select_events(info, eventsToSelect);
	}

	// We need the FD to stay open while we're doing this, so no select()/
	// deselect() will be called on it after it is closed.
	atomic_add(&descriptor->open_count, 1);

	locker.Unlock();

	// select any events asked for
	uint32 selectedEvents = 0;

	for (uint16 event = 1; event < 16; event++) {
		if ((eventsToSelect & SELECT_FLAG(event)) != 0
			&& descriptor->ops->fd_select(descriptor, event,
				(selectsync*)info) == B_OK) {
			selectedEvents |= SELECT_FLAG(event);
		}
	}
	info->selected_events = selectedEvents
		| (info->selected_events & B_EVENT_INVALID);

	// Add the info to the IO context. Even if nothing has been selected -- we
	// always support B_EVENT_INVALID.
	locker.Lock();
	if (context->fds[fd] != descriptor) {
		// Someone close()d the index in the meantime. deselect() all
		// events.
		info->next = NULL;
		deselect_select_infos(descriptor, info, false);

		// Release our open reference of the descriptor.
		close_fd(descriptor);
		return B_FILE_ERROR;
	}

	// The FD index hasn't changed, so we add the select info to the table.

	info->next = context->select_infos[fd];
	context->select_infos[fd] = info;

	// As long as the info is in the list, we keep a reference to the sync
	// object.
	atomic_add(&info->sync->ref_count, 1);

	// Finally release our open reference. It is safe just to decrement,
	// since as long as the descriptor is associated with the slot,
	// someone else still has it open.
	atomic_add(&descriptor->open_count, -1);

	return B_OK;
}