|
|
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.