xref: /illumos-gate/usr/src/uts/common/sys/callb.h (revision bb78539e556f92fce6eb2a077f042db6e89b7272)
1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef	_SYS_CALLB_H
27 #define	_SYS_CALLB_H
28 
29 #include <sys/t_lock.h>
30 #include <sys/thread.h>
31 #include <sys/taskq.h>
32 
33 #ifdef	__cplusplus
34 extern "C" {
35 #endif
36 
37 /*
38  * definitions of callback classes (c_class)
39  *
40  * Callbacks belong in the same class if (1) their callback routines
41  * do the same kind of processing (ideally, using the same callback function)
42  * and (2) they can/should be executed at the same time in a cpr
43  * suspend/resume operation.
44  *
45  * Note: The DAEMON class, in particular, is for stopping kernel threads
46  * and nothing else.  The CALLB_* macros below should be used to deal
47  * with kernel threads, and the callback function should be callb_generic_cpr.
48  * Another idiosyncrasy of the DAEMON class is that if a suspend operation
49  * fails, some of the callback functions may be called with the RESUME
50  * code which were never called with SUSPEND.  Not a problem currently,
51  * but see bug 4201851.
52  */
53 #define	CB_CL_CPR_DAEMON	0
54 #define	CB_CL_CPR_VM		1
55 #define	CB_CL_CPR_CALLOUT	2
56 #define	CB_CL_CPR_OBP		3
57 #define	CB_CL_CPR_FB		4
58 #define	CB_CL_PANIC		5
59 #define	CB_CL_CPR_RPC		6
60 #define	CB_CL_CPR_PROMPRINTF	7
61 #define	CB_CL_UADMIN		8
62 #define	CB_CL_CPR_PM		9
63 #define	CB_CL_HALT		10
64 #define	CB_CL_CPR_DMA		11
65 #define	CB_CL_CPR_POST_USER	12
66 #define	CB_CL_UADMIN_PRE_VFS    13
67 #define	CB_CL_MDBOOT		CB_CL_UADMIN
68 #define	CB_CL_ENTER_DEBUGGER	14
69 #define	CB_CL_CPR_POST_KERNEL	15
70 #define	CB_CL_CPU_DEEP_IDLE	16
71 #define	NCBCLASS		17 /* CHANGE ME if classes are added/removed */
72 
73 #define	CB_MAXNAME  TASKQ_NAMELEN
74 
75 /*
76  * CB_CL_CPR_DAEMON class specific definitions are given below:
77  */
78 
79 /*
80  * code for CPR callb_execute_class
81  */
82 #define	CB_CODE_CPR_CHKPT	0
83 #define	CB_CODE_CPR_RESUME	1
84 
85 typedef	void *		callb_id_t;
86 /*
87  * Per kernel thread structure for CPR daemon callbacks.
88  * Must be protected by either a existing lock in the daemon or
89  * a new lock created for such a purpose.
90  */
91 typedef struct callb_cpr {
92 	kmutex_t	*cc_lockp;	/* lock to protect this struct */
93 	char		cc_events;	/* various events for CPR */
94 	callb_id_t	cc_id;		/* callb id address */
95 	kcondvar_t	cc_callb_cv;	/* cv for callback waiting */
96 	kcondvar_t	cc_stop_cv;	/* cv to checkpoint block */
97 } callb_cpr_t;
98 
99 /*
100  * cc_events definitions
101  */
102 #define	CALLB_CPR_START		1	/* a checkpoint request's started */
103 #define	CALLB_CPR_SAFE		2	/* thread is safe for CPR */
104 #define	CALLB_CPR_ALWAYS_SAFE	4	/* thread is ALWAYS safe for CPR */
105 
106 /*
107  * Used when checking that all kernel threads are stopped.
108  */
109 #define	CALLB_MAX_RETRY		3	/* when waiting for kthread to sleep */
110 #define	CALLB_THREAD_DELAY	10	/* ticks allowed to reach sleep */
111 #define	CPR_KTHREAD_TIMEOUT_SEC	90	/* secs before callback times out -- */
112 					/* due to pwr mgmt of disks, make -- */
113 					/* big enough for worst spinup time */
114 
115 #ifdef  _KERNEL
116 /*
117  *
118  * CALLB_CPR_INIT macro is used by kernel threads to add their entry to
119  * the callback table and perform other initialization.  It automatically
120  * adds the thread as being in the callback class CB_CL_CPR_DAEMON.
121  *
122  *	cp    - ptr to the callb_cpr_t structure for this kernel thread
123  *
124  *	lockp - pointer to mutex protecting the callb_cpr_t stuct
125  *
126  *	func  - pointer to the callback function for this kernel thread.
127  *		It has the prototype boolean_t <func>(void *arg, int code)
128  *		where: arg	- ptr to the callb_cpr_t structure
129  *		       code	- not used for this type of callback
130  *		returns: B_TRUE if successful; B_FALSE if unsuccessful.
131  *
132  *	name  - a string giving the name of the kernel thread
133  *
134  * Note: lockp is the lock to protect the callb_cpr_t (cp) structure
135  * later on.  No lock held is needed for this initialization.
136  */
137 #define	CALLB_CPR_INIT(cp, lockp, func, name)	{			\
138 		bzero((caddr_t)(cp), sizeof (callb_cpr_t));		\
139 		(cp)->cc_lockp = lockp;					\
140 		(cp)->cc_id = callb_add(func, (void *)(cp),		\
141 			CB_CL_CPR_DAEMON, name);			\
142 	}
143 
144 #ifndef __lock_lint
145 #define	CALLB_CPR_ASSERT(cp)	ASSERT(MUTEX_HELD((cp)->cc_lockp));
146 #else
147 #define	CALLB_CPR_ASSERT(cp)
148 #endif
149 /*
150  * Some threads (like the idle threads) do not adhere to the callback
151  * protocol and are always considered safe.  Such threads must never exit.
152  * They register their presence by calling this macro during their
153  * initialization.
154  *
155  * Args:
156  *	t	- thread pointer of the client kernel thread
157  *	name	- a string giving the name of the kernel thread
158  */
159 #define	CALLB_CPR_INIT_SAFE(t, name) {					\
160 		(void) callb_add_thread(callb_generic_cpr_safe,		\
161 		(void *) &callb_cprinfo_safe, CB_CL_CPR_DAEMON,		\
162 		    name, t);						\
163 	}
164 /*
165  * The lock to protect cp's content must be held before
166  * calling the following two macros.
167  *
168  * Any code region between CALLB_CPR_SAFE_BEGIN and CALLB_CPR_SAFE_END
169  * is safe for checkpoint/resume.
170  */
171 #define	CALLB_CPR_SAFE_BEGIN(cp) {			\
172 		CALLB_CPR_ASSERT(cp)			\
173 		(cp)->cc_events |= CALLB_CPR_SAFE;	\
174 		if ((cp)->cc_events & CALLB_CPR_START)	\
175 			cv_signal(&(cp)->cc_callb_cv);	\
176 	}
177 #define	CALLB_CPR_SAFE_END(cp, lockp) {				\
178 		CALLB_CPR_ASSERT(cp)				\
179 		while ((cp)->cc_events & CALLB_CPR_START)	\
180 			cv_wait(&(cp)->cc_stop_cv, lockp);	\
181 		(cp)->cc_events &= ~CALLB_CPR_SAFE;		\
182 	}
183 /*
184  * cv_destroy is nop right now but may be needed in the future.
185  */
186 #define	CALLB_CPR_EXIT(cp) {				\
187 		CALLB_CPR_ASSERT(cp)			\
188 		(cp)->cc_events |= CALLB_CPR_SAFE;	\
189 		if ((cp)->cc_events & CALLB_CPR_START)	\
190 			cv_signal(&(cp)->cc_callb_cv);	\
191 		mutex_exit((cp)->cc_lockp);		\
192 		(void) callb_delete((cp)->cc_id);	\
193 		cv_destroy(&(cp)->cc_callb_cv);		\
194 		cv_destroy(&(cp)->cc_stop_cv);		\
195 	}
196 
197 extern callb_cpr_t callb_cprinfo_safe;
198 extern void	callb_init(void);
199 extern callb_id_t callb_add(boolean_t  (*)(void *, int), void *, int, char *);
200 extern callb_id_t callb_add_thread(boolean_t (*)(void *, int),
201     void *, int, char *, kthread_id_t);
202 extern int	callb_delete(callb_id_t);
203 extern void	callb_execute(callb_id_t, int);
204 extern void	*callb_execute_class(int, int);
205 extern boolean_t callb_generic_cpr(void *, int);
206 extern boolean_t callb_generic_cpr_safe(void *, int);
207 extern boolean_t callb_is_stopped(kthread_id_t, caddr_t *);
208 extern void	callb_lock_table(void);
209 extern void	callb_unlock_table(void);
210 #endif
211 
212 #ifdef	__cplusplus
213 }
214 #endif
215 
216 #endif	/* _SYS_CALLB_H */
217