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