Home | History | Annotate | Download | only in os
      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, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <sys/types.h>
     30 #include <sys/param.h>
     31 #include <sys/var.h>
     32 #include <sys/thread.h>
     33 #include <sys/cpuvar.h>
     34 #include <sys/kstat.h>
     35 #include <sys/uadmin.h>
     36 #include <sys/systm.h>
     37 #include <sys/errno.h>
     38 #include <sys/cmn_err.h>
     39 #include <sys/procset.h>
     40 #include <sys/processor.h>
     41 #include <sys/debug.h>
     42 #include <sys/cyclic.h>
     43 #include <sys/pool_pset.h>
     44 
     45 /*
     46  * cpu_intr_on - determine whether the CPU is participating
     47  * in I/O interrupts.
     48  */
     49 int
     50 cpu_intr_on(cpu_t *cp)
     51 {
     52 	ASSERT(MUTEX_HELD(&cpu_lock));
     53 	return ((cp->cpu_flags & CPU_ENABLE) != 0);
     54 }
     55 
     56 /*
     57  * Return the next on-line CPU handling interrupts.
     58  */
     59 cpu_t *
     60 cpu_intr_next(cpu_t *cp)
     61 {
     62 	cpu_t	*c;
     63 
     64 	ASSERT(MUTEX_HELD(&cpu_lock));
     65 
     66 	c = cp->cpu_next_onln;
     67 	while (c != cp) {
     68 		if (cpu_intr_on(c)) {
     69 			return (c);
     70 		}
     71 		c = c->cpu_next_onln;
     72 	}
     73 	return (NULL);
     74 }
     75 
     76 /*
     77  * cpu_intr_count - count how many CPUs are handling I/O interrupts.
     78  */
     79 int
     80 cpu_intr_count(cpu_t *cp)
     81 {
     82 	cpu_t	*c;
     83 	int	count = 0;
     84 
     85 	ASSERT(MUTEX_HELD(&cpu_lock));
     86 	c = cp;
     87 	do {
     88 		if (cpu_intr_on(c)) {
     89 			++count;
     90 		}
     91 	} while ((c = c->cpu_next) != cp);
     92 	return (count);
     93 }
     94 
     95 /*
     96  * Enable I/O interrupts on this CPU, if they are disabled.
     97  */
     98 void
     99 cpu_intr_enable(cpu_t *cp)
    100 {
    101 	ASSERT(MUTEX_HELD(&cpu_lock));
    102 	if (!cpu_intr_on(cp)) {
    103 		cpu_enable_intr(cp);
    104 		cpu_set_state(cp);
    105 	}
    106 }
    107 
    108 /*
    109  * cpu_intr_disable - redirect I/O interrupts targetted at this CPU.
    110  *
    111  * semantics: We check the count of CPUs that are accepting
    112  * interrupts, because it's stupid to take the last CPU out
    113  * of I/O interrupt participation. This also permits the
    114  * p_online syscall to fail gracefully in uniprocessor configurations
    115  * without having to perform any special platform-specific operations.
    116  */
    117 int
    118 cpu_intr_disable(cpu_t *cp)
    119 {
    120 	int	e = EBUSY;
    121 
    122 	ASSERT(MUTEX_HELD(&cpu_lock));
    123 	if ((cpu_intr_count(cp) > 1) && (cpu_intr_next(cp) != NULL)) {
    124 		if (cpu_intr_on(cp)) {
    125 			/*
    126 			 * Juggle away cyclics, but don't fail if we don't
    127 			 * manage to juggle all of them away; we want to allow
    128 			 * CPU-bound cyclics to continue to fire on the
    129 			 * sheltered CPU.
    130 			 */
    131 			(void) cyclic_juggle(cp);
    132 			e = cpu_disable_intr(cp);
    133 		}
    134 	}
    135 	if (e == 0)
    136 		cpu_set_state(cp);
    137 	return (e);
    138 }
    139