kern_context.c revision 112888
1106977Sdeischen/*-
2106977Sdeischen * Copyright (c) 2002 Daniel M. Eischen <deischen@freebsd.org>
3106977Sdeischen * All rights reserved.
4106977Sdeischen *
5106977Sdeischen * Redistribution and use in source and binary forms, with or without
6106977Sdeischen * modification, are permitted provided that the following conditions
7106977Sdeischen * are met:
8106977Sdeischen * 1. Redistributions of source code must retain the above copyright
9106977Sdeischen *    notice, this list of conditions and the following disclaimer.
10106977Sdeischen * 2. Redistributions in binary form must reproduce the above copyright
11106977Sdeischen *    notice, this list of conditions and the following disclaimer in the
12106977Sdeischen *    documentation and/or other materials provided with the distribution.
13106977Sdeischen *
14106977Sdeischen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15106977Sdeischen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16106977Sdeischen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17106977Sdeischen * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18106977Sdeischen * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19106977Sdeischen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20106977Sdeischen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21106977Sdeischen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22106977Sdeischen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23106977Sdeischen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24106977Sdeischen * SUCH DAMAGE.
25106977Sdeischen *
26106977Sdeischen */
27106977Sdeischen/*
28106977Sdeischen * $FreeBSD: head/sys/kern/kern_context.c 112888 2003-03-31 22:49:17Z jeff $
29106977Sdeischen */
30106977Sdeischen
31106977Sdeischen#include <sys/param.h>
32106977Sdeischen#include <sys/kernel.h>
33106977Sdeischen#include <sys/lock.h>
34106977Sdeischen#include <sys/mutex.h>
35106977Sdeischen#include <sys/proc.h>
36106977Sdeischen#include <sys/sysent.h>
37106977Sdeischen#include <sys/systm.h>
38106977Sdeischen#include <sys/sysproto.h>
39106977Sdeischen#include <sys/signalvar.h>
40106977Sdeischen#include <sys/ucontext.h>
41106977Sdeischen
42106977Sdeischen/*
43106977Sdeischen * The first two fields of a ucontext_t are the signal mask and
44106977Sdeischen * the machine context.  The next field is uc_link; we want to
45106977Sdeischen * avoid destroying the link when copying out contexts.
46106977Sdeischen */
47106977Sdeischen#define	UC_COPY_SIZE	(sizeof(sigset_t) + sizeof(mcontext_t))
48106977Sdeischen
49106977Sdeischen
50106977Sdeischen#ifndef _SYS_SYSPROTO_H_
51106977Sdeischenstruct getcontext_args {
52106977Sdeischen	struct __ucontext *ucp;
53106977Sdeischen}
54106977Sdeischenstruct setcontext_args {
55106977Sdeischen	const struct __ucontext_t *ucp;
56106977Sdeischen}
57106977Sdeischenstruct swapcontext_args {
58106977Sdeischen	struct __ucontext *oucp;
59106977Sdeischen	const struct __ucontext_t *ucp;
60106977Sdeischen}
61106977Sdeischen#endif
62106977Sdeischen
63106977Sdeischen/*
64106977Sdeischen * MPSAFE
65106977Sdeischen */
66106977Sdeischenint
67106977Sdeischengetcontext(struct thread *td, struct getcontext_args *uap)
68106977Sdeischen{
69106977Sdeischen	ucontext_t uc;
70106977Sdeischen	int ret;
71106977Sdeischen
72106977Sdeischen	if (uap->ucp == NULL)
73106977Sdeischen		ret = EINVAL;
74106977Sdeischen	else {
75106977Sdeischen		get_mcontext(td, &uc.uc_mcontext);
76112888Sjeff		uc.uc_sigmask = td->td_sigmask;
77106977Sdeischen		ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
78106977Sdeischen	}
79106977Sdeischen	return (ret);
80106977Sdeischen}
81106977Sdeischen
82106977Sdeischen/*
83106977Sdeischen * MPSAFE
84106977Sdeischen */
85106977Sdeischenint
86106977Sdeischensetcontext(struct thread *td, struct setcontext_args *uap)
87106977Sdeischen{
88106977Sdeischen	ucontext_t uc;
89106977Sdeischen	int ret;
90106977Sdeischen
91106977Sdeischen	if (uap->ucp == NULL)
92106977Sdeischen		ret = EINVAL;
93106977Sdeischen	else {
94106977Sdeischen		ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
95106977Sdeischen		if (ret == 0) {
96106977Sdeischen			ret = set_mcontext(td, &uc.uc_mcontext);
97106977Sdeischen			if (ret == 0) {
98106977Sdeischen				SIG_CANTMASK(uc.uc_sigmask);
99106977Sdeischen				PROC_LOCK(td->td_proc);
100112888Sjeff				td->td_sigmask = uc.uc_sigmask;
101106977Sdeischen				PROC_UNLOCK(td->td_proc);
102106977Sdeischen			}
103106977Sdeischen		}
104106977Sdeischen	}
105106977Sdeischen	return (ret);
106106977Sdeischen}
107106977Sdeischen
108106977Sdeischenint
109106977Sdeischenswapcontext(struct thread *td, struct swapcontext_args *uap)
110106977Sdeischen{
111106977Sdeischen	ucontext_t uc;
112106977Sdeischen	int ret;
113106977Sdeischen
114106977Sdeischen	if (uap->oucp == NULL || uap->ucp == NULL)
115106977Sdeischen		ret = EINVAL;
116106977Sdeischen	else {
117106977Sdeischen		get_mcontext(td, &uc.uc_mcontext);
118112888Sjeff		uc.uc_sigmask = td->td_sigmask;
119106977Sdeischen		ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
120106977Sdeischen		if (ret == 0) {
121106977Sdeischen			ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
122106977Sdeischen			if (ret == 0) {
123106977Sdeischen				ret = set_mcontext(td, &uc.uc_mcontext);
124106977Sdeischen				if (ret == 0) {
125106977Sdeischen					SIG_CANTMASK(uc.uc_sigmask);
126106977Sdeischen					PROC_LOCK(td->td_proc);
127112888Sjeff					td->td_sigmask = uc.uc_sigmask;
128106977Sdeischen					PROC_UNLOCK(td->td_proc);
129106977Sdeischen				}
130106977Sdeischen			}
131106977Sdeischen		}
132106977Sdeischen	}
133106977Sdeischen	return (ret);
134106977Sdeischen}
135