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#ifdef __NetBSD__ 134#define CALLB_CPR_INIT(cp, lockp, func, name) { \ 135 /* XXXNETBSD set thread 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#else 144#define CALLB_CPR_INIT(cp, lockp, func, name) { \ 145 strlcpy(curthread->td_name, (name), \ 146 sizeof(curthread->td_name)); \ 147 bzero((caddr_t)(cp), sizeof (callb_cpr_t)); \ 148 (cp)->cc_lockp = lockp; \ 149 (cp)->cc_id = callb_add(func, (void *)(cp), \ 150 CB_CL_CPR_DAEMON, name); \ 151 cv_init(&(cp)->cc_callb_cv, NULL, CV_DEFAULT, NULL); \ 152 cv_init(&(cp)->cc_stop_cv, NULL, CV_DEFAULT, NULL); \ 153 } 154#endif 155 156#ifndef __lock_lint 157#define CALLB_CPR_ASSERT(cp) ASSERT(MUTEX_HELD((cp)->cc_lockp)); 158#else 159#define CALLB_CPR_ASSERT(cp) 160#endif 161/* 162 * Some threads (like the idle threads) do not adhere to the callback 163 * protocol and are always considered safe. Such threads must never exit. 164 * They register their presence by calling this macro during their 165 * initialization. 166 * 167 * Args: 168 * t - thread pointer of the client kernel thread 169 * name - a string giving the name of the kernel thread 170 */ 171#define CALLB_CPR_INIT_SAFE(t, name) { \ 172 (void) callb_add_thread(callb_generic_cpr_safe, \ 173 (void *) &callb_cprinfo_safe, CB_CL_CPR_DAEMON, \ 174 name, t); \ 175 } 176/* 177 * The lock to protect cp's content must be held before 178 * calling the following two macros. 179 * 180 * Any code region between CALLB_CPR_SAFE_BEGIN and CALLB_CPR_SAFE_END 181 * is safe for checkpoint/resume. 182 */ 183#define CALLB_CPR_SAFE_BEGIN(cp) { \ 184 CALLB_CPR_ASSERT(cp) \ 185 (cp)->cc_events |= CALLB_CPR_SAFE; \ 186 if ((cp)->cc_events & CALLB_CPR_START) \ 187 cv_signal(&(cp)->cc_callb_cv); \ 188 } 189#define CALLB_CPR_SAFE_END(cp, lockp) { \ 190 CALLB_CPR_ASSERT(cp) \ 191 while ((cp)->cc_events & CALLB_CPR_START) \ 192 cv_wait(&(cp)->cc_stop_cv, lockp); \ 193 (cp)->cc_events &= ~CALLB_CPR_SAFE; \ 194 } 195/* 196 * cv_destroy is nop right now but may be needed in the future. 197 */ 198#define CALLB_CPR_EXIT(cp) { \ 199 CALLB_CPR_ASSERT(cp) \ 200 (cp)->cc_events |= CALLB_CPR_SAFE; \ 201 if ((cp)->cc_events & CALLB_CPR_START) \ 202 cv_signal(&(cp)->cc_callb_cv); \ 203 mutex_exit((cp)->cc_lockp); \ 204 (void) callb_delete((cp)->cc_id); \ 205 cv_destroy(&(cp)->cc_callb_cv); \ 206 cv_destroy(&(cp)->cc_stop_cv); \ 207 } 208 209extern callb_cpr_t callb_cprinfo_safe; 210extern callb_id_t callb_add(boolean_t (*)(void *, int), void *, int, char *); 211extern callb_id_t callb_add_thread(boolean_t (*)(void *, int), 212 void *, int, char *, kthread_id_t); 213extern int callb_delete(callb_id_t); 214extern void callb_execute(callb_id_t, int); 215extern void *callb_execute_class(int, int); 216extern boolean_t callb_generic_cpr(void *, int); 217extern boolean_t callb_generic_cpr_safe(void *, int); 218extern boolean_t callb_is_stopped(kthread_id_t, caddr_t *); 219extern void callb_lock_table(void); 220extern void callb_unlock_table(void); 221#ifdef __NetBSD__ 222extern void callb_init(void *); 223extern void callb_fini(void *); 224#endif 225#endif 226 227#ifdef __cplusplus 228} 229#endif 230 231#endif /* _SYS_CALLB_H */ 232