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