|
|
1.1 root 1: #ifndef __SYS_KSYNCH_H__
2: #define __SYS_KSYNCH_H__
3:
4: /*
5: * Support for basic locks.
6: */
7:
8: /*
9: *-IMPORTS:
10: * <common/ccompat.h>
11: * __EXTERN_C_BEGIN__
12: * __EXTERN_C_END__
13: * __VOID__
14: * __PROTO ()
15: * <kernel/_lock.h>
16: * __lock_t
17: * <kernel/x86lock.h>
18: * atomic_uchar_t
19: * <sys/types.h>
20: * bool_t
21: * pl_t
22: */
23:
24: #if _DDI_DKI
25:
26: #include <common/ccompat.h>
27: #include <kernel/_lock.h>
28: #include <kernel/x86lock.h>
29: #include <sys/types.h>
30:
31: /*
32: * We can provide a greater level of error checking/reporting if we know we
33: * are running on a uniprocessor. Use this feature-test macro to control
34: * compilation of code for uniprocessors.
35: *
36: * Note that many of the traditional simplifying assumptions about
37: * uniprocessor systems may not apply if basic-lock acquisition can schedule
38: * interrupt contexts (ie, if the system is designed such that interrupts
39: * need not be turned off). Such as system would behave effectively like a
40: * multiprocessor, although most of the extra checking could still be valid
41: * with information gained from the interrupt-handler scheduling system.
42: */
43:
44: #define __UNIPROCESSOR__
45:
46:
47: /*
48: * For greater scalability, a "ticket lock" should be preferred over a basic
49: * test-and-set or test-and-test-and-set spin lock, since it guarantees
50: * FIFO ordering and reduces the level of memory contention (important for
51: * multiprocessor shared-memory cache performance). See the paper cited at the
52: * top of this file for more details.
53: *
54: * However, ticket locks take slightly more memory and are slightly slower
55: * that basic test-and-set spin locks, so we only use them in situations
56: * where we expect them to be needed.
57: */
58:
59: #ifdef __UNIPROCESSOR__
60: #define __TICKET_LOCK__
61: #endif
62:
63:
64: /*
65: * Even if ticket locks are used, in the absence of a fetch-and-increment
66: * atomic operation a basic test-and-set style lock must be used to control
67: * the "ticket gate", so the style of test-and-set lock used will always have
68: * consequences. A simple test-and-set spin lock reduces delay, while a
69: * test-and-test-and-set spin reduces contention.
70: */
71:
72: #define __TEST_AND_TEST__
73:
74:
75: /*
76: * Information structure used for holding debugging information about
77: * lock structures.
78: */
79:
80: struct lock_info {
81: __CONST__ char * lk_name; /* name for statistics gathering */
82: int lk_flags; /* must be zero */
83: int lk_pad;
84: };
85:
86: typedef struct lock_info lkinfo_t;
87:
88:
89: /*
90: * No lock statistics structure is currently defined, but we reserve the name.
91: *
92: * For the other lock structures, we publish only their names, and leave the
93: * types incomplete.
94: */
95:
96: typedef __VOID__ lkstat_t;
97: typedef __lock_t lock_t;
98: typedef struct synch_var sv_t;
99: typedef struct sleep_lock sleep_t;
100: typedef struct readwrite_lock rwlock_t;
101:
102:
103: __EXTERN_C_BEGIN__
104:
105: /* Basic lock functions */
106:
107: pl_t LOCK __PROTO ((lock_t * _lockp, pl_t _pl));
108: lock_t * LOCK_ALLOC __PROTO ((__lkhier_t _hierarchy,
109: pl_t _min_pl, lkinfo_t * _lkinfop,
110: int _flag));
111: void LOCK_DEALLOC __PROTO ((lock_t * _lockp));
112: pl_t TRYLOCK __PROTO ((lock_t * _lockp, pl_t _pl));
113: void UNLOCK __PROTO ((lock_t * _lockp, pl_t _pl));
114:
115:
116: /* Synchronisation variable functions */
117:
118: sv_t * SV_ALLOC __PROTO ((int _flag));
119: void SV_BROADCAST __PROTO ((sv_t * _svp, int _flags));
120: void SV_DEALLOC __PROTO ((sv_t * _svp));
121: void SV_SIGNAL __PROTO ((sv_t * _svp, int _flags));
122: void SV_WAIT __PROTO ((sv_t * _svp, int _priority,
123: lock_t * _lkp));
124: bool_t SV_WAIT_SIG __PROTO ((sv_t * _svp, int _priority,
125: lock_t * _lkp));
126:
127:
128: /* Sleep locks */
129:
130: sleep_t * SLEEP_ALLOC __PROTO ((int _arg, lkinfo_t * _lkinfop,
131: int _flag));
132: void SLEEP_DEALLOC __PROTO ((sleep_t * _lockp));
133: void SLEEP_LOCK __PROTO ((sleep_t * _lockp, int _priority));
134: bool_t SLEEP_LOCKAVAIL __PROTO ((sleep_t * _lockp));
135: bool_t SLEEP_LOCKOWNED __PROTO ((sleep_t * _lockp));
136: bool_t SLEEP_LOCK_SIG __PROTO ((sleep_t * _lockp, int _priority));
137: bool_t SLEEP_TRYLOCK __PROTO ((sleep_t * _lockp));
138: void SLEEP_UNLOCK __PROTO ((sleep_t * _lockp));
139:
140:
141: /* Read/write locks */
142:
143: rwlock_t * RW_ALLOC __PROTO ((__lkhier_t _hierarchy,
144: pl_t _min_pl, lkinfo_t * _lkinfop,
145: int _flag));
146: void RW_DEALLOC __PROTO ((rwlock_t * _lockp));
147: pl_t RW_RDLOCK __PROTO ((rwlock_t * _lockp, pl_t _pl));
148: pl_t RW_TRYRDLOCK __PROTO ((rwlock_t * _lockp, pl_t _pl));
149: pl_t RW_TRYWRLOCK __PROTO ((rwlock_t * _lockp, pl_t _pl));
150: void RW_UNLOCK __PROTO ((rwlock_t * _lockp, pl_t _pl));
151: pl_t RW_WRLOCK __PROTO ((rwlock_t * _lockp, pl_t _pl));
152:
153: __EXTERN_C_END__
154:
155: #endif /* _DDI_DKI */
156:
157: /*
158: * This type is used in the old Coherent source as a primitive form of sleep
159: * lock. It should go ASAP, but there's a limit to how much people will let
160: * me get away with changing... this type is used in a structure which cannot
161: * alter because the "configuration" mechanism for Coherent kernels is to
162: * stuff values into the linked object file, in particular the device switch
163: * table!
164: */
165:
166: #if ! _I386
167:
168: typedef unsigned char GATE [2];
169:
170: #else /* if _I386 */
171:
172: typedef struct {
173: unsigned char _lock [2];
174: unsigned _count;
175: char * _name;
176: } GATE [1];
177:
178: #define __GATE_INIT(g, name) ((g)->_lock [1] = (g)->_lock [0] = 0, \
179: (g)->_name = (name), (g)->_count = 0)
180: #define __GATE_LOCK_COUNT(g) ((g)->_count ++)
181: #define __GATE_LOCKED(gate) ((gate)->_lock [0])
182:
183: #endif /* ! _I386 */
184:
185: #endif /* ! defined (__SYS_KSYNCH_H__) */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.