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
27116182Sobrien#include <sys/cdefs.h>
28116182Sobrien__FBSDID("$FreeBSD$");
29116182Sobrien
30106977Sdeischen#include <sys/param.h>
31106977Sdeischen#include <sys/kernel.h>
32106977Sdeischen#include <sys/lock.h>
33106977Sdeischen#include <sys/mutex.h>
34106977Sdeischen#include <sys/proc.h>
35209613Sjhb#include <sys/syscallsubr.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/*
43167232Srwatson * The first two fields of a ucontext_t are the signal mask and the machine
44167232Srwatson * context.  The next field is uc_link; we want to avoid destroying the link
45167232Srwatson * when copying out contexts.
46106977Sdeischen */
47112962Sjake#define	UC_COPY_SIZE	offsetof(ucontext_t, uc_link)
48106977Sdeischen
49106977Sdeischen#ifndef _SYS_SYSPROTO_H_
50106977Sdeischenstruct getcontext_args {
51106977Sdeischen	struct __ucontext *ucp;
52106977Sdeischen}
53106977Sdeischenstruct setcontext_args {
54106977Sdeischen	const struct __ucontext_t *ucp;
55106977Sdeischen}
56106977Sdeischenstruct swapcontext_args {
57106977Sdeischen	struct __ucontext *oucp;
58106977Sdeischen	const struct __ucontext_t *ucp;
59106977Sdeischen}
60106977Sdeischen#endif
61106977Sdeischen
62106977Sdeischenint
63225617Skmacysys_getcontext(struct thread *td, struct getcontext_args *uap)
64106977Sdeischen{
65106977Sdeischen	ucontext_t uc;
66113626Sjhb	int ret;
67106977Sdeischen
68106977Sdeischen	if (uap->ucp == NULL)
69106977Sdeischen		ret = EINVAL;
70106977Sdeischen	else {
71122364Smarcel		get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
72113626Sjhb		PROC_LOCK(td->td_proc);
73112888Sjeff		uc.uc_sigmask = td->td_sigmask;
74113626Sjhb		PROC_UNLOCK(td->td_proc);
75218327Skib		bzero(uc.__spare__, sizeof(uc.__spare__));
76106977Sdeischen		ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
77106977Sdeischen	}
78106977Sdeischen	return (ret);
79106977Sdeischen}
80106977Sdeischen
81106977Sdeischenint
82225617Skmacysys_setcontext(struct thread *td, struct setcontext_args *uap)
83106977Sdeischen{
84106977Sdeischen	ucontext_t uc;
85106977Sdeischen	int ret;
86106977Sdeischen
87106977Sdeischen	if (uap->ucp == NULL)
88106977Sdeischen		ret = EINVAL;
89106977Sdeischen	else {
90106977Sdeischen		ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
91106977Sdeischen		if (ret == 0) {
92106977Sdeischen			ret = set_mcontext(td, &uc.uc_mcontext);
93106977Sdeischen			if (ret == 0) {
94198507Skib				kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask,
95198507Skib				    NULL, 0);
96106977Sdeischen			}
97106977Sdeischen		}
98106977Sdeischen	}
99112962Sjake	return (ret == 0 ? EJUSTRETURN : ret);
100106977Sdeischen}
101106977Sdeischen
102106977Sdeischenint
103225617Skmacysys_swapcontext(struct thread *td, struct swapcontext_args *uap)
104106977Sdeischen{
105106977Sdeischen	ucontext_t uc;
106106977Sdeischen	int ret;
107106977Sdeischen
108106977Sdeischen	if (uap->oucp == NULL || uap->ucp == NULL)
109106977Sdeischen		ret = EINVAL;
110106977Sdeischen	else {
111122364Smarcel		get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
112218327Skib		bzero(uc.__spare__, sizeof(uc.__spare__));
113113626Sjhb		PROC_LOCK(td->td_proc);
114112888Sjeff		uc.uc_sigmask = td->td_sigmask;
115113626Sjhb		PROC_UNLOCK(td->td_proc);
116106977Sdeischen		ret = copyout(&uc, uap->oucp, UC_COPY_SIZE);
117106977Sdeischen		if (ret == 0) {
118106977Sdeischen			ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
119106977Sdeischen			if (ret == 0) {
120106977Sdeischen				ret = set_mcontext(td, &uc.uc_mcontext);
121106977Sdeischen				if (ret == 0) {
122198507Skib					kern_sigprocmask(td, SIG_SETMASK,
123198507Skib					    &uc.uc_sigmask, NULL, 0);
124106977Sdeischen				}
125106977Sdeischen			}
126106977Sdeischen		}
127106977Sdeischen	}
128112962Sjake	return (ret == 0 ? EJUSTRETURN : ret);
129106977Sdeischen}
130