|
|
1.1 ! root 1: #ifndef __KERNEL_DDI_CPU_H__ ! 2: #define __KERNEL_DDI_CPU_H__ ! 3: ! 4: /* ! 5: * This internal header file defines structures and an access procedure for ! 6: * DDI/DKI data that is global per CPU. In a multiprocessor system, each ! 7: * CPU would have a distinct data region separate from all others. ! 8: */ ! 9: ! 10: /* ! 11: *-IMPORTS: ! 12: * <common/ccompat.h> ! 13: * __EXTERN_C_BEGIN__ ! 14: * __EXTERN_C_END__ ! 15: * __PROTO () ! 16: * <common/__size.h> ! 17: * __size_t ! 18: * <common/_intmask.h> ! 19: * intmask_t ! 20: * <kernel/_lock.h> ! 21: * __lock_t ! 22: * __MAX_HIERARCHY__ ! 23: * __MIN_HIERARCHY__ ! 24: * <kernel/_cpuid.h> ! 25: * processorid_t ! 26: * <sys/debug.h> ! 27: * ASSERT () ! 28: */ ! 29: ! 30: #include <common/ccompat.h> ! 31: #include <common/__size.h> ! 32: #include <common/_intmask.h> ! 33: #include <kernel/_cpuid.h> ! 34: #include <kernel/_lock.h> ! 35: #include <kernel/ddi_data.h> ! 36: #include <sys/debug.h> ! 37: ! 38: /* ! 39: * Many DDI/DKI routines specify constraints on the circumstances in which ! 40: * they may be called, for example. ! 41: * Base level only, eg SV_WAIT (). ! 42: * Pass interrupt priority level greater than the current level, ! 43: * eg LOCK (). ! 44: * Not called from within a streams service routine, eg putbq () with ! 45: * a high-priority STREAMS message. ! 46: * ! 47: * These assertions are important for maintaining system integrity, but it can ! 48: * be difficult to detect when these constraints a violated under normal ! 49: * circumstances, especially when the probability of failure is expected to ! 50: * be low. Therefore, it is important for routines which specify such ! 51: * constraints to be able to umambiguously detect constraint violations with ! 52: * the highest level of probability possible. ! 53: * ! 54: * However, the testability of these assertions depends on cooperation from ! 55: * a wide range of kernel facilities. In a highly multithreaded system with ! 56: * either multiple processors or the ability to suspend interrupt contexts, ! 57: * or both, it is necessary to be able to make detailed inquiries about the ! 58: * system state to re-establish some of the certainty about system state that ! 59: * is lost in the move to gain extra concurrency. ! 60: */ ! 61: ! 62: /* ! 63: * Returns true if we are at base level or if the system cannot distinguish ! 64: * between base and interrupt level; if the system is definitely not at base ! 65: * level, returns false. ! 66: */ ! 67: ! 68: #define IS_BASE_LEVEL() (ddi_cpu_data ()->dc_int_level == 0) ! 69: ! 70: ! 71: /* ! 72: * Returns true if we are at interrupt level or if the system cannot ! 73: * distinguish between base and interrupt level; if the system is definitely ! 74: * at base level, returns false. ! 75: */ ! 76: ! 77: #define IS_INTERRUPT_LEVEL() (ddi_cpu_data ()->dc_int_level != 0) ! 78: ! 79: ! 80: /* ! 81: * Most of the time we want to include the above in simple assertions. ! 82: */ ! 83: ! 84: #define ASSERT_BASE_LEVEL() ASSERT (IS_BASE_LEVEL ()) ! 85: ! 86: ! 87: /* ! 88: * Here is a description of the per-CPU data we wish to record. ! 89: * ! 90: * In order to deal with lock-hierarchy assertions, we use a table of ! 91: * counters instead of maintaining a list of held locks. We do this because ! 92: * the nature of shared read/write locks permits even a single CPU to hold ! 93: * the same lock multiple times, and because while TRYLOCK () and UNLOCK () ! 94: * allow out-of-order acquisition and release we want LOCK () to rigidly ! 95: * check the hierarchy assertions. The array of counters is mostly O(1), a ! 96: * desirable property. ! 97: * ! 98: * While a trace of held locks is not unreasonable, it is difficult to set a ! 99: * fixed upper bound on the number of simultaneous locks. Even if we use a ! 100: * counter for multiple acquisitions of shared locks, we can potentially need ! 101: * as many trace records as allocated locks. ! 102: */ ! 103: ! 104: struct ddi_cpu_data { ! 105: /* ! 106: * Interrupt-related data is at the front of this structure for easy ! 107: * access by hand-coded assembly-language support routines. Same for ! 108: * the defer-table stuff. ! 109: */ ! 110: ! 111: processorid_t dc_cpuid; /* who are we for? */ ! 112: ! 113: intmask_t dc_base_mask; /* interrupt masks */ ! 114: unsigned char dc_int_level; /* processing interrupts */ ! 115: unsigned char dc_user_level; /* user level/kernel level */ ! 116: unsigned char dc_ipl; /* current ipl */ ! 117: ! 118: defer_t dc_defint; /* interrupt-deferred ops */ ! 119: defer_t dc_defproc; /* process-deferred ops */ ! 120: ! 121: __lkhier_t dc_max_hierarchy; /* ! 122: * For basic-lock hierarchy ! 123: * assertions ! 124: */ ! 125: __lkhier_t * dc_hierarchy_cnt; ! 126: ! 127: atomic_uchar_t dc_run_timeouts; /* run deferred timeouts */ ! 128: ! 129: struct pollwait * ! 130: dc_pollwait; /* task performing a poll */ ! 131: ! 132: char * dc_dynalloc; /* for getting per-cpu data */ ! 133: char * dc_dynend; /* end of free per-cpu data */ ! 134: }; ! 135: ! 136: typedef struct ddi_cpu_data dcdata_t; ! 137: ! 138: ! 139: ! 140: __EXTERN_C_BEGIN__ ! 141: ! 142: dcdata_t * ddi_cpu_data __PROTO ((void)); ! 143: ! 144: #if _DDI_DKI_IMPL ! 145: /* ! 146: * Functions for the implementation only. ! 147: */ ! 148: __VOID__ * ddi_cpu_alloc __PROTO ((__size_t _size)); ! 149: dcdata_t * ddi_cpu_ref __PROTO ((processorid_t _cpu)); ! 150: void ddi_cpu_unref __PROTO ((dcdata_t * _data)); ! 151: processorid_t ddi_cpu_id __PROTO ((void)); ! 152: ! 153: #endif ! 154: ! 155: __EXTERN_C_END__ ! 156: ! 157: ! 158: extern dcdata_t __ddi_cpu_data []; ! 159: ! 160: #define ddi_cpu_data() (__ddi_cpu_data) ! 161: ! 162: #endif /* ! defined (__KERNEL_DDI_CPU_H__) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.