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/kcondvar.h> 30 31#ifdef __cplusplus 32extern "C" { 33#endif 34 35/* 36 * definitions of callback classes (c_class) 37 * 38 * Callbacks belong in the same class if (1) their callback routines 39 * do the same kind of processing (ideally, using the same callback function) 40 * and (2) they can/should be executed at the same time in a cpr 41 * suspend/resume operation. 42 * 43 * Note: The DAEMON class, in particular, is for stopping kernel threads 44 * and nothing else. The CALLB_* macros below should be used to deal 45 * with kernel threads, and the callback function should be callb_generic_cpr. 46 * Another idiosyncrasy of the DAEMON class is that if a suspend operation 47 * fails, some of the callback functions may be called with the RESUME 48 * code which were never called with SUSPEND. Not a problem currently, 49 * but see bug 4201851. 50 */ 51#define CB_CL_CPR_DAEMON 0 52#define CB_CL_CPR_VM 1 53#define CB_CL_CPR_CALLOUT 2 54#define CB_CL_CPR_OBP 3 55#define CB_CL_CPR_FB 4 56#define CB_CL_PANIC 5 57#define CB_CL_CPR_RPC 6 58#define CB_CL_CPR_PROMPRINTF 7 59#define CB_CL_UADMIN 8 60#define CB_CL_CPR_PM 9 61#define CB_CL_HALT 10 62#define CB_CL_CPR_DMA 11 63#define CB_CL_CPR_POST_USER 12 64#define CB_CL_UADMIN_PRE_VFS 13 65#define CB_CL_MDBOOT CB_CL_UADMIN 66#define CB_CL_ENTER_DEBUGGER 14 67#define CB_CL_CPR_POST_KERNEL 15 68#define CB_CL_CPU_DEEP_IDLE 16 69#define NCBCLASS 17 /* CHANGE ME if classes are added/removed */ 70 71/* 72 * CB_CL_CPR_DAEMON class specific definitions are given below: 73 */ 74 75/* 76 * code for CPR callb_execute_class 77 */ 78#define CB_CODE_CPR_CHKPT 0 79#define CB_CODE_CPR_RESUME 1 80 81typedef void * callb_id_t; 82/* 83 * Per kernel thread structure for CPR daemon callbacks. 84 * Must be protected by either a existing lock in the daemon or 85 * a new lock created for such a purpose. 86 */ 87typedef struct callb_cpr { 88 kmutex_t *cc_lockp; /* lock to protect this struct */ 89 char cc_events; /* various events for CPR */ 90 callb_id_t cc_id; /* callb id address */ 91 kcondvar_t cc_callb_cv; /* cv for callback waiting */ 92 kcondvar_t cc_stop_cv; /* cv to checkpoint block */ 93} callb_cpr_t; 94 95/* 96 * cc_events definitions 97 */ 98#define CALLB_CPR_START 1 /* a checkpoint request's started */ 99#define CALLB_CPR_SAFE 2 /* thread is safe for CPR */ 100#define CALLB_CPR_ALWAYS_SAFE 4 /* thread is ALWAYS safe for CPR */ 101 102/* 103 * Used when checking that all kernel threads are stopped. 104 */ 105#define CALLB_MAX_RETRY 3 /* when waiting for kthread to sleep */ 106#define CALLB_THREAD_DELAY 10 /* ticks allowed to reach sleep */ 107#define CPR_KTHREAD_TIMEOUT_SEC 90 /* secs before callback times out -- */ 108 /* due to pwr mgmt of disks, make -- */ 109 /* big enough for worst spinup time */ 110 111#ifdef _KERNEL 112/* 113 * 114 * CALLB_CPR_INIT macro is used by kernel threads to add their entry to 115 * the callback table and perform other initialization. It automatically 116 * adds the thread as being in the callback class CB_CL_CPR_DAEMON. 117 * 118 * cp - ptr to the callb_cpr_t structure for this kernel thread 119 * 120 * lockp - pointer to mutex protecting the callb_cpr_t stuct 121 * 122 * func - pointer to the callback function for this kernel thread. 123 * It has the prototype boolean_t <func>(void *arg, int code) 124 * where: arg - ptr to the callb_cpr_t structure 125 * code - not used for this type of callback 126 * returns: B_TRUE if successful; B_FALSE if unsuccessful. 127 * 128 * name - a string giving the name of the kernel thread 129 * 130 * Note: lockp is the lock to protect the callb_cpr_t (cp) structure 131 * later on. No lock held is needed for this initialization. 132 */ 133#define CALLB_CPR_INIT(cp, lockp, func, name) { \ 134 strlcpy(curthread->td_name, (name), \ 135 sizeof(curthread->td_name)); \ 136 bzero((caddr_t)(cp), sizeof (callb_cpr_t)); \ 137 (cp)->cc_lockp = lockp; \ 138 (cp)->cc_id = callb_add(func, (void *)(cp), \ 139 CB_CL_CPR_DAEMON, name); \ 140 cv_init(&(cp)->cc_callb_cv, NULL, CV_DEFAULT, NULL); \ 141 cv_init(&(cp)->cc_stop_cv, NULL, CV_DEFAULT, NULL); \ 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 197extern callb_cpr_t callb_cprinfo_safe; 198extern callb_id_t callb_add(boolean_t (*)(void *, int), void *, int, char *); 199extern callb_id_t callb_add_thread(boolean_t (*)(void *, int), 200 void *, int, char *, kthread_id_t); 201extern int callb_delete(callb_id_t); 202extern void callb_execute(callb_id_t, int); 203extern void *callb_execute_class(int, int); 204extern boolean_t callb_generic_cpr(void *, int); 205extern boolean_t callb_generic_cpr_safe(void *, int); 206extern boolean_t callb_is_stopped(kthread_id_t, caddr_t *); 207extern void callb_lock_table(void); 208extern void callb_unlock_table(void); 209#endif 210 211#ifdef __cplusplus 212} 213#endif 214 215#endif /* _SYS_CALLB_H */ 216