10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*8906SEric.Saxe@Sun.COM * Common Development and Distribution License (the "License"). 6*8906SEric.Saxe@Sun.COM * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*8906SEric.Saxe@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #ifndef _SYS_CALLB_H 270Sstevel@tonic-gate #define _SYS_CALLB_H 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/t_lock.h> 300Sstevel@tonic-gate #include <sys/thread.h> 310Sstevel@tonic-gate 320Sstevel@tonic-gate #ifdef __cplusplus 330Sstevel@tonic-gate extern "C" { 340Sstevel@tonic-gate #endif 350Sstevel@tonic-gate 360Sstevel@tonic-gate /* 370Sstevel@tonic-gate * definitions of callback classes (c_class) 380Sstevel@tonic-gate * 390Sstevel@tonic-gate * Callbacks belong in the same class if (1) their callback routines 400Sstevel@tonic-gate * do the same kind of processing (ideally, using the same callback function) 410Sstevel@tonic-gate * and (2) they can/should be executed at the same time in a cpr 420Sstevel@tonic-gate * suspend/resume operation. 430Sstevel@tonic-gate * 440Sstevel@tonic-gate * Note: The DAEMON class, in particular, is for stopping kernel threads 450Sstevel@tonic-gate * and nothing else. The CALLB_* macros below should be used to deal 460Sstevel@tonic-gate * with kernel threads, and the callback function should be callb_generic_cpr. 470Sstevel@tonic-gate * Another idiosyncrasy of the DAEMON class is that if a suspend operation 480Sstevel@tonic-gate * fails, some of the callback functions may be called with the RESUME 490Sstevel@tonic-gate * code which were never called with SUSPEND. Not a problem currently, 500Sstevel@tonic-gate * but see bug 4201851. 510Sstevel@tonic-gate */ 520Sstevel@tonic-gate #define CB_CL_CPR_DAEMON 0 530Sstevel@tonic-gate #define CB_CL_CPR_VM 1 540Sstevel@tonic-gate #define CB_CL_CPR_CALLOUT 2 550Sstevel@tonic-gate #define CB_CL_CPR_OBP 3 560Sstevel@tonic-gate #define CB_CL_CPR_FB 4 570Sstevel@tonic-gate #define CB_CL_PANIC 5 580Sstevel@tonic-gate #define CB_CL_CPR_RPC 6 590Sstevel@tonic-gate #define CB_CL_CPR_PROMPRINTF 7 600Sstevel@tonic-gate #define CB_CL_UADMIN 8 610Sstevel@tonic-gate #define CB_CL_CPR_PM 9 620Sstevel@tonic-gate #define CB_CL_HALT 10 630Sstevel@tonic-gate #define CB_CL_CPR_DMA 11 640Sstevel@tonic-gate #define CB_CL_CPR_POST_USER 12 650Sstevel@tonic-gate #define CB_CL_UADMIN_PRE_VFS 13 66136Sachartre #define CB_CL_MDBOOT CB_CL_UADMIN 670Sstevel@tonic-gate #define CB_CL_ENTER_DEBUGGER 14 680Sstevel@tonic-gate #define CB_CL_CPR_POST_KERNEL 15 69*8906SEric.Saxe@Sun.COM #define CB_CL_CPU_DEEP_IDLE 16 70*8906SEric.Saxe@Sun.COM #define NCBCLASS 17 /* CHANGE ME if classes are added/removed */ 710Sstevel@tonic-gate 720Sstevel@tonic-gate /* 730Sstevel@tonic-gate * CB_CL_CPR_DAEMON class specific definitions are given below: 740Sstevel@tonic-gate */ 750Sstevel@tonic-gate 760Sstevel@tonic-gate /* 770Sstevel@tonic-gate * code for CPR callb_execute_class 780Sstevel@tonic-gate */ 790Sstevel@tonic-gate #define CB_CODE_CPR_CHKPT 0 800Sstevel@tonic-gate #define CB_CODE_CPR_RESUME 1 810Sstevel@tonic-gate 820Sstevel@tonic-gate typedef void * callb_id_t; 830Sstevel@tonic-gate /* 840Sstevel@tonic-gate * Per kernel thread structure for CPR daemon callbacks. 850Sstevel@tonic-gate * Must be protected by either a existing lock in the daemon or 860Sstevel@tonic-gate * a new lock created for such a purpose. 870Sstevel@tonic-gate */ 880Sstevel@tonic-gate typedef struct callb_cpr { 890Sstevel@tonic-gate kmutex_t *cc_lockp; /* lock to protect this struct */ 900Sstevel@tonic-gate char cc_events; /* various events for CPR */ 910Sstevel@tonic-gate callb_id_t cc_id; /* callb id address */ 920Sstevel@tonic-gate kcondvar_t cc_callb_cv; /* cv for callback waiting */ 930Sstevel@tonic-gate kcondvar_t cc_stop_cv; /* cv to checkpoint block */ 940Sstevel@tonic-gate } callb_cpr_t; 950Sstevel@tonic-gate 960Sstevel@tonic-gate /* 970Sstevel@tonic-gate * cc_events definitions 980Sstevel@tonic-gate */ 990Sstevel@tonic-gate #define CALLB_CPR_START 1 /* a checkpoint request's started */ 1000Sstevel@tonic-gate #define CALLB_CPR_SAFE 2 /* thread is safe for CPR */ 1010Sstevel@tonic-gate #define CALLB_CPR_ALWAYS_SAFE 4 /* thread is ALWAYS safe for CPR */ 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate /* 1040Sstevel@tonic-gate * Used when checking that all kernel threads are stopped. 1050Sstevel@tonic-gate */ 1060Sstevel@tonic-gate #define CALLB_MAX_RETRY 3 /* when waiting for kthread to sleep */ 1070Sstevel@tonic-gate #define CALLB_THREAD_DELAY 10 /* ticks allowed to reach sleep */ 1080Sstevel@tonic-gate #define CPR_KTHREAD_TIMEOUT_SEC 90 /* secs before callback times out -- */ 1090Sstevel@tonic-gate /* due to pwr mgmt of disks, make -- */ 1100Sstevel@tonic-gate /* big enough for worst spinup time */ 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate #ifdef _KERNEL 1130Sstevel@tonic-gate /* 1140Sstevel@tonic-gate * 1150Sstevel@tonic-gate * CALLB_CPR_INIT macro is used by kernel threads to add their entry to 1160Sstevel@tonic-gate * the callback table and perform other initialization. It automatically 1170Sstevel@tonic-gate * adds the thread as being in the callback class CB_CL_CPR_DAEMON. 1180Sstevel@tonic-gate * 1190Sstevel@tonic-gate * cp - ptr to the callb_cpr_t structure for this kernel thread 1200Sstevel@tonic-gate * 1210Sstevel@tonic-gate * lockp - pointer to mutex protecting the callb_cpr_t stuct 1220Sstevel@tonic-gate * 1230Sstevel@tonic-gate * func - pointer to the callback function for this kernel thread. 1240Sstevel@tonic-gate * It has the prototype boolean_t <func>(void *arg, int code) 1250Sstevel@tonic-gate * where: arg - ptr to the callb_cpr_t structure 1260Sstevel@tonic-gate * code - not used for this type of callback 1270Sstevel@tonic-gate * returns: B_TRUE if successful; B_FALSE if unsuccessful. 1280Sstevel@tonic-gate * 1290Sstevel@tonic-gate * name - a string giving the name of the kernel thread 1300Sstevel@tonic-gate * 1310Sstevel@tonic-gate * Note: lockp is the lock to protect the callb_cpr_t (cp) structure 1320Sstevel@tonic-gate * later on. No lock held is needed for this initialization. 1330Sstevel@tonic-gate */ 1340Sstevel@tonic-gate #define CALLB_CPR_INIT(cp, lockp, func, name) { \ 1350Sstevel@tonic-gate bzero((caddr_t)(cp), sizeof (callb_cpr_t)); \ 1360Sstevel@tonic-gate (cp)->cc_lockp = lockp; \ 1370Sstevel@tonic-gate (cp)->cc_id = callb_add(func, (void *)(cp), \ 1380Sstevel@tonic-gate CB_CL_CPR_DAEMON, name); \ 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate #ifndef __lock_lint 1420Sstevel@tonic-gate #define CALLB_CPR_ASSERT(cp) ASSERT(MUTEX_HELD((cp)->cc_lockp)); 1430Sstevel@tonic-gate #else 1440Sstevel@tonic-gate #define CALLB_CPR_ASSERT(cp) 1450Sstevel@tonic-gate #endif 1460Sstevel@tonic-gate /* 1470Sstevel@tonic-gate * Some threads (like the idle threads) do not adhere to the callback 1480Sstevel@tonic-gate * protocol and are always considered safe. Such threads must never exit. 1490Sstevel@tonic-gate * They register their presence by calling this macro during their 1500Sstevel@tonic-gate * initialization. 1510Sstevel@tonic-gate * 1520Sstevel@tonic-gate * Args: 1530Sstevel@tonic-gate * t - thread pointer of the client kernel thread 1540Sstevel@tonic-gate * name - a string giving the name of the kernel thread 1550Sstevel@tonic-gate */ 1560Sstevel@tonic-gate #define CALLB_CPR_INIT_SAFE(t, name) { \ 1570Sstevel@tonic-gate (void) callb_add_thread(callb_generic_cpr_safe, \ 1580Sstevel@tonic-gate (void *) &callb_cprinfo_safe, CB_CL_CPR_DAEMON, \ 1590Sstevel@tonic-gate name, t); \ 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate /* 1620Sstevel@tonic-gate * The lock to protect cp's content must be held before 1630Sstevel@tonic-gate * calling the following two macros. 1640Sstevel@tonic-gate * 1650Sstevel@tonic-gate * Any code region between CALLB_CPR_SAFE_BEGIN and CALLB_CPR_SAFE_END 1660Sstevel@tonic-gate * is safe for checkpoint/resume. 1670Sstevel@tonic-gate */ 1680Sstevel@tonic-gate #define CALLB_CPR_SAFE_BEGIN(cp) { \ 1690Sstevel@tonic-gate CALLB_CPR_ASSERT(cp) \ 1700Sstevel@tonic-gate (cp)->cc_events |= CALLB_CPR_SAFE; \ 1710Sstevel@tonic-gate if ((cp)->cc_events & CALLB_CPR_START) \ 1720Sstevel@tonic-gate cv_signal(&(cp)->cc_callb_cv); \ 1730Sstevel@tonic-gate } 1740Sstevel@tonic-gate #define CALLB_CPR_SAFE_END(cp, lockp) { \ 1750Sstevel@tonic-gate CALLB_CPR_ASSERT(cp) \ 1760Sstevel@tonic-gate while ((cp)->cc_events & CALLB_CPR_START) \ 1770Sstevel@tonic-gate cv_wait(&(cp)->cc_stop_cv, lockp); \ 1780Sstevel@tonic-gate (cp)->cc_events &= ~CALLB_CPR_SAFE; \ 1790Sstevel@tonic-gate } 1800Sstevel@tonic-gate /* 1810Sstevel@tonic-gate * cv_destroy is nop right now but may be needed in the future. 1820Sstevel@tonic-gate */ 1830Sstevel@tonic-gate #define CALLB_CPR_EXIT(cp) { \ 1840Sstevel@tonic-gate CALLB_CPR_ASSERT(cp) \ 1850Sstevel@tonic-gate (cp)->cc_events |= CALLB_CPR_SAFE; \ 1860Sstevel@tonic-gate if ((cp)->cc_events & CALLB_CPR_START) \ 1870Sstevel@tonic-gate cv_signal(&(cp)->cc_callb_cv); \ 1880Sstevel@tonic-gate mutex_exit((cp)->cc_lockp); \ 1890Sstevel@tonic-gate (void) callb_delete((cp)->cc_id); \ 1900Sstevel@tonic-gate cv_destroy(&(cp)->cc_callb_cv); \ 1910Sstevel@tonic-gate cv_destroy(&(cp)->cc_stop_cv); \ 1920Sstevel@tonic-gate } 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate extern callb_cpr_t callb_cprinfo_safe; 1950Sstevel@tonic-gate extern void callb_init(void); 1960Sstevel@tonic-gate extern callb_id_t callb_add(boolean_t (*)(void *, int), void *, int, char *); 1970Sstevel@tonic-gate extern callb_id_t callb_add_thread(boolean_t (*)(void *, int), 1980Sstevel@tonic-gate void *, int, char *, kthread_id_t); 1990Sstevel@tonic-gate extern int callb_delete(callb_id_t); 2000Sstevel@tonic-gate extern void callb_execute(callb_id_t, int); 2010Sstevel@tonic-gate extern void *callb_execute_class(int, int); 2020Sstevel@tonic-gate extern boolean_t callb_generic_cpr(void *, int); 2030Sstevel@tonic-gate extern boolean_t callb_generic_cpr_safe(void *, int); 2040Sstevel@tonic-gate extern boolean_t callb_is_stopped(kthread_id_t, caddr_t *); 2050Sstevel@tonic-gate extern void callb_lock_table(void); 2060Sstevel@tonic-gate extern void callb_unlock_table(void); 2070Sstevel@tonic-gate #endif 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate #ifdef __cplusplus 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate #endif 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate #endif /* _SYS_CALLB_H */ 214