xref: /illumos-gate/usr/src/uts/common/sys/callb.h (revision bb78539e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50e751525SEric Saxe  * Common Development and Distribution License (the "License").
60e751525SEric Saxe  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
220e751525SEric Saxe  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #ifndef	_SYS_CALLB_H
277c478bd9Sstevel@tonic-gate #define	_SYS_CALLB_H
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
307c478bd9Sstevel@tonic-gate #include <sys/thread.h>
31*bb78539eSNolan Heimlich #include <sys/taskq.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
347c478bd9Sstevel@tonic-gate extern "C" {
357c478bd9Sstevel@tonic-gate #endif
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate  * definitions of callback classes (c_class)
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  * Callbacks belong in the same class if (1) their callback routines
417c478bd9Sstevel@tonic-gate  * do the same kind of processing (ideally, using the same callback function)
427c478bd9Sstevel@tonic-gate  * and (2) they can/should be executed at the same time in a cpr
437c478bd9Sstevel@tonic-gate  * suspend/resume operation.
447c478bd9Sstevel@tonic-gate  *
457c478bd9Sstevel@tonic-gate  * Note: The DAEMON class, in particular, is for stopping kernel threads
467c478bd9Sstevel@tonic-gate  * and nothing else.  The CALLB_* macros below should be used to deal
477c478bd9Sstevel@tonic-gate  * with kernel threads, and the callback function should be callb_generic_cpr.
487c478bd9Sstevel@tonic-gate  * Another idiosyncrasy of the DAEMON class is that if a suspend operation
497c478bd9Sstevel@tonic-gate  * fails, some of the callback functions may be called with the RESUME
507c478bd9Sstevel@tonic-gate  * code which were never called with SUSPEND.  Not a problem currently,
517c478bd9Sstevel@tonic-gate  * but see bug 4201851.
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_DAEMON	0
547c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_VM		1
557c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_CALLOUT	2
567c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_OBP		3
577c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_FB		4
587c478bd9Sstevel@tonic-gate #define	CB_CL_PANIC		5
597c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_RPC		6
607c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_PROMPRINTF	7
617c478bd9Sstevel@tonic-gate #define	CB_CL_UADMIN		8
627c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_PM		9
637c478bd9Sstevel@tonic-gate #define	CB_CL_HALT		10
647c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_DMA		11
657c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_POST_USER	12
667c478bd9Sstevel@tonic-gate #define	CB_CL_UADMIN_PRE_VFS    13
67edc40228Sachartre #define	CB_CL_MDBOOT		CB_CL_UADMIN
687c478bd9Sstevel@tonic-gate #define	CB_CL_ENTER_DEBUGGER	14
697c478bd9Sstevel@tonic-gate #define	CB_CL_CPR_POST_KERNEL	15
700e751525SEric Saxe #define	CB_CL_CPU_DEEP_IDLE	16
710e751525SEric Saxe #define	NCBCLASS		17 /* CHANGE ME if classes are added/removed */
727c478bd9Sstevel@tonic-gate 
73*bb78539eSNolan Heimlich #define	CB_MAXNAME  TASKQ_NAMELEN
74*bb78539eSNolan Heimlich 
757c478bd9Sstevel@tonic-gate /*
767c478bd9Sstevel@tonic-gate  * CB_CL_CPR_DAEMON class specific definitions are given below:
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate  * code for CPR callb_execute_class
817c478bd9Sstevel@tonic-gate  */
827c478bd9Sstevel@tonic-gate #define	CB_CODE_CPR_CHKPT	0
837c478bd9Sstevel@tonic-gate #define	CB_CODE_CPR_RESUME	1
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate typedef	void *		callb_id_t;
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * Per kernel thread structure for CPR daemon callbacks.
887c478bd9Sstevel@tonic-gate  * Must be protected by either a existing lock in the daemon or
897c478bd9Sstevel@tonic-gate  * a new lock created for such a purpose.
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate typedef struct callb_cpr {
927c478bd9Sstevel@tonic-gate 	kmutex_t	*cc_lockp;	/* lock to protect this struct */
937c478bd9Sstevel@tonic-gate 	char		cc_events;	/* various events for CPR */
947c478bd9Sstevel@tonic-gate 	callb_id_t	cc_id;		/* callb id address */
957c478bd9Sstevel@tonic-gate 	kcondvar_t	cc_callb_cv;	/* cv for callback waiting */
967c478bd9Sstevel@tonic-gate 	kcondvar_t	cc_stop_cv;	/* cv to checkpoint block */
977c478bd9Sstevel@tonic-gate } callb_cpr_t;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate  * cc_events definitions
1017c478bd9Sstevel@tonic-gate  */
1027c478bd9Sstevel@tonic-gate #define	CALLB_CPR_START		1	/* a checkpoint request's started */
1037c478bd9Sstevel@tonic-gate #define	CALLB_CPR_SAFE		2	/* thread is safe for CPR */
1047c478bd9Sstevel@tonic-gate #define	CALLB_CPR_ALWAYS_SAFE	4	/* thread is ALWAYS safe for CPR */
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate /*
1077c478bd9Sstevel@tonic-gate  * Used when checking that all kernel threads are stopped.
1087c478bd9Sstevel@tonic-gate  */
1097c478bd9Sstevel@tonic-gate #define	CALLB_MAX_RETRY		3	/* when waiting for kthread to sleep */
1107c478bd9Sstevel@tonic-gate #define	CALLB_THREAD_DELAY	10	/* ticks allowed to reach sleep */
1117c478bd9Sstevel@tonic-gate #define	CPR_KTHREAD_TIMEOUT_SEC	90	/* secs before callback times out -- */
1127c478bd9Sstevel@tonic-gate 					/* due to pwr mgmt of disks, make -- */
1137c478bd9Sstevel@tonic-gate 					/* big enough for worst spinup time */
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate #ifdef  _KERNEL
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate  *
1187c478bd9Sstevel@tonic-gate  * CALLB_CPR_INIT macro is used by kernel threads to add their entry to
1197c478bd9Sstevel@tonic-gate  * the callback table and perform other initialization.  It automatically
1207c478bd9Sstevel@tonic-gate  * adds the thread as being in the callback class CB_CL_CPR_DAEMON.
1217c478bd9Sstevel@tonic-gate  *
1227c478bd9Sstevel@tonic-gate  *	cp    - ptr to the callb_cpr_t structure for this kernel thread
1237c478bd9Sstevel@tonic-gate  *
1247c478bd9Sstevel@tonic-gate  *	lockp - pointer to mutex protecting the callb_cpr_t stuct
1257c478bd9Sstevel@tonic-gate  *
1267c478bd9Sstevel@tonic-gate  *	func  - pointer to the callback function for this kernel thread.
1277c478bd9Sstevel@tonic-gate  *		It has the prototype boolean_t <func>(void *arg, int code)
1287c478bd9Sstevel@tonic-gate  *		where: arg	- ptr to the callb_cpr_t structure
1297c478bd9Sstevel@tonic-gate  *		       code	- not used for this type of callback
1307c478bd9Sstevel@tonic-gate  *		returns: B_TRUE if successful; B_FALSE if unsuccessful.
1317c478bd9Sstevel@tonic-gate  *
1327c478bd9Sstevel@tonic-gate  *	name  - a string giving the name of the kernel thread
1337c478bd9Sstevel@tonic-gate  *
1347c478bd9Sstevel@tonic-gate  * Note: lockp is the lock to protect the callb_cpr_t (cp) structure
1357c478bd9Sstevel@tonic-gate  * later on.  No lock held is needed for this initialization.
1367c478bd9Sstevel@tonic-gate  */
1377c478bd9Sstevel@tonic-gate #define	CALLB_CPR_INIT(cp, lockp, func, name)	{			\
1387c478bd9Sstevel@tonic-gate 		bzero((caddr_t)(cp), sizeof (callb_cpr_t));		\
1397c478bd9Sstevel@tonic-gate 		(cp)->cc_lockp = lockp;					\
1407c478bd9Sstevel@tonic-gate 		(cp)->cc_id = callb_add(func, (void *)(cp),		\
1417c478bd9Sstevel@tonic-gate 			CB_CL_CPR_DAEMON, name);			\
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate #ifndef __lock_lint
1457c478bd9Sstevel@tonic-gate #define	CALLB_CPR_ASSERT(cp)	ASSERT(MUTEX_HELD((cp)->cc_lockp));
1467c478bd9Sstevel@tonic-gate #else
1477c478bd9Sstevel@tonic-gate #define	CALLB_CPR_ASSERT(cp)
1487c478bd9Sstevel@tonic-gate #endif
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate  * Some threads (like the idle threads) do not adhere to the callback
1517c478bd9Sstevel@tonic-gate  * protocol and are always considered safe.  Such threads must never exit.
1527c478bd9Sstevel@tonic-gate  * They register their presence by calling this macro during their
1537c478bd9Sstevel@tonic-gate  * initialization.
1547c478bd9Sstevel@tonic-gate  *
1557c478bd9Sstevel@tonic-gate  * Args:
1567c478bd9Sstevel@tonic-gate  *	t	- thread pointer of the client kernel thread
1577c478bd9Sstevel@tonic-gate  *	name	- a string giving the name of the kernel thread
1587c478bd9Sstevel@tonic-gate  */
1597c478bd9Sstevel@tonic-gate #define	CALLB_CPR_INIT_SAFE(t, name) {					\
1607c478bd9Sstevel@tonic-gate 		(void) callb_add_thread(callb_generic_cpr_safe,		\
1617c478bd9Sstevel@tonic-gate 		(void *) &callb_cprinfo_safe, CB_CL_CPR_DAEMON,		\
1627c478bd9Sstevel@tonic-gate 		    name, t);						\
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate  * The lock to protect cp's content must be held before
1667c478bd9Sstevel@tonic-gate  * calling the following two macros.
1677c478bd9Sstevel@tonic-gate  *
1687c478bd9Sstevel@tonic-gate  * Any code region between CALLB_CPR_SAFE_BEGIN and CALLB_CPR_SAFE_END
1697c478bd9Sstevel@tonic-gate  * is safe for checkpoint/resume.
1707c478bd9Sstevel@tonic-gate  */
171*bb78539eSNolan Heimlich #define	CALLB_CPR_SAFE_BEGIN(cp) {			\
1727c478bd9Sstevel@tonic-gate 		CALLB_CPR_ASSERT(cp)			\
1737c478bd9Sstevel@tonic-gate 		(cp)->cc_events |= CALLB_CPR_SAFE;	\
1747c478bd9Sstevel@tonic-gate 		if ((cp)->cc_events & CALLB_CPR_START)	\
1757c478bd9Sstevel@tonic-gate 			cv_signal(&(cp)->cc_callb_cv);	\
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate #define	CALLB_CPR_SAFE_END(cp, lockp) {				\
1787c478bd9Sstevel@tonic-gate 		CALLB_CPR_ASSERT(cp)				\
1797c478bd9Sstevel@tonic-gate 		while ((cp)->cc_events & CALLB_CPR_START)	\
1807c478bd9Sstevel@tonic-gate 			cv_wait(&(cp)->cc_stop_cv, lockp);	\
1817c478bd9Sstevel@tonic-gate 		(cp)->cc_events &= ~CALLB_CPR_SAFE;		\
1827c478bd9Sstevel@tonic-gate 	}
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate  * cv_destroy is nop right now but may be needed in the future.
1857c478bd9Sstevel@tonic-gate  */
1867c478bd9Sstevel@tonic-gate #define	CALLB_CPR_EXIT(cp) {				\
1877c478bd9Sstevel@tonic-gate 		CALLB_CPR_ASSERT(cp)			\
1887c478bd9Sstevel@tonic-gate 		(cp)->cc_events |= CALLB_CPR_SAFE;	\
1897c478bd9Sstevel@tonic-gate 		if ((cp)->cc_events & CALLB_CPR_START)	\
1907c478bd9Sstevel@tonic-gate 			cv_signal(&(cp)->cc_callb_cv);	\
1917c478bd9Sstevel@tonic-gate 		mutex_exit((cp)->cc_lockp);		\
1927c478bd9Sstevel@tonic-gate 		(void) callb_delete((cp)->cc_id);	\
1937c478bd9Sstevel@tonic-gate 		cv_destroy(&(cp)->cc_callb_cv);		\
1947c478bd9Sstevel@tonic-gate 		cv_destroy(&(cp)->cc_stop_cv);		\
1957c478bd9Sstevel@tonic-gate 	}
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate extern callb_cpr_t callb_cprinfo_safe;
1987c478bd9Sstevel@tonic-gate extern void	callb_init(void);
1997c478bd9Sstevel@tonic-gate extern callb_id_t callb_add(boolean_t  (*)(void *, int), void *, int, char *);
2007c478bd9Sstevel@tonic-gate extern callb_id_t callb_add_thread(boolean_t (*)(void *, int),
2017c478bd9Sstevel@tonic-gate     void *, int, char *, kthread_id_t);
2027c478bd9Sstevel@tonic-gate extern int	callb_delete(callb_id_t);
2037c478bd9Sstevel@tonic-gate extern void	callb_execute(callb_id_t, int);
2047c478bd9Sstevel@tonic-gate extern void	*callb_execute_class(int, int);
2057c478bd9Sstevel@tonic-gate extern boolean_t callb_generic_cpr(void *, int);
2067c478bd9Sstevel@tonic-gate extern boolean_t callb_generic_cpr_safe(void *, int);
2077c478bd9Sstevel@tonic-gate extern boolean_t callb_is_stopped(kthread_id_t, caddr_t *);
2087c478bd9Sstevel@tonic-gate extern void	callb_lock_table(void);
2097c478bd9Sstevel@tonic-gate extern void	callb_unlock_table(void);
2107c478bd9Sstevel@tonic-gate #endif
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate #endif
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate #endif	/* _SYS_CALLB_H */
217