Merge commit '05e627dc484199c2d1bcdec2c07e471897d93354'
[unleashed/lotheac.git] / kernel / cpr / cpr_uthread.c
blob4deaa04bfa61d1ace3f9ac3944c146436b5dcaf8
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <sys/types.h>
29 #include <sys/thread.h>
30 #include <sys/conf.h>
31 #include <sys/cpuvar.h>
32 #include <sys/cpr.h>
33 #include <sys/user.h>
34 #include <sys/cmn_err.h>
35 #include <sys/callb.h>
37 extern void utstop_init(void);
38 extern void add_one_utstop(void);
39 extern void utstop_timedwait(long ticks);
41 static void cpr_stop_user(int);
42 static int cpr_check_user_threads(void);
45 * CPR user thread related support routines
47 void
48 cpr_signal_user(int sig)
51 * The signal SIGTHAW and SIGFREEZE cannot be sent to every thread yet
52 * since openwin is catching every signal and default action is to exit.
53 * We also need to implement the true SIGFREEZE and SIGTHAW to stop threads.
55 struct proc *p;
57 mutex_enter(&pidlock);
59 for (p = practive; p; p = p->p_next) {
60 /* only user threads */
61 if (p->p_exec == NULL || p->p_stat == SZOMB ||
62 p == proc_init || p == ttoproc(curthread))
63 continue;
65 mutex_enter(&p->p_lock);
66 sigtoproc(p, NULL, sig);
67 mutex_exit(&p->p_lock);
69 mutex_exit(&pidlock);
71 DELAY(MICROSEC);
74 /* max wait time for user thread stop */
75 #define CPR_UTSTOP_WAIT hz
76 #define CPR_UTSTOP_RETRY 4
77 static int count;
79 int
80 cpr_stop_user_threads()
82 utstop_init();
84 count = 0;
85 do {
86 if (++count > CPR_UTSTOP_RETRY)
87 return (ESRCH);
88 cpr_stop_user(count * count * CPR_UTSTOP_WAIT);
89 } while (cpr_check_user_threads());
91 return (0);
95 * This routine tries to stop all user threads before we get rid of all
96 * its pages.It goes through allthreads list and set the TP_CHKPT flag
97 * for all user threads and make them runnable. If all of the threads
98 * can be stopped within the max wait time, CPR will proceed. Otherwise
99 * CPR is aborted after a few of similiar retries.
101 static void
102 cpr_stop_user(int wait)
104 kthread_id_t tp;
105 proc_t *p;
107 /* The whole loop below needs to be atomic */
108 mutex_enter(&pidlock);
110 /* faster this way */
111 tp = curthread->t_next;
112 do {
113 /* kernel threads will be handled later */
114 p = ttoproc(tp);
115 if (p->p_as == &kas || p->p_stat == SZOMB)
116 continue;
119 * If the thread is stopped (by CPR) already, do nothing;
120 * if running, mark TP_CHKPT;
121 * if sleeping normally, mark TP_CHKPT and setrun;
122 * if sleeping non-interruptable, mark TP_CHKPT only for now;
123 * if sleeping with t_wchan0 != 0 etc, virtually stopped,
124 * do nothing.
127 /* p_lock is needed for modifying t_proc_flag */
128 mutex_enter(&p->p_lock);
129 thread_lock(tp); /* needed to check CPR_ISTOPPED */
131 if (tp->t_state == TS_STOPPED) {
133 * if already stopped by other reasons, add this new
134 * reason to it.
136 if (tp->t_schedflag & TS_RESUME)
137 tp->t_schedflag &= ~TS_RESUME;
138 } else {
140 tp->t_proc_flag |= TP_CHKPT;
142 thread_unlock(tp);
143 mutex_exit(&p->p_lock);
144 add_one_utstop();
145 mutex_enter(&p->p_lock);
146 thread_lock(tp);
148 aston(tp);
150 if (ISWAKEABLE(tp) || ISWAITING(tp)) {
151 setrun_locked(tp);
155 * force the thread into the kernel if it is not already there.
157 if (tp->t_state == TS_ONPROC && tp->t_cpu != CPU)
158 poke_cpu(tp->t_cpu->cpu_id);
159 thread_unlock(tp);
160 mutex_exit(&p->p_lock);
162 } while ((tp = tp->t_next) != curthread);
163 mutex_exit(&pidlock);
165 utstop_timedwait(wait);
169 * Checks and makes sure all user threads are stopped
171 static int
172 cpr_check_user_threads()
174 kthread_id_t tp;
175 int rc = 0;
177 mutex_enter(&pidlock);
178 tp = curthread->t_next;
179 do {
180 if (ttoproc(tp)->p_as == &kas || ttoproc(tp)->p_stat == SZOMB)
181 continue;
183 thread_lock(tp);
185 * make sure that we are off all the queues and in a stopped
186 * state.
188 if (!CPR_ISTOPPED(tp)) {
189 thread_unlock(tp);
190 mutex_exit(&pidlock);
192 if (count == CPR_UTSTOP_RETRY) {
193 CPR_DEBUG(CPR_DEBUG1, "Suspend failed: "
194 "cannot stop uthread\n");
195 cpr_err(CE_WARN, "Suspend cannot stop "
196 "process %s (%p:%x).",
197 ttoproc(tp)->p_user.u_psargs, (void *)tp,
198 tp->t_state);
199 cpr_err(CE_WARN, "Process may be waiting for"
200 " network request, please try again.");
203 CPR_DEBUG(CPR_DEBUG2, "cant stop t=%p state=%x pfg=%x "
204 "sched=%x\n", (void *)tp, tp->t_state,
205 tp->t_proc_flag, tp->t_schedflag);
206 CPR_DEBUG(CPR_DEBUG2, "proc %p state=%x pid=%d\n",
207 (void *)ttoproc(tp), ttoproc(tp)->p_stat,
208 ttoproc(tp)->p_pidp->pid_id);
209 return (1);
211 thread_unlock(tp);
213 } while ((tp = tp->t_next) != curthread && rc == 0);
215 mutex_exit(&pidlock);
216 return (0);
221 * start all threads that were stopped for checkpoint.
223 void
224 cpr_start_user_threads()
226 kthread_id_t tp;
227 proc_t *p;
229 mutex_enter(&pidlock);
230 tp = curthread->t_next;
231 do {
232 p = ttoproc(tp);
234 * kernel threads are callback'ed rather than setrun.
236 if (ttoproc(tp)->p_as == &kas) continue;
238 * t_proc_flag should have been cleared. Just to make sure here
240 mutex_enter(&p->p_lock);
241 tp->t_proc_flag &= ~TP_CHKPT;
242 mutex_exit(&p->p_lock);
244 thread_lock(tp);
245 if (CPR_ISTOPPED(tp)) {
248 * put it back on the runq
250 tp->t_schedflag |= TS_RESUME;
251 setrun_locked(tp);
253 thread_unlock(tp);
255 * DEBUG - Keep track of current and next thread pointer.
257 } while ((tp = tp->t_next) != curthread);
259 mutex_exit(&pidlock);
264 * re/start kernel threads
266 void
267 cpr_start_kernel_threads(void)
269 CPR_DEBUG(CPR_DEBUG1, "starting kernel daemons...");
270 (void) callb_execute_class(CB_CL_CPR_DAEMON, CB_CODE_CPR_RESUME);
271 CPR_DEBUG(CPR_DEBUG1, "done\n");
273 /* see table lock below */
274 callb_unlock_table();
279 * Stop kernel threads by using the callback mechanism. If any thread
280 * cannot be stopped, return failure.
283 cpr_stop_kernel_threads(void)
285 caddr_t name;
287 callb_lock_table(); /* Note: we unlock the table in resume. */
289 CPR_DEBUG(CPR_DEBUG1, "stopping kernel daemons...");
290 if ((name = callb_execute_class(CB_CL_CPR_DAEMON,
291 CB_CODE_CPR_CHKPT)) != NULL) {
292 cpr_err(CE_WARN,
293 "Could not stop \"%s\" kernel thread. "
294 "Please try again later.", name);
295 return (EBUSY);
298 CPR_DEBUG(CPR_DEBUG1, ("done\n"));
299 return (0);
303 * Check to see that kernel threads are stopped.
304 * This should be called while CPU's are paused, and the caller is
305 * effectively running single user, or else we are virtually guaranteed
306 * to fail. The routine should not ASSERT on the paused state or spl
307 * level, as there may be a use for this to verify that things are running
308 * again.
311 cpr_threads_are_stopped(void)
313 caddr_t name;
314 kthread_id_t tp;
315 proc_t *p;
318 * We think we stopped all the kernel threads. Just in case
319 * someone is not playing by the rules, take a spin through
320 * the threadlist and see if we can account for everybody.
322 mutex_enter(&pidlock);
323 tp = curthread->t_next;
324 do {
325 p = ttoproc(tp);
326 if (p->p_as != &kas)
327 continue;
329 if (tp->t_flag & T_INTR_THREAD)
330 continue;
332 if (! callb_is_stopped(tp, &name)) {
333 mutex_exit(&pidlock);
334 cpr_err(CE_WARN,
335 "\"%s\" kernel thread not stopped.", name);
336 return (EBUSY);
338 } while ((tp = tp->t_next) != curthread);
340 mutex_exit(&pidlock);
341 return (0);