4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
30 #pragma ident "@(#)callb.h 1.29 05/06/23 SMI"
32 #include <sys/kcondvar.h>
39 * definitions of callback classes (c_class)
41 * Callbacks belong in the same class if (1) their callback routines
42 * do the same kind of processing (ideally, using the same callback function)
43 * and (2) they can/should be executed at the same time in a cpr
44 * suspend/resume operation.
46 * Note: The DAEMON class, in particular, is for stopping kernel threads
47 * and nothing else. The CALLB_* macros below should be used to deal
48 * with kernel threads, and the callback function should be callb_generic_cpr.
49 * Another idiosyncrasy of the DAEMON class is that if a suspend operation
50 * fails, some of the callback functions may be called with the RESUME
51 * code which were never called with SUSPEND. Not a problem currently,
52 * but see bug 4201851.
54 #define CB_CL_CPR_DAEMON 0
55 #define CB_CL_CPR_VM 1
56 #define CB_CL_CPR_CALLOUT 2
57 #define CB_CL_CPR_OBP 3
58 #define CB_CL_CPR_FB 4
60 #define CB_CL_CPR_RPC 6
61 #define CB_CL_CPR_PROMPRINTF 7
62 #define CB_CL_UADMIN 8
63 #define CB_CL_CPR_PM 9
65 #define CB_CL_CPR_DMA 11
66 #define CB_CL_CPR_POST_USER 12
67 #define CB_CL_UADMIN_PRE_VFS 13
68 #define CB_CL_MDBOOT CB_CL_UADMIN
69 #define CB_CL_ENTER_DEBUGGER 14
70 #define CB_CL_CPR_POST_KERNEL 15
71 #define NCBCLASS 16 /* CHANGE ME if classes are added/removed */
74 * CB_CL_CPR_DAEMON class specific definitions are given below:
78 * code for CPR callb_execute_class
80 #define CB_CODE_CPR_CHKPT 0
81 #define CB_CODE_CPR_RESUME 1
83 typedef void * callb_id_t;
85 * Per kernel thread structure for CPR daemon callbacks.
86 * Must be protected by either a existing lock in the daemon or
87 * a new lock created for such a purpose.
89 typedef struct callb_cpr {
90 kmutex_t *cc_lockp; /* lock to protect this struct */
91 char cc_events; /* various events for CPR */
92 callb_id_t cc_id; /* callb id address */
93 kcondvar_t cc_callb_cv; /* cv for callback waiting */
94 kcondvar_t cc_stop_cv; /* cv to checkpoint block */
98 * cc_events definitions
100 #define CALLB_CPR_START 1 /* a checkpoint request's started */
101 #define CALLB_CPR_SAFE 2 /* thread is safe for CPR */
102 #define CALLB_CPR_ALWAYS_SAFE 4 /* thread is ALWAYS safe for CPR */
105 * Used when checking that all kernel threads are stopped.
107 #define CALLB_MAX_RETRY 3 /* when waiting for kthread to sleep */
108 #define CALLB_THREAD_DELAY 10 /* ticks allowed to reach sleep */
109 #define CPR_KTHREAD_TIMEOUT_SEC 90 /* secs before callback times out -- */
110 /* due to pwr mgmt of disks, make -- */
111 /* big enough for worst spinup time */
116 * CALLB_CPR_INIT macro is used by kernel threads to add their entry to
117 * the callback table and perform other initialization. It automatically
118 * adds the thread as being in the callback class CB_CL_CPR_DAEMON.
120 * cp - ptr to the callb_cpr_t structure for this kernel thread
122 * lockp - pointer to mutex protecting the callb_cpr_t stuct
124 * func - pointer to the callback function for this kernel thread.
125 * It has the prototype boolean_t <func>(void *arg, int code)
126 * where: arg - ptr to the callb_cpr_t structure
127 * code - not used for this type of callback
128 * returns: B_TRUE if successful; B_FALSE if unsuccessful.
130 * name - a string giving the name of the kernel thread
132 * Note: lockp is the lock to protect the callb_cpr_t (cp) structure
133 * later on. No lock held is needed for this initialization.
135 #define CALLB_CPR_INIT(cp, lockp, func, name) { \
136 strlcpy(curthread->td_name, (name), \
137 sizeof(curthread->td_name)); \
138 strlcpy(curthread->td_proc->p_comm, (name), \
139 sizeof(curthread->td_proc->p_comm)); \
140 bzero((caddr_t)(cp), sizeof (callb_cpr_t)); \
141 (cp)->cc_lockp = lockp; \
142 (cp)->cc_id = callb_add(func, (void *)(cp), \
143 CB_CL_CPR_DAEMON, name); \
144 cv_init(&(cp)->cc_callb_cv, NULL, CV_DEFAULT, NULL); \
145 cv_init(&(cp)->cc_stop_cv, NULL, CV_DEFAULT, NULL); \
149 #define CALLB_CPR_ASSERT(cp) ASSERT(MUTEX_HELD((cp)->cc_lockp));
151 #define CALLB_CPR_ASSERT(cp)
154 * Some threads (like the idle threads) do not adhere to the callback
155 * protocol and are always considered safe. Such threads must never exit.
156 * They register their presence by calling this macro during their
160 * t - thread pointer of the client kernel thread
161 * name - a string giving the name of the kernel thread
163 #define CALLB_CPR_INIT_SAFE(t, name) { \
164 (void) callb_add_thread(callb_generic_cpr_safe, \
165 (void *) &callb_cprinfo_safe, CB_CL_CPR_DAEMON, \
169 * The lock to protect cp's content must be held before
170 * calling the following two macros.
172 * Any code region between CALLB_CPR_SAFE_BEGIN and CALLB_CPR_SAFE_END
173 * is safe for checkpoint/resume.
175 #define CALLB_CPR_SAFE_BEGIN(cp) { \
176 CALLB_CPR_ASSERT(cp) \
177 (cp)->cc_events |= CALLB_CPR_SAFE; \
178 if ((cp)->cc_events & CALLB_CPR_START) \
179 cv_signal(&(cp)->cc_callb_cv); \
181 #define CALLB_CPR_SAFE_END(cp, lockp) { \
182 CALLB_CPR_ASSERT(cp) \
183 while ((cp)->cc_events & CALLB_CPR_START) \
184 cv_wait(&(cp)->cc_stop_cv, lockp); \
185 (cp)->cc_events &= ~CALLB_CPR_SAFE; \
188 * cv_destroy is nop right now but may be needed in the future.
190 #define CALLB_CPR_EXIT(cp) { \
191 CALLB_CPR_ASSERT(cp) \
192 (cp)->cc_events |= CALLB_CPR_SAFE; \
193 if ((cp)->cc_events & CALLB_CPR_START) \
194 cv_signal(&(cp)->cc_callb_cv); \
195 mutex_exit((cp)->cc_lockp); \
196 (void) callb_delete((cp)->cc_id); \
197 cv_destroy(&(cp)->cc_callb_cv); \
198 cv_destroy(&(cp)->cc_stop_cv); \
201 extern callb_cpr_t callb_cprinfo_safe;
202 extern callb_id_t callb_add(boolean_t (*)(void *, int), void *, int, char *);
203 extern callb_id_t callb_add_thread(boolean_t (*)(void *, int),
204 void *, int, char *, kthread_id_t);
205 extern int callb_delete(callb_id_t);
206 extern void callb_execute(callb_id_t, int);
207 extern void *callb_execute_class(int, int);
208 extern boolean_t callb_generic_cpr(void *, int);
209 extern boolean_t callb_generic_cpr_safe(void *, int);
210 extern boolean_t callb_is_stopped(kthread_id_t, caddr_t *);
211 extern void callb_lock_table(void);
212 extern void callb_unlock_table(void);
219 #endif /* _SYS_CALLB_H */