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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/param.h>
27 #include <sys/t_lock.h>
28 #include <sys/types.h>
30 #include <sys/sysmacros.h>
31 #include <sys/systm.h>
32 #include <sys/cpuvar.h>
35 #include <sys/callb.h>
37 #include <sys/cmn_err.h>
39 #include <sys/vmsystm.h>
40 #include <sys/class.h>
41 #include <sys/debug.h>
42 #include <sys/thread.h>
44 #include <sys/ddi.h> /* for delay() */
45 #include <sys/taskq.h> /* For TASKQ_NAMELEN */
47 #define CB_MAXNAME TASKQ_NAMELEN
50 * The callb mechanism provides generic event scheduling/echoing.
51 * A callb function is registered and called on behalf of the event.
53 typedef struct callb
{
54 struct callb
*c_next
; /* next in class or on freelist */
55 kthread_id_t c_thread
; /* ptr to caller's thread struct */
56 char c_flag
; /* info about the callb state */
57 uchar_t c_class
; /* this callb's class */
58 kcondvar_t c_done_cv
; /* signal callb completion */
59 boolean_t (*c_func
)(); /* cb function: returns true if ok */
60 void *c_arg
; /* arg to c_func */
61 char c_name
[CB_MAXNAME
+1]; /* debug:max func name length */
65 * callb c_flag bitmap definitions
67 #define CALLB_FREE 0x0
68 #define CALLB_TAKEN 0x1
69 #define CALLB_EXECUTING 0x2
72 * Basic structure for a callb table.
73 * All callbs are organized into different class groups described
75 * The callbs within a class are single-linked and normally run by a
78 typedef struct callb_table
{
79 kmutex_t ct_lock
; /* protect all callb states */
80 callb_t
*ct_freelist
; /* free callb structures */
81 int ct_busy
; /* != 0 prevents additions */
82 kcondvar_t ct_busy_cv
; /* to wait for not busy */
83 int ct_ncallb
; /* num of callbs allocated */
84 callb_t
*ct_first_cb
[NCBCLASS
]; /* ptr to 1st callb in a class */
87 int callb_timeout_sec
= CPR_KTHREAD_TIMEOUT_SEC
;
89 static callb_id_t
callb_add_common(boolean_t (*)(void *, int),
90 void *, int, char *, kthread_id_t
);
92 static callb_table_t callb_table
; /* system level callback table */
93 static callb_table_t
*ct
= &callb_table
;
94 static kmutex_t callb_safe_mutex
;
95 callb_cpr_t callb_cprinfo_safe
= {
96 &callb_safe_mutex
, CALLB_CPR_ALWAYS_SAFE
, 0, 0, 0 };
99 * Init all callb tables in the system.
104 callb_table
.ct_busy
= 0; /* mark table open for additions */
105 mutex_init(&callb_safe_mutex
, NULL
, MUTEX_DEFAULT
, NULL
);
106 mutex_init(&callb_table
.ct_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
110 * callout_add() is called to register func() be called later.
113 callb_add_common(boolean_t (*func
)(void *arg
, int code
),
114 void *arg
, int class, char *name
, kthread_id_t t
)
118 ASSERT(class < NCBCLASS
);
120 mutex_enter(&ct
->ct_lock
);
122 cv_wait(&ct
->ct_busy_cv
, &ct
->ct_lock
);
123 if ((cp
= ct
->ct_freelist
) == NULL
) {
125 cp
= (callb_t
*)kmem_zalloc(sizeof (callb_t
), KM_SLEEP
);
127 ct
->ct_freelist
= cp
->c_next
;
131 cp
->c_class
= (uchar_t
)class;
132 cp
->c_flag
|= CALLB_TAKEN
;
134 if (strlen(name
) > CB_MAXNAME
)
135 cmn_err(CE_WARN
, "callb_add: name of callback function '%s' "
136 "too long -- truncated to %d chars",
139 (void) strncpy(cp
->c_name
, name
, CB_MAXNAME
);
140 cp
->c_name
[CB_MAXNAME
] = '\0';
143 * Insert the new callb at the head of its class list.
145 cp
->c_next
= ct
->ct_first_cb
[class];
146 ct
->ct_first_cb
[class] = cp
;
148 mutex_exit(&ct
->ct_lock
);
149 return ((callb_id_t
)cp
);
153 * The default function to add an entry to the callback table. Since
154 * it uses curthread as the thread identifier to store in the table,
155 * it should be used for the normal case of a thread which is calling
156 * to add ITSELF to the table.
159 callb_add(boolean_t (*func
)(void *arg
, int code
),
160 void *arg
, int class, char *name
)
162 return (callb_add_common(func
, arg
, class, name
, curthread
));
166 * A special version of callb_add() above for use by threads which
167 * might be adding an entry to the table on behalf of some other
168 * thread (for example, one which is constructed but not yet running).
169 * In this version the thread id is an argument.
172 callb_add_thread(boolean_t (*func
)(void *arg
, int code
),
173 void *arg
, int class, char *name
, kthread_id_t t
)
175 return (callb_add_common(func
, arg
, class, name
, t
));
179 * callout_delete() is called to remove an entry identified by id
180 * that was originally placed there by a call to callout_add().
181 * return -1 if fail to delete a callb entry otherwise return 0.
184 callb_delete(callb_id_t id
)
187 callb_t
*me
= (callb_t
*)id
;
189 mutex_enter(&ct
->ct_lock
);
192 pp
= &ct
->ct_first_cb
[me
->c_class
];
193 while (*pp
!= NULL
&& *pp
!= me
)
198 cmn_err(CE_WARN
, "callb delete bogus entry 0x%p",
200 mutex_exit(&ct
->ct_lock
);
206 * It is not allowed to delete a callb in the middle of
207 * executing otherwise, the callb_execute() will be confused.
209 if (!(me
->c_flag
& CALLB_EXECUTING
))
212 cv_wait(&me
->c_done_cv
, &ct
->ct_lock
);
214 /* relink the class list */
217 /* clean up myself and return the free callb to the head of freelist */
218 me
->c_flag
= CALLB_FREE
;
219 me
->c_next
= ct
->ct_freelist
;
220 ct
->ct_freelist
= me
;
222 mutex_exit(&ct
->ct_lock
);
227 * class: indicates to execute all callbs in the same class;
228 * code: optional argument for the callb functions.
229 * return: = 0: success
230 * != 0: ptr to string supplied when callback was registered
233 callb_execute_class(int class, int code
)
238 ASSERT(class < NCBCLASS
);
240 mutex_enter(&ct
->ct_lock
);
242 for (cp
= ct
->ct_first_cb
[class];
243 cp
!= NULL
&& ret
== 0; cp
= cp
->c_next
) {
244 while (cp
->c_flag
& CALLB_EXECUTING
)
245 cv_wait(&cp
->c_done_cv
, &ct
->ct_lock
);
247 * cont if the callb is deleted while we're sleeping
249 if (cp
->c_flag
== CALLB_FREE
)
251 cp
->c_flag
|= CALLB_EXECUTING
;
254 printf("callb_execute: name=%s func=%p arg=%p\n",
255 cp
->c_name
, (void *)cp
->c_func
, (void *)cp
->c_arg
);
256 #endif /* CALLB_DEBUG */
258 mutex_exit(&ct
->ct_lock
);
259 /* If callback function fails, pass back client's name */
260 if (!(*cp
->c_func
)(cp
->c_arg
, code
))
262 mutex_enter(&ct
->ct_lock
);
264 cp
->c_flag
&= ~CALLB_EXECUTING
;
265 cv_broadcast(&cp
->c_done_cv
);
267 mutex_exit(&ct
->ct_lock
);
272 * callers make sure no recursive entries to this func.
273 * dp->cc_lockp is registered by callb_add to protect callb_cpr_t structure.
275 * When calling to stop a kernel thread (code == CB_CODE_CPR_CHKPT) we
276 * use a cv_timedwait() in case the kernel thread is blocked.
278 * Note that this is a generic callback handler for daemon CPR and
279 * should NOT be changed to accommodate any specific requirement in a daemon.
280 * Individual daemons that require changes to the handler shall write
281 * callback routines in their own daemon modules.
284 callb_generic_cpr(void *arg
, int code
)
286 callb_cpr_t
*cp
= (callb_cpr_t
*)arg
;
287 clock_t ret
= 0; /* assume success */
289 mutex_enter(cp
->cc_lockp
);
292 case CB_CODE_CPR_CHKPT
:
293 cp
->cc_events
|= CALLB_CPR_START
;
294 #ifdef CPR_NOT_THREAD_SAFE
295 while (!(cp
->cc_events
& CALLB_CPR_SAFE
))
296 /* cv_timedwait() returns -1 if it times out. */
297 if ((ret
= cv_reltimedwait(&cp
->cc_callb_cv
,
298 cp
->cc_lockp
, (callb_timeout_sec
* hz
),
299 TR_CLOCK_TICK
)) == -1)
304 case CB_CODE_CPR_RESUME
:
305 cp
->cc_events
&= ~CALLB_CPR_START
;
306 cv_signal(&cp
->cc_stop_cv
);
309 mutex_exit(cp
->cc_lockp
);
314 * The generic callback function associated with kernel threads which
315 * are always considered safe.
319 callb_generic_cpr_safe(void *arg
, int code
)
324 * Prevent additions to callback table.
327 callb_lock_table(void)
329 mutex_enter(&ct
->ct_lock
);
330 ASSERT(ct
->ct_busy
== 0);
332 mutex_exit(&ct
->ct_lock
);
336 * Allow additions to callback table.
339 callb_unlock_table(void)
341 mutex_enter(&ct
->ct_lock
);
342 ASSERT(ct
->ct_busy
!= 0);
344 cv_broadcast(&ct
->ct_busy_cv
);
345 mutex_exit(&ct
->ct_lock
);
349 * Return a boolean value indicating whether a particular kernel thread is
350 * stopped in accordance with the cpr callback protocol. If returning
351 * false, also return a pointer to the thread name via the 2nd argument.
354 callb_is_stopped(kthread_id_t tp
, caddr_t
*thread_name
)
359 mutex_enter(&ct
->ct_lock
);
361 for (cp
= ct
->ct_first_cb
[CB_CL_CPR_DAEMON
];
362 cp
!= NULL
&& tp
!= cp
->c_thread
; cp
= cp
->c_next
)
365 ret_val
= (cp
!= NULL
);
368 * We found the thread in the callback table and have
369 * provisionally set the return value to true. Now
370 * see if it is marked "safe" and is sleeping or stopped.
372 callb_cpr_t
*ccp
= (callb_cpr_t
*)cp
->c_arg
;
374 *thread_name
= cp
->c_name
; /* in case not stopped */
375 mutex_enter(ccp
->cc_lockp
);
377 if (ccp
->cc_events
& CALLB_CPR_SAFE
) {
380 mutex_exit(ccp
->cc_lockp
);
381 for (retry
= 0; retry
< CALLB_MAX_RETRY
; retry
++) {
383 if (tp
->t_state
& (TS_SLEEP
| TS_STOPPED
)) {
388 delay(CALLB_THREAD_DELAY
);
390 ret_val
= retry
< CALLB_MAX_RETRY
;
393 (ccp
->cc_events
& CALLB_CPR_ALWAYS_SAFE
) != 0;
394 mutex_exit(ccp
->cc_lockp
);
398 * Thread not found in callback table. Make the best
399 * attempt to identify the thread in the error message.
402 char *sym
= kobj_getsymname((uintptr_t)tp
->t_startpc
,
405 *thread_name
= sym
? sym
: "*unknown*";
408 mutex_exit(&ct
->ct_lock
);