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