1168404Spjd/* 2168404Spjd * CDDL HEADER START 3168404Spjd * 4168404Spjd * The contents of this file are subject to the terms of the 5219089Spjd * Common Development and Distribution License (the "License"). 6219089Spjd * You may not use this file except in compliance with the License. 7168404Spjd * 8168404Spjd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9168404Spjd * or http://www.opensolaris.org/os/licensing. 10168404Spjd * See the License for the specific language governing permissions 11168404Spjd * and limitations under the License. 12168404Spjd * 13168404Spjd * When distributing Covered Code, include this CDDL HEADER in each 14168404Spjd * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15168404Spjd * If applicable, add the following below this CDDL HEADER, with the 16168404Spjd * fields enclosed by brackets "[]" replaced with your own identifying 17168404Spjd * information: Portions Copyright [yyyy] [name of copyright owner] 18168404Spjd * 19168404Spjd * CDDL HEADER END 20168404Spjd */ 21168404Spjd/* 22219089Spjd * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23168404Spjd * Use is subject to license terms. 24168404Spjd */ 25168404Spjd 26168404Spjd#ifndef _SYS_CALLB_H 27168404Spjd#define _SYS_CALLB_H 28168404Spjd 29185029Spjd#include <sys/kcondvar.h> 30168404Spjd 31168404Spjd#ifdef __cplusplus 32168404Spjdextern "C" { 33168404Spjd#endif 34168404Spjd 35168404Spjd/* 36168404Spjd * definitions of callback classes (c_class) 37168404Spjd * 38168404Spjd * Callbacks belong in the same class if (1) their callback routines 39168404Spjd * do the same kind of processing (ideally, using the same callback function) 40168404Spjd * and (2) they can/should be executed at the same time in a cpr 41168404Spjd * suspend/resume operation. 42168404Spjd * 43168404Spjd * Note: The DAEMON class, in particular, is for stopping kernel threads 44168404Spjd * and nothing else. The CALLB_* macros below should be used to deal 45168404Spjd * with kernel threads, and the callback function should be callb_generic_cpr. 46168404Spjd * Another idiosyncrasy of the DAEMON class is that if a suspend operation 47168404Spjd * fails, some of the callback functions may be called with the RESUME 48168404Spjd * code which were never called with SUSPEND. Not a problem currently, 49168404Spjd * but see bug 4201851. 50168404Spjd */ 51168404Spjd#define CB_CL_CPR_DAEMON 0 52168404Spjd#define CB_CL_CPR_VM 1 53168404Spjd#define CB_CL_CPR_CALLOUT 2 54168404Spjd#define CB_CL_CPR_OBP 3 55168404Spjd#define CB_CL_CPR_FB 4 56168404Spjd#define CB_CL_PANIC 5 57168404Spjd#define CB_CL_CPR_RPC 6 58168404Spjd#define CB_CL_CPR_PROMPRINTF 7 59168404Spjd#define CB_CL_UADMIN 8 60168404Spjd#define CB_CL_CPR_PM 9 61168404Spjd#define CB_CL_HALT 10 62168404Spjd#define CB_CL_CPR_DMA 11 63168404Spjd#define CB_CL_CPR_POST_USER 12 64168404Spjd#define CB_CL_UADMIN_PRE_VFS 13 65168404Spjd#define CB_CL_MDBOOT CB_CL_UADMIN 66168404Spjd#define CB_CL_ENTER_DEBUGGER 14 67168404Spjd#define CB_CL_CPR_POST_KERNEL 15 68219089Spjd#define CB_CL_CPU_DEEP_IDLE 16 69219089Spjd#define NCBCLASS 17 /* CHANGE ME if classes are added/removed */ 70168404Spjd 71168404Spjd/* 72168404Spjd * CB_CL_CPR_DAEMON class specific definitions are given below: 73168404Spjd */ 74168404Spjd 75168404Spjd/* 76168404Spjd * code for CPR callb_execute_class 77168404Spjd */ 78168404Spjd#define CB_CODE_CPR_CHKPT 0 79168404Spjd#define CB_CODE_CPR_RESUME 1 80168404Spjd 81168404Spjdtypedef void * callb_id_t; 82168404Spjd/* 83168404Spjd * Per kernel thread structure for CPR daemon callbacks. 84168404Spjd * Must be protected by either a existing lock in the daemon or 85168404Spjd * a new lock created for such a purpose. 86168404Spjd */ 87168404Spjdtypedef struct callb_cpr { 88168404Spjd kmutex_t *cc_lockp; /* lock to protect this struct */ 89168404Spjd char cc_events; /* various events for CPR */ 90168404Spjd callb_id_t cc_id; /* callb id address */ 91168404Spjd kcondvar_t cc_callb_cv; /* cv for callback waiting */ 92168404Spjd kcondvar_t cc_stop_cv; /* cv to checkpoint block */ 93168404Spjd} callb_cpr_t; 94168404Spjd 95168404Spjd/* 96168404Spjd * cc_events definitions 97168404Spjd */ 98168404Spjd#define CALLB_CPR_START 1 /* a checkpoint request's started */ 99168404Spjd#define CALLB_CPR_SAFE 2 /* thread is safe for CPR */ 100168404Spjd#define CALLB_CPR_ALWAYS_SAFE 4 /* thread is ALWAYS safe for CPR */ 101168404Spjd 102168404Spjd/* 103168404Spjd * Used when checking that all kernel threads are stopped. 104168404Spjd */ 105168404Spjd#define CALLB_MAX_RETRY 3 /* when waiting for kthread to sleep */ 106168404Spjd#define CALLB_THREAD_DELAY 10 /* ticks allowed to reach sleep */ 107168404Spjd#define CPR_KTHREAD_TIMEOUT_SEC 90 /* secs before callback times out -- */ 108168404Spjd /* due to pwr mgmt of disks, make -- */ 109168404Spjd /* big enough for worst spinup time */ 110168404Spjd 111168404Spjd#ifdef _KERNEL 112168404Spjd/* 113168404Spjd * 114168404Spjd * CALLB_CPR_INIT macro is used by kernel threads to add their entry to 115168404Spjd * the callback table and perform other initialization. It automatically 116168404Spjd * adds the thread as being in the callback class CB_CL_CPR_DAEMON. 117168404Spjd * 118168404Spjd * cp - ptr to the callb_cpr_t structure for this kernel thread 119168404Spjd * 120168404Spjd * lockp - pointer to mutex protecting the callb_cpr_t stuct 121168404Spjd * 122168404Spjd * func - pointer to the callback function for this kernel thread. 123168404Spjd * It has the prototype boolean_t <func>(void *arg, int code) 124168404Spjd * where: arg - ptr to the callb_cpr_t structure 125168404Spjd * code - not used for this type of callback 126168404Spjd * returns: B_TRUE if successful; B_FALSE if unsuccessful. 127168404Spjd * 128168404Spjd * name - a string giving the name of the kernel thread 129168404Spjd * 130168404Spjd * Note: lockp is the lock to protect the callb_cpr_t (cp) structure 131168404Spjd * later on. No lock held is needed for this initialization. 132168404Spjd */ 133168404Spjd#define CALLB_CPR_INIT(cp, lockp, func, name) { \ 134185029Spjd strlcpy(curthread->td_name, (name), \ 135185029Spjd sizeof(curthread->td_name)); \ 136168404Spjd bzero((caddr_t)(cp), sizeof (callb_cpr_t)); \ 137168404Spjd (cp)->cc_lockp = lockp; \ 138168404Spjd (cp)->cc_id = callb_add(func, (void *)(cp), \ 139168404Spjd CB_CL_CPR_DAEMON, name); \ 140185029Spjd cv_init(&(cp)->cc_callb_cv, NULL, CV_DEFAULT, NULL); \ 141185029Spjd cv_init(&(cp)->cc_stop_cv, NULL, CV_DEFAULT, NULL); \ 142168404Spjd } 143168404Spjd 144168404Spjd#ifndef __lock_lint 145168404Spjd#define CALLB_CPR_ASSERT(cp) ASSERT(MUTEX_HELD((cp)->cc_lockp)); 146168404Spjd#else 147168404Spjd#define CALLB_CPR_ASSERT(cp) 148168404Spjd#endif 149168404Spjd/* 150168404Spjd * Some threads (like the idle threads) do not adhere to the callback 151168404Spjd * protocol and are always considered safe. Such threads must never exit. 152168404Spjd * They register their presence by calling this macro during their 153168404Spjd * initialization. 154168404Spjd * 155168404Spjd * Args: 156168404Spjd * t - thread pointer of the client kernel thread 157168404Spjd * name - a string giving the name of the kernel thread 158168404Spjd */ 159168404Spjd#define CALLB_CPR_INIT_SAFE(t, name) { \ 160168404Spjd (void) callb_add_thread(callb_generic_cpr_safe, \ 161168404Spjd (void *) &callb_cprinfo_safe, CB_CL_CPR_DAEMON, \ 162168404Spjd name, t); \ 163168404Spjd } 164168404Spjd/* 165168404Spjd * The lock to protect cp's content must be held before 166168404Spjd * calling the following two macros. 167168404Spjd * 168168404Spjd * Any code region between CALLB_CPR_SAFE_BEGIN and CALLB_CPR_SAFE_END 169168404Spjd * is safe for checkpoint/resume. 170168404Spjd */ 171168404Spjd#define CALLB_CPR_SAFE_BEGIN(cp) { \ 172168404Spjd CALLB_CPR_ASSERT(cp) \ 173168404Spjd (cp)->cc_events |= CALLB_CPR_SAFE; \ 174168404Spjd if ((cp)->cc_events & CALLB_CPR_START) \ 175168404Spjd cv_signal(&(cp)->cc_callb_cv); \ 176168404Spjd } 177168404Spjd#define CALLB_CPR_SAFE_END(cp, lockp) { \ 178168404Spjd CALLB_CPR_ASSERT(cp) \ 179168404Spjd while ((cp)->cc_events & CALLB_CPR_START) \ 180168404Spjd cv_wait(&(cp)->cc_stop_cv, lockp); \ 181168404Spjd (cp)->cc_events &= ~CALLB_CPR_SAFE; \ 182168404Spjd } 183168404Spjd/* 184168404Spjd * cv_destroy is nop right now but may be needed in the future. 185168404Spjd */ 186168404Spjd#define CALLB_CPR_EXIT(cp) { \ 187168404Spjd CALLB_CPR_ASSERT(cp) \ 188168404Spjd (cp)->cc_events |= CALLB_CPR_SAFE; \ 189168404Spjd if ((cp)->cc_events & CALLB_CPR_START) \ 190168404Spjd cv_signal(&(cp)->cc_callb_cv); \ 191168404Spjd mutex_exit((cp)->cc_lockp); \ 192168404Spjd (void) callb_delete((cp)->cc_id); \ 193168404Spjd cv_destroy(&(cp)->cc_callb_cv); \ 194168404Spjd cv_destroy(&(cp)->cc_stop_cv); \ 195168404Spjd } 196168404Spjd 197168404Spjdextern callb_cpr_t callb_cprinfo_safe; 198168404Spjdextern callb_id_t callb_add(boolean_t (*)(void *, int), void *, int, char *); 199168404Spjdextern callb_id_t callb_add_thread(boolean_t (*)(void *, int), 200168404Spjd void *, int, char *, kthread_id_t); 201168404Spjdextern int callb_delete(callb_id_t); 202168404Spjdextern void callb_execute(callb_id_t, int); 203168404Spjdextern void *callb_execute_class(int, int); 204168404Spjdextern boolean_t callb_generic_cpr(void *, int); 205168404Spjdextern boolean_t callb_generic_cpr_safe(void *, int); 206168404Spjdextern boolean_t callb_is_stopped(kthread_id_t, caddr_t *); 207168404Spjdextern void callb_lock_table(void); 208168404Spjdextern void callb_unlock_table(void); 209168404Spjd#endif 210168404Spjd 211168404Spjd#ifdef __cplusplus 212168404Spjd} 213168404Spjd#endif 214168404Spjd 215168404Spjd#endif /* _SYS_CALLB_H */ 216