コード例 #1
0
ファイル: seg.c プロジェクト: JamesLinus/vsta
/*
 * make_seg()
 *	Given a vas and a byte range, return a segment describing it.
 *
 * The byte range must occupy a single pset.  On error, 0 is returned.
 */
struct seg *
make_seg(struct vas *vas, void *buf, uint buflen)
{
	struct pview *pv;
	struct seg *s;
	int x;

	/*
	 * Invalid buf/buflen?
	 */
	if ((buf == 0) || (buflen == 0)) {
		return(0);
	}

	/*
	 * Get new segment
	 */
	s = MALLOC(sizeof(struct seg), MT_SEG);

	/*
	 * Find pview holding the starting address
	 */
	pv = find_pview(vas, buf);
	if (!pv) {
		FREE(s, MT_SEG);
		return(0);
	}

	/*
	 * Make sure end lies within pview
	 */
	if (((char *)buf + buflen) > ((char *)pv->p_vaddr+ptob(pv->p_len))) {
		v_lock(&pv->p_set->p_lock, SPL0);
		FREE(s, MT_SEG);
		return(0);
	}

	/*
	 * Duplicate view, record byte offset
	 */
	s->s_pview = *pv;
	ref_pset(pv->p_set);
	s->s_off = (char *)buf - (char *)pv->p_vaddr;
	s->s_len = buflen;

	/*
	 * Trim off leading and trailing pages from the view
	 */
	pv = &s->s_pview;
	x = btop(s->s_off);
	pv->p_off += x;
	s->s_off -= ptob(x);
	pv->p_len = btorp(s->s_off + buflen);

	/*
	 * Done with set
	 */
	v_lock(&pv->p_set->p_lock, SPL0);
	return(s);
}
コード例 #2
0
ファイル: msgcon.c プロジェクト: JamesLinus/vsta
/*
 * shut_client()
 *	Shut down a connection from a client to a server
 */
void
shut_client(struct portref *pr, int sema_held)
{
	struct sysmsg *sm;
	struct port *port;
	ulong refs;

	/*
	 * Decrement the reference count, just return if
	 * it's not zero yet.
	 * TBD: consider compare-and-exchange
	 */
	p_lock_void(&pr->p_lock, SPL0);
	refs = pr->p_refs;
	pr->p_refs -= 1;
	v_lock(&pr->p_lock, SPL0_SAME);
	if (refs > 1) {
		if (sema_held) {
			v_sema(&pr->p_sema);
		}
		return;
	}

	/*
	 * Get a system message
	 */
	sm = MALLOC(sizeof(struct sysmsg), MT_SYSMSG);
	sm->sm_sender = pr;
	sm->sm_op = M_DISCONNECT;
	sm->sm_arg = (long)pr;
	sm->sm_arg1 = sm->sm_nseg = 0;

	/*
	 * If he's closed on us at the same time, no problem.
	 */
	p_lock_void(&pr->p_lock, SPL0);
	if (!(port = pr->p_port)) {
		v_lock(&pr->p_lock, SPL0_SAME);
		free_portref(pr);
		FREE(sm, MT_SYSMSG);
		return;
	}

	/*
	 * Put disconnect message on port's queue.  Flag that we've
	 * sent our final message.  He will clean up from here.
	 */
	pr->p_state = PS_CLOSING;
	queue_msg(port, sm, SPL0);
	if (!sema_held) {
		p_sema_v_lock(&pr->p_sema, PRIHI, &pr->p_lock);
	} else {
		v_lock(&pr->p_lock, SPL0_SAME);
	}
}
コード例 #3
0
ファイル: output.cpp プロジェクト: TangoCash/tangos-enigma2
bool Output::Play()
{
	bool ret = true;

	ScopedLock v_lock(videoMutex);
	ScopedLock a_lock(audioMutex);

	AVCodecContext *avcc;

	if (videoTrack && videoTrack->stream && videofd > -1 && (avcc = videoTrack->stream->codec)) {
		videoWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type, videoTrack->ac3flags);
		videoWriter->Init(videofd, videoTrack->stream, player);
		if (dioctl(videofd, VIDEO_SET_ENCODING, videoWriter->GetVideoEncoding(avcc->codec_id))
		||  dioctl(videofd, VIDEO_PLAY, NULL))
			ret = false;
	}

	if (audioTrack && audioTrack->stream && audiofd > -1 && (avcc = audioTrack->stream->codec)) {
		audioWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type, audioTrack->ac3flags);
		audioWriter->Init(audiofd, audioTrack->stream, player);
		audio_encoding_t audioEncoding = AUDIO_ENCODING_LPCMA;
		if (audioTrack->ac3flags != 6)
			audioEncoding = audioWriter->GetAudioEncoding(avcc->codec_id);
		if (dioctl(audiofd, AUDIO_SET_ENCODING, audioEncoding)
		||  dioctl(audiofd, AUDIO_PLAY, NULL))
			ret = false;
	}
	return ret;
}
コード例 #4
0
ファイル: msgcon.c プロジェクト: JamesLinus/vsta
/*
 * msg_accept()
 *	Accept a connection with ID "arg_tran"
 */
int
msg_accept(long arg_tran)
{
	struct portref *pr;
	int error;

	/*
	 * Look up the transaction, sanity check it
	 */
	pr = tran_find(arg_tran);
	if (!pr) {
		return(-1);
	}
	if (pr->p_state != PS_OPENING) {
		/*
		 * Our caller's hosed.  He's not connecting.
		 */
		error = err(EINVAL);
	} else {

		/*
		 * Flag success, wake him.
		 */
		pr->p_state = PS_IODONE;
		v_sema(&pr->p_iowait);
		error = 0;
	}
	v_lock(&pr->p_lock, SPL0);
	return(error);
}
コード例 #5
0
ファイル: output.cpp プロジェクト: Audioniek/apps
bool Output::SwitchVideo(AVStream *stream)
{
	ScopedLock v_lock(videoMutex);
	if (stream == videoStream)
	{
		return true;
	}
	if (videofd > -1)
	{
		dioctl(videofd, VIDEO_STOP, NULL);
		ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
	}
	videoStream = stream;
	if (stream)
	{
		AVCodecContext *avcc = stream->codec;
		if (!avcc)
		{
			return false;
		}
		videoWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type);
		videoWriter->Init(videofd, videoStream, player);
		if (videofd > -1)
		{
			dioctl(videofd, VIDEO_SET_ENCODING, Writer::GetVideoEncoding(avcc->codec_id));
			dioctl(videofd, VIDEO_PLAY, NULL);
		}
	}
	return true;
}
コード例 #6
0
ファイル: output.cpp プロジェクト: Audioniek/apps
bool Output::Flush()
{
	bool ret = true;

	ScopedLock v_lock(videoMutex);
	ScopedLock a_lock(audioMutex);

	if (videofd > -1 && ioctl(videofd, VIDEO_FLUSH, NULL))
	{
		ret = false;
	}
	if (audiofd > -1 && audioWriter)
	{
		// flush audio decoder
		AVPacket packet;
		packet.data = NULL;
		packet.size = 0;
		audioWriter->Write(&packet, 0);

		if (ioctl(audiofd, AUDIO_FLUSH, NULL))
		{
			ret = false;
		}
	}
	return ret;
}
コード例 #7
0
ファイル: output.cpp プロジェクト: Audioniek/apps
bool Output::Play()
{
	bool ret = true;

	ScopedLock v_lock(videoMutex);
	ScopedLock a_lock(audioMutex);

	AVCodecContext *avcc;

	if (videoStream && videofd > -1 && (avcc = videoStream->codec))
	{
		videoWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type);
		videoWriter->Init(videofd, videoStream, player);
		if (dioctl(videofd, VIDEO_SET_ENCODING, videoWriter->GetVideoEncoding(avcc->codec_id))
		||  dioctl(videofd, VIDEO_PLAY, NULL))
		{
			ret = false;
		}
	}

	if (audioStream && audiofd > -1 && (avcc = audioStream->codec))
	{
		audioWriter = Writer::GetWriter(avcc->codec_id, avcc->codec_type);
		audioWriter->Init(audiofd, audioStream, player);
		if (dioctl(audiofd, AUDIO_SET_ENCODING, audioWriter->GetAudioEncoding(avcc->codec_id))
		||  dioctl(audiofd, AUDIO_PLAY, NULL))
		{
			ret = false;
		}
	}
	return ret;
}
コード例 #8
0
ファイル: abc.c プロジェクト: JamesLinus/vsta
/*
 * get()
 *	Access buffer, interlocking with BG
 */
static void
get(struct buf *b)
{
	if (!(b->b_flags & B_BUSY)) {
		return;
	}
	p_lock(&b->b_lock);
	if (!(b->b_flags & B_BUSY)) {
		v_lock(&b->b_lock);
		return;
	}
	b->b_flags |= B_WANT;
	v_lock(&b->b_lock);
	mutex_thread(0);
	ASSERT_DEBUG(!(b->b_flags & (B_WANT|B_BUSY)), "get: still busy/wanted");
}
コード例 #9
0
ファイル: abc.c プロジェクト: JamesLinus/vsta
/*
 * _sync_buf()
 *	Sync back buffer if dirty
 *
 * Write back the 1st sector, or the whole buffer, as appropriate
 */
static void
_sync_buf(struct buf *b, int from_qio)
{
	ASSERT_DEBUG(b->b_flags & (B_SEC0 | B_SECS), "sync_buf: not ref'ed");

	/*
	 * Skip it if not dirty
	 */
	if (!(b->b_flags & B_DIRTY)) {
		return;
	}

	/*
	 * Do the I/O--whole buffer, or just 1st sector if that was
	 * the only sector referenced.
	 */
	if (!from_qio) {
		get(b);
	}
	if (b->b_flags & B_SECS) {
		write_secs(b->b_start, b->b_data, b->b_nsec);
	} else {
		write_secs(b->b_start, b->b_data, 1);
	}
	p_lock(&b->b_lock);
	b->b_flags &= ~B_DIRTY;
	v_lock(&b->b_lock);

	/*
	 * If there are possible handles, clear them too
	 */
	if (b->b_handles) {
		bzero(b->b_handles, b->b_nhandle * sizeof(void *));
	}
}
コード例 #10
0
ファイル: output.cpp プロジェクト: TangoCash/tangos-enigma2
bool Output::Stop()
{
	bool ret = true;

	ScopedLock v_lock(videoMutex);
	ScopedLock a_lock(audioMutex);

	if (videofd > -1) {
		ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
		/* set back to normal speed (end trickmodes) */
		dioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY);
		if (dioctl(videofd, VIDEO_STOP, NULL))
			ret = false;
	}

	if (audiofd > -1) {
		ioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL);
		/* set back to normal speed (end trickmodes) */
		dioctl(audiofd, AUDIO_SET_SPEED, DVB_SPEED_NORMAL_PLAY);
		if (dioctl(audiofd, AUDIO_STOP, NULL))
			ret = false;
	}

	return ret;
}
コード例 #11
0
ファイル: output.cpp プロジェクト: TangoCash/tangos-enigma2
bool Output::Open()
{
	ScopedLock v_lock(videoMutex);
	ScopedLock a_lock(audioMutex);

	if (videofd < 0)
		videofd = open(VIDEODEV, O_RDWR);

	if (videofd < 0)
		return false;

	ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
	dioctl(videofd, VIDEO_SELECT_SOURCE, (void *) VIDEO_SOURCE_MEMORY);
	dioctl(videofd, VIDEO_SET_STREAMTYPE, (void *) STREAM_TYPE_PROGRAM);
	dioctl(videofd, VIDEO_SET_SPEED, DVB_SPEED_NORMAL_PLAY);

	if (audiofd < 0)
		audiofd = open(AUDIODEV, O_RDWR);

	if (audiofd < 0) {
		close(videofd);
		videofd = -1;
		return false;
	}

	ioctl(audiofd, AUDIO_CLEAR_BUFFER, NULL);
	dioctl(audiofd, AUDIO_SELECT_SOURCE, (void *) AUDIO_SOURCE_MEMORY);
	dioctl(audiofd, AUDIO_SET_STREAMTYPE, (void *) STREAM_TYPE_PROGRAM);

	return true;
}
コード例 #12
0
ファイル: base_sink.cpp プロジェクト: yuetianle/gateway
void base_sink::proc_input()
{
	deque<basic_buff_ptr> temp;
	while (m_open_flag)
	{
		{
			v_lock(write_lck, mtx_msg_queue);
			if (m_msg_queue.size() > 0)
			{
				temp.swap(m_msg_queue);
			}
		}
		for (auto& x : temp)
		{
			process_internal(x);
		}
		temp.clear();
		chrono::system_clock::time_point tp = chrono::system_clock::now() + chrono::milliseconds(500);
		v_unique_lock(lck, mtx_input);
		m_cond_input.wait_for(lck, chrono::milliseconds(100));
		if (!m_open_flag)
		{
			break;
		}
	}
	for (auto& x : m_msg_queue)
	{
		process_internal(x);
	}
	m_msg_queue.clear();
}
コード例 #13
0
int msg_distribution::read_host_info(const string &file_name)
{
	if (!file_name.empty())
	{
		fsys::path s(file_name);
		v_lock(lk, s_host_mutex);
		if (fsys::exists(s))
		{
			
			pugi::xml_document doc;
			pugi::xml_parse_result xml_ret = doc.load_file(file_name.c_str());
			if (pugi::xml_parse_status::status_ok == xml_ret.status)
			{
				pugi::xml_node host_nodes = doc.child("hosts");
				if (!host_nodes.empty())
				{
					for (pugi::xml_node_iterator item = host_nodes.begin(); item != host_nodes.end(); ++item)
					{
						string manuc = item->attribute("manufacture").as_string();
						int	   port = item->attribute("port").as_int();
						s_host_listen_lists.insert(port, manuc);
					}
				}
				/*for (pugi::xml_node_iterator item = doc.begin(); item != doc.end(); ++item)
				{
					string manuc = item->attribute("manufacture").as_string();
					int	   port = item->attribute("port").as_int();
					s_host_listen_lists.insert(port, manuc);
				}*/
				return v_OK;
			}
		}
	}
	return v_ERR_BAD_ARGUMENT;
}
コード例 #14
0
ファイル: sema.c プロジェクト: JamesLinus/vsta
/*
 * v_sema()
 *	Leave semaphore
 */
void
v_sema(struct sema *s)
{
	int val;

	p_lock(&s->s_locked);
	val = (s->s_val += 1);
	v_lock(&s->s_locked);
	if (val <= 0) {
		(void)send(s->s_portmaster, FS_SEEK);
	}
}
コード例 #15
0
ファイル: msgcon.c プロジェクト: JamesLinus/vsta
/*
 * close_client()
 *	Dump a client when the server closes its port
 *
 * Returns 1 if it detects messages in the port's queue; no action
 * is taken on the portref.  Otherwise zeroes the p_port field of
 * the portref, flagging that the server's gone.  It also removes
 * the portref from the port's list, and finally returns 0.
 */
static int
close_client(struct port *port, struct portref *pr)
{
	int err;

	unmapsegs(&pr->p_segs);
	p_lock_void(&pr->p_lock, SPL0);
	p_lock_void(&port->p_lock, SPLHI);
	if (port->p_hd) {
		err = 1;
	} else {
		pr->p_port = 0;
		if (blocked_sema(&pr->p_iowait)) {
			v_sema(&pr->p_iowait);
		}
		deref_port(port, pr);
		err = 0;
	}
	v_lock(&port->p_lock, SPL0);
	v_lock(&pr->p_lock, SPL0_SAME);
	return(err);
}
コード例 #16
0
ファイル: output.cpp プロジェクト: TangoCash/tangos-enigma2
bool Output::Write(AVStream *stream, AVPacket *packet, int64_t pts)
{
	switch (stream->codec->codec_type) {
		case AVMEDIA_TYPE_VIDEO: {
			ScopedLock v_lock(videoMutex);
			return videofd > -1 && videoWriter && videoWriter->Write(packet, pts);
		}
		case AVMEDIA_TYPE_AUDIO: {
			ScopedLock a_lock(audioMutex);
			return audiofd > -1 && audioWriter && audioWriter->Write(packet, pts);
		}
		default:
			return false;
	}
}
コード例 #17
0
ファイル: output.cpp プロジェクト: TangoCash/tangos-enigma2
bool Output::Continue()
{
	bool ret = true;

	ScopedLock v_lock(videoMutex);
	ScopedLock a_lock(audioMutex);

	if (videofd > -1 && dioctl(videofd, VIDEO_CONTINUE, NULL))
		ret = false;

	if (audiofd > -1 && dioctl(audiofd, AUDIO_CONTINUE, NULL))
		ret = false;

	return ret;
}
コード例 #18
0
ファイル: sema.c プロジェクト: JamesLinus/vsta
/*
 * p_sema()
 *	Enter semaphore
 */
int
p_sema(struct sema *s)
{
	int val;

	p_lock(&s->s_locked);
	val = (s->s_val -= 1);
	v_lock(&s->s_locked);
	if (val >= 0) {
		return(0);
	}
	if (send(s->s_port, FS_READ)) {
		return(-1);
	}
	return(0);
}
コード例 #19
0
ファイル: output.cpp プロジェクト: TangoCash/tangos-enigma2
bool Output::Pause()
{
	bool ret = true;

	ScopedLock v_lock(videoMutex);
	ScopedLock a_lock(audioMutex);

	if (videofd > -1) {
		if (dioctl(videofd, VIDEO_FREEZE, NULL))
			ret = false;
	}

	if (audiofd > -1) {
		if (dioctl(audiofd, AUDIO_PAUSE, NULL))
			ret = false;
	}

	return ret;
}
コード例 #20
0
ファイル: abc.c プロジェクト: JamesLinus/vsta
/*
 * bg_thread()
 *	Endless loop to take QIO operations and execute them
 */
static void
bg_thread(int dummy)
{
	uint next = 0, want;
	struct qio *q;
	struct buf *b;

	/*
	 * Become ephemeral
	 */
	(void)sched_op(SCHEDOP_EPHEM, 0);

	/*
	 * Endless loop, serving background requests
	 */
	for (;;) {
		/*
		 * Get next operation
		 */
		mutex_thread(0);
		q = &qios[next++];
		if (next >= NQIO) {
			next = 0;
		}

		/*
		 * Execute it
		 */
		exec_qio(b = q->q_buf, q->q_op);

		/*
		 * Flag completion
		 */
		q->q_op = 0;
		p_lock(&b->b_lock);
		want = b->b_flags & B_WANT;
		b->b_flags &= ~(B_BUSY | B_WANT);
		v_lock(&b->b_lock);
		if (want) {
			mutex_thread(fg_pid);
		}
	}
}
コード例 #21
0
ファイル: output.cpp プロジェクト: TangoCash/tangos-enigma2
bool Output::Close()
{
	Stop();

	ScopedLock v_lock(videoMutex);
	ScopedLock a_lock(audioMutex);

	if (videofd > -1) {
		close(videofd);
		videofd = -1;
	}
	if (audiofd > -1) {
		close(audiofd);
		audiofd = -1;
	}

	videoTrack = NULL;
	audioTrack = NULL;

	return true;
}
コード例 #22
0
ファイル: msgcon.c プロジェクト: JamesLinus/vsta
/*
 * msg_portname()
 *	Tell server port name associated with portref
 */
port_name
msg_portname(port_t arg_port)
{
	struct portref *pr;
	port_name pn;

	/*
	 * Access our open port reference.
	 */
	pr = find_portref(curthread->t_proc, arg_port);
	if (pr) {
		struct port *port;

		/*
		 * It looked good.  Take the portref spinlock so we
		 * don't race with the server trying to exit.  If we're
		 * still connected to a server, get his port_name.
		 */
		port = pr->p_port;
		if (port) {
			pn = port->p_name;
		} else {
			/*
			 * He bombed
			 */
			pn = err(EIO);
		}
		v_lock(&pr->p_lock, SPL0);
		v_sema(&pr->p_sema);
	} else {
		/*
		 * Bad port requested.  find_portref() sets err().
		 */
		pn = -1;
	}
	return(pn);
}
コード例 #23
0
ファイル: base_sink.cpp プロジェクト: yuetianle/gateway
int base_sink::input(basic_buff_ptr buf)
{
	v_lock(lck, mtx_msg_queue);
	m_msg_queue.push_back(buf);
	return v_OK;
}
コード例 #24
0
ファイル: output.cpp プロジェクト: TangoCash/tangos-enigma2
bool Output::ClearVideo()
{
	ScopedLock v_lock(videoMutex);
	return videofd > -1 && !ioctl(videofd, VIDEO_CLEAR_BUFFER, NULL);
}
コード例 #25
0
ファイル: output.cpp プロジェクト: TangoCash/tangos-enigma2
bool Output::SlowMotion(int speed)
{
	ScopedLock v_lock(videoMutex);
	return videofd > -1 && !dioctl(videofd, VIDEO_SLOWMOTION, speed);
}
コード例 #26
0
ファイル: output.cpp プロジェクト: TangoCash/tangos-enigma2
bool Output::FastForward(int speed)
{
	ScopedLock v_lock(videoMutex);
	return videofd > -1 && !dioctl(videofd, VIDEO_FAST_FORWARD, speed);
}
コード例 #27
0
ファイル: ptrace.c プロジェクト: JamesLinus/vsta
/*
 * ptrace_slave()
 *	Called by slave process when it detects a need to call the master
 *
 * Actually, it's called when it *appears* that a need exists; this
 * routine does locking and handles the case where it really wasn't
 * needed.
 *
 * XXX use "event" (pack into longs?), and allow them to clear it
 * unless it's the unblockable kill message.
 */
void
ptrace_slave(char *event, uint why)
{
	struct thread *t = curthread;
	struct proc *p = t->t_proc;
	struct portref *pr;
	port_t port;
	long args[3];
	uint x;
	extern struct portref *find_portref();

retry:
	p_sema(&p->p_sema, PRIHI);

	/*
	 * If we've raced with another thread doing the setup, just
	 * continue.  This would be a pretty chaotic situation anyway.
	 */
	if (p->p_dbg.pd_flags & PD_CONNECTING) {
		v_sema(&p->p_sema);
		return;
	}

	/*
	 * If it appears we're the first to have seen this ptrace
	 * request, do the initial connect and setup.  Then start
	 * over.
	 */
	if (p->p_dbg.pd_name && (p->p_dbg.pd_port == -1)) {
		ptrace_attach();
		goto retry;
	}

	/*
	 * Try to get our portref to the debug port.  If it has
	 * gone away, clear our debug environment and continue.
	 *
	 * After this block of code, we hold a semaphore for clients
	 * on the named portref, and we have released our proc
	 * semaphore.  We are thus in a pretty good position to
	 * interact at length with our debugger.
	 */
	port = p->p_dbg.pd_port;
	v_sema(&p->p_sema);
	pr = find_portref(p, port);
	if (pr == 0) {
		p_sema(&p->p_sema, PRIHI);
		/*
		 * This could actually blow away a usable, new debug
		 * session.  C'est la vie.  To get here you had to
		 * hunt down your port and msg_disconnect() it yourself,
		 * which is pretty hosed in itself.
		 */
		if (p->p_dbg.pd_port == port) {
			bzero(&p->p_dbg, sizeof(struct pdbg));
		}
		v_sema(&p->p_sema);
		return;
	}

	/*
	 * kernmsg_send() does this for itself.  We hold the
	 * semaphore, so we won't race with other I/O clients.
	 * Since we have the lock, take this opportunity to
	 * flag that this connection should never be dup'ed.
	 */
	pr->p_flags |= PF_NODUP;
	v_lock(&pr->p_lock, SPL0);

	/*
	 * Return value is initially the bits which matched and
	 * caused us to drop into ptrace_slave().
	 */
	args[0] = why;
	args[1] = 0;
	for (;;) {
		/*
		 * Build a message and send it
		 */
		if (kernmsg_send(pr, PD_SLAVE, args) < 0) {
			v_sema(&pr->p_sema);
			p_sema(&p->p_sema, PRIHI);
			(void)msg_disconnect(p->p_dbg.pd_port);
			bzero(&p->p_dbg, sizeof(struct pdbg));
			v_sema(&p->p_sema);
			return;
		}

		/*
		 * Act on his answer
		 */
		switch (args[2]) {
		case PD_RUN:	/* Continue running */
			v_sema(&pr->p_sema);
			return;

		case PD_STEP:	/* Run for one step */
			single_step(args[0]);
			break;

		case PD_BREAK:	/* Set/clear breakpoint */
			args[0] = set_break(args[1], args[0]);
			break;

		case PD_RDREG:	/* Read register */
			args[0] = getreg(args[0]);
			break;

		case PD_WRREG:	/* Write register */
			args[0] = setreg(args[0], args[1]);
			break;

		case PD_MASK:	/* Set debug event mask */
			p->p_dbg.pd_flags = args[0];
			break;

		case PD_RDMEM:	/* Read memory */
			{ ulong l;
			  if (copyin((void *)args[0], &l, sizeof(l)) < 0) {
				args[1] = 1;
			  } else {
			  	args[0] = l;
				args[1] = 0;
			  }
			}
			break;

		case PD_WRMEM:	/* Write memory */
			if (copyout((void *)args[0], &args[1],
					sizeof(args[1]))) {
				args[1] = 1;
			} else {
				args[1] = 0;
			}
			args[0] = 0;
			break;

		case PD_MEVENT:	/* Read/write event string */
			x = args[0] & 0xFF;
			if (x > ERRLEN) {
				args[0] = -1;
				break;
			}
			if (args[0] & 0xFF00) {
				if (event) {
					event[x] = args[1];
				}
			} else {
				if (event) {
					args[1] = event[x];
				} else {
					args[1] = 0;
				}
			}
			break;

		case PD_PID:	/* Tell him our PID/TID */
			args[0] = p->p_pid;
			args[1] = t->t_pid;
			break;

		default:	/* Bogus--drop him */
			v_sema(&pr->p_sema);
			(void)msg_disconnect(port);
			p_sema(&p->p_sema, PRIHI);
			if (p->p_dbg.pd_port == port) {
				bzero(&p->p_dbg, sizeof(struct pdbg));
			}
			v_sema(&p->p_sema);
			return;
		}
	}
}
コード例 #28
0
ファイル: vm_fault.c プロジェクト: JamesLinus/vsta
/*
 * vas_fault()
 *	Process a fault within the given address space
 *
 * Returns 0 if the fault could be resolved, 1 if process needs to
 * receive an event.  The HAT layer is expected to reliably hold
 * a translation added via hat_addtrans() until hat_deletetrans().
 * A lost translation would cause the atl to hold multiple entries.
 */
vas_fault(void *vas, void *vaddr, int write)
{
	struct pview *pv;
	struct pset *ps;
	struct perpage *pp;
	uint idx, pvidx;
	int error = 0;
	int wasvalid;

	/*
	 * Easiest--no view matches address
	 */
	if ((pv = find_pview(vas, vaddr)) == 0) {
		return(1);
	}
	ASSERT_DEBUG(pv->p_valid, "vas_fault: pview !p_valid");
	ps = pv->p_set;

	/*
	 * Next easiest--trying to write to read-only view
	 */
	if (write && (pv->p_prot & PROT_RO)) {
		v_lock(&ps->p_lock, SPL0_SAME);
		return(1);
	}

	/*
	 * Transfer from pset lock to page slot lock
	 */
	pvidx = btop((char *)vaddr - (char *)pv->p_vaddr);
	idx = pvidx + pv->p_off;
	pp = find_pp(ps, idx);
	lock_slot(ps, pp);

	/*
	 * If the slot is bad, can't fill
	 */
	if (pp->pp_flags & PP_BAD) {
		error = 1;
		goto out;
	}

	/*
	 * If slot is invalid, request it be filled.  Otherwise just
	 * add a reference.
	 */
	if (!(pp->pp_flags & PP_V)) {
		wasvalid = 0;
		if ((*(ps->p_ops->psop_fillslot))(ps, pp, idx)) {
			error = 1;
			goto out;
		}
		ASSERT(pp->pp_flags & PP_V, "vm_fault: lost the page");
	} else {
		wasvalid = 1;
		ref_slot(ps, pp, idx);
	}

	/*
	 * Break COW association when we write it
	 */
	if ((pp->pp_flags & PP_COW) && write) {
		/*
		 * May or may not be there.  If it is, remove
		 * its reference from the per-page struct.
		 */
		if (wasvalid) {
			if (pv->p_valid[pvidx]) {
				ASSERT(delete_atl(pp, pv, pvidx) == 0,
					"vas_fault: p_valid no atl");
				pv->p_valid[pvidx] = 0;
			}
			deref_slot(ps, pp, idx);
		}
		cow_write(ps, pp, idx);
		ASSERT(pp->pp_flags & PP_V, "vm_fault: lost the page 2");

	/*
	 * If not writing to a COW association, then inhibit adding
	 * the translation if it's already present (another thread
	 * ran and brought it in for us, probably)
	 */
	} else if (pv->p_valid[pvidx]) {
		deref_slot(ps, pp, idx);
		goto out;
	}

	/*
	 * With a valid slot, add a hat translation and tabulate
	 * the entry with an atl.
	 */
	add_atl(pp, pv, pvidx, 0);
	hat_addtrans(pv, vaddr, pp->pp_pfn, pv->p_prot |
		((pp->pp_flags & PP_COW) ? PROT_RO : 0));
	ASSERT_DEBUG(pv->p_valid[pvidx] == 0, "vas_fault: p_valid went on");
	pv->p_valid[pvidx] = 1;

	/*
	 * Free the various things we hold and return
	 */
out:
	unlock_slot(ps, pp);
	return(error);
}
コード例 #29
0
ファイル: msgcon.c プロジェクト: JamesLinus/vsta
/*
 * bounce_msgs()
 *	Take the messages off a port, and bounce each of them
 *
 * We need to do this as sysmsg's can have segments within them,
 * and we need to clean those segments up.  This routine is called
 * with the port locked, and returns with it released.
 */
static void
bounce_msgs(struct port *port)
{
	struct sysmsg *msgs, *sm, *smn;
	struct portref *pr;

	/*
	 * Pull whatever messages are on the port out of the queue.
	 * We'll walk the list once we've released our lock.  We can't
	 * hold the port lock and go for the portrefs, as we lock in
	 * the other order, and would deadlock.
	 */
	p_lock_void(&port->p_lock, SPL0);
	msgs = port->p_hd;
	port->p_hd = 0;
	v_lock(&port->p_lock, SPL0);

	/*
	 * Step through the linked list.  As our clients will be waking
	 * up and discarding messages, we record the next pointer field
	 * into a local variable.
	 */
	for (sm = msgs; sm; sm = smn) {
		/*
		 * Get pointers, apply sanity check
		 */
		pr = sm->sm_sender;
		smn = sm->sm_next;
#ifdef DEBUG
		sm->sm_next = 0;
#endif

		/*
		 * ISR messages are somewhat special.  They don't have
		 * a portref, and there's no connection to break.
		 * We have already de-registered, so it can't come
		 * back.
		 */
		if (pr == 0) {
			ASSERT_DEBUG(sm->sm_op == M_ISR,
				"bounce_msgs: !pr !M_ISR");
			continue;
		}

		ASSERT_DEBUG(pr->p_port == port,
			"bounce_msgs: msg in queue not for port");

		/*
		 * Lock portref, then port
		 */
		p_lock_void(&pr->p_lock, SPL0_SAME);
		p_lock_void(&port->p_lock, SPLHI);

		/*
		 * If any segments in the message, discard them
		 */
		if (sm->sm_nseg > 0) {
			freesegs(sm);
		}

		/*
		 * If the client has tried to abort the operation,
		 * ignore anything but the abort message itself.
		 */
		if ((pr->p_state == PS_ABWAIT) &&
				(sm->sm_op != M_ABORT)) {
			/* nothing */ ;
		} else {

			/*
			 * Fill in sysmsg as an I/O error, clear
			 * p_port to preclude further I/O, and
			 * kick client awake.
			 */
			sm->sm_arg1 = sm->sm_arg = -1;
			strcpy(sm->sm_err, EIO);
			pr->p_port = 0;
			v_sema(&pr->p_iowait);
		}

		/*
		 * Release locks, and remove the portref from our list
		 */
		v_lock(&port->p_lock, SPL0);
		v_lock(&pr->p_lock, SPL0_SAME);
	}
}
コード例 #30
0
ファイル: msgcon.c プロジェクト: JamesLinus/vsta
/*
 * msg_err()
 *	Return error reply to message
 *
 * Mostly because I didn't think it out too well, msg_err() returns
 * errors to both regular operations received with msg_receive(), as
 * well as connection requests.  A connection is accepted with
 * msg_accept(), but rejected here.
 */
int
msg_err(long arg_tran, const char *arg_why, int arg_len)
{
	struct portref *pr;
	struct port *port;
	struct proc *p = curthread->t_proc;
	char errmsg[ERRLEN];

	/*
	 * Validate error string, copy it in.  It's small, so we
	 * just stash it on the stack.
	 */
	if ((arg_len < 1) || (arg_len >= ERRLEN)) {
		return(err(EINVAL));
	}
	if (get_ustr(errmsg, ERRLEN, arg_why, arg_len)) {
		return(-1);
	}

	/*
	 * Validate transaction ID.   If we don't find it, this
	 * system call returns an error immediately.  For failed
	 * opens, delete it from the hash before we release
	 * the mutex.
	 */
	if (p_sema(&p->p_sema, PRICATCH)) {
		return(err(EINTR));
	}
	pr = hash_lookup(p->p_prefs, arg_tran);
	if (pr) {
		p_lock_void(&pr->p_lock, SPL0);
		if (pr->p_state == PS_OPENING) {
			hash_delete(p->p_prefs, arg_tran);
		}
	}
	v_sema(&p->p_sema);
	if (!pr) {
		return(err(EINVAL));
	}

	/*
	 * If the server port's on its way down, never mind
	 * this.  If there's not a request outstanding from
	 * this client, error that as well.
	 */
	port = pr->p_port;
	if (!port) {
		v_lock(&pr->p_lock, SPL0);
		return(err(EIO));
	}
	if (pr->p_msg == 0) {
		v_lock(&pr->p_lock, SPL0);
		return(err(EINVAL));
	}

	/*
	 * Figure out if this is an open, an I/O, or if our caller's
	 * just jerking us around.
	 */
	switch (pr->p_state) {
	case PS_IOWAIT:
		/*
		 * The usual--he sent a request, and here's the error
		 * response.  Flag an error using the m_arg field of
		 * his sysmsg; put the error string in the m_err part.
		 * Wake him up.
		 */
		pr->p_state = PS_IODONE;
		pr->p_msg->sm_arg = -1;
		strcpy(pr->p_msg->sm_err, errmsg);
		v_sema(&pr->p_iowait);
		break;
	case PS_OPENING:
		/*
		 * A failed open needs the portref cleared
		 */
		p_lock_void(&port->p_lock, SPLHI);
		deref_port(port, pr);
		v_lock(&port->p_lock, SPL0);

		/*
		 * An open failed.  We already deleted him from our
		 * hash above.  Flag open failure by setting his
		 * p_state to anything but PS_IODONE.  Wake him up.
		 */
		pr->p_state = PS_ABDONE;
		strcpy(pr->p_msg->sm_err, errmsg);
		v_sema(&pr->p_iowait);
		break;
	default:
		v_lock(&pr->p_lock, SPL0);
		return(err(EINVAL));
	}
	v_lock(&pr->p_lock, SPL0);
	return(0);
}