4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/param.h>
28 #include <sys/types.h>
29 #include <sys/bitmap.h>
30 #include <sys/sysmacros.h>
31 #include <sys/systm.h>
33 #include <sys/errno.h>
35 #include <sys/fault.h>
36 #include <sys/procset.h>
37 #include <sys/signal.h>
38 #include <sys/siginfo.h>
41 #include <sys/schedctl.h>
42 #include <sys/debug.h>
43 #include <sys/condvar_impl.h>
44 #include <sys/model.h>
49 copyout_siginfo(model_t datamodel
, k_siginfo_t
*ksip
, void *uaddr
)
51 zoneid_t zoneid
= getzoneid();
53 if (datamodel
== DATAMODEL_NATIVE
) {
54 if (SI_FROMUSER(ksip
) && zoneid
!= GLOBAL_ZONEID
&&
55 zoneid
!= ksip
->si_zoneid
) {
56 k_siginfo_t sani_sip
= *ksip
;
57 sani_sip
.si_pid
= curproc
->p_zone
->zone_zsched
->p_pid
;
59 sani_sip
.si_ctid
= -1;
60 sani_sip
.si_zoneid
= zoneid
;
61 if (copyout(&sani_sip
, uaddr
, sizeof (sani_sip
)))
62 return (set_errno(EFAULT
));
64 if (copyout(ksip
, uaddr
, sizeof (*ksip
)))
65 return (set_errno(EFAULT
));
68 #ifdef _SYSCALL32_IMPL
72 siginfo_kto32(ksip
, &si32
);
73 if (SI_FROMUSER(ksip
) && zoneid
!= GLOBAL_ZONEID
&&
74 zoneid
!= ksip
->si_zoneid
) {
75 si32
.si_pid
= curproc
->p_zone
->zone_zsched
->p_pid
;
78 si32
.si_zoneid
= zoneid
;
80 if (copyout(&si32
, uaddr
, sizeof (si32
)))
81 return (set_errno(EFAULT
));
84 return (ksip
->si_signo
);
88 * Wait until a signal within a specified set is posted or until the
89 * time interval 'timeout' if specified. The signal is caught but
90 * not delivered. The value of the signal is returned to the caller.
93 sigtimedwait(sigset_t
*setp
, siginfo_t
*siginfop
, timespec_t
*timeoutp
)
97 kthread_t
*t
= curthread
;
98 klwp_t
*lwp
= ttolwp(t
);
99 proc_t
*p
= ttoproc(t
);
100 timespec_t sig_timeout
;
101 timespec_t
*rqtp
= NULL
;
105 k_siginfo_t info
, *infop
;
106 model_t datamodel
= get_udatamodel();
111 timecheck
= timechanged
;
113 if (datamodel
== DATAMODEL_NATIVE
) {
114 if (copyin(timeoutp
, &sig_timeout
,
115 sizeof (sig_timeout
)))
116 return (set_errno(EFAULT
));
118 timespec32_t timeout32
;
120 if (copyin(timeoutp
, &timeout32
, sizeof (timeout32
)))
121 return (set_errno(EFAULT
));
122 TIMESPEC32_TO_TIMESPEC(&sig_timeout
, &timeout32
)
125 if (itimerspecfix(&sig_timeout
))
126 return (set_errno(EINVAL
));
128 * Convert the timespec value into absolute time.
130 timespecadd(&sig_timeout
, &now
);
133 if (copyin(setp
, &set
, sizeof (set
)))
134 return (set_errno(EFAULT
));
135 sigutok(&set
, &t
->t_sigwait
);
136 if (sigisempty(&t
->t_sigwait
))
137 return (set_errno(EINVAL
));
139 mutex_enter(&p
->p_lock
);
141 * set the thread's signal mask to unmask
142 * those signals in the specified set.
144 schedctl_finish_sigblock(t
);
146 sigdiffset(&t
->t_hold
, &t
->t_sigwait
);
149 * Wait until we take a signal or until
150 * the absolute future time is passed.
152 while ((ret
= cv_waituntil_sig(&t
->t_delay_cv
, &p
->p_lock
,
153 rqtp
, timecheck
)) > 0)
159 * Restore thread's signal mask to its previous value.
162 t
->t_sig_check
= 1; /* so post_syscall sees new t_hold mask */
165 mutex_exit(&p
->p_lock
);
166 sigemptyset(&t
->t_sigwait
);
167 return (set_errno(error
)); /* timer expired */
170 * Don't bother with signal if it is not in request set.
172 if (lwp
->lwp_cursig
== 0 ||
173 !sigismember(&t
->t_sigwait
, lwp
->lwp_cursig
)) {
174 mutex_exit(&p
->p_lock
);
176 * lwp_cursig is zero if pokelwps() awakened cv_wait_sig().
177 * This happens if some other thread in this process called
178 * forkall() or exit().
180 sigemptyset(&t
->t_sigwait
);
181 return (set_errno(EINTR
));
184 if (lwp
->lwp_curinfo
)
185 infop
= &lwp
->lwp_curinfo
->sq_info
;
188 bzero(infop
, sizeof (info
));
189 infop
->si_signo
= lwp
->lwp_cursig
;
190 infop
->si_code
= SI_NOINFO
;
193 lwp
->lwp_ru
.nsignals
++;
194 ret
= lwp
->lwp_cursig
;
195 DTRACE_PROC2(signal__clear
, int, ret
, ksiginfo_t
*, infop
);
198 mutex_exit(&p
->p_lock
);
201 ret
= copyout_siginfo(datamodel
, infop
, siginfop
);
202 if (lwp
->lwp_curinfo
) {
203 siginfofree(lwp
->lwp_curinfo
);
204 lwp
->lwp_curinfo
= NULL
;
206 sigemptyset(&t
->t_sigwait
);