|
|
1.1 root 1: #define _DDI_DKI 1
2: #define _DDI_DKI_IMPL 1
3: #define _SYSV4 1
4:
5: /*
6: *-IMPORTS:
7: * <common/ccompat.h>
8: * __USE_PROTO__
9: * __ARGS ()
10: * <sys/debug.h>
11: * ASSERT ()
12: * <kernel/ddi_cpu.h>
13: * dcdata_t
14: * ddi_cpu_data ()
15: * <kernel/ddi_glob.h>
16: * dgdata_t
17: * ddi_global_data ()
18: * <kernel/ddi_lock.h>
19: * defer_priority
20: * defer_hierarchy
21: * <sys/ksynch.h>
22: * LOCK ()
23: * UNLOCK ()
24: * <sys/cmn_err.h>
25: * CE_WARN
26: * cmn_err ()
27: * <sys/stdlib.h>
28: * NULL
29: */
30:
31: #include <common/ccompat.h>
32: #include <kernel/ddi_cpu.h>
33: #include <kernel/ddi_glob.h>
34: #include <kernel/ddi_lock.h>
35: #include <sys/debug.h>
36: #include <sys/ksynch.h>
37: #include <sys/cmn_err.h>
38: #include <stddef.h>
39:
40: #include <kernel/defer.h>
41:
42:
43: /*
44: * This internal function queues a deferred function on a deferred-function
45: * queue.
46: */
47:
48: #if __USE_PROTO__
49: __LOCAL__ int (DEFER) (defer_t * deferp, __deffuncp_t funcp)
50: #else
51: __LOCAL__ int
52: DEFER __ARGS ((deferp, funcp))
53: defer_t * deferp;
54: __deffuncp_t funcp;
55: #endif
56: {
57: pl_t prev_pl;
58: int idx;
59:
60: ASSERT (funcp != NULL);
61: ASSERT (deferp != NULL);
62: ASSERT (deferp->df_tab != NULL && deferp->df_max > 0);
63:
64: prev_pl = LOCK (deferp->df_wlock, defer_priority);
65:
66: /*
67: * Write the function pointer into the next free slot in the table,
68: * and then move the write pointer to the next entry in the circular
69: * buffer.
70: */
71:
72: idx = ATOMIC_FETCH_UCHAR (deferp->df_write);
73:
74: deferp->df_tab [idx ++] = funcp;
75:
76: if (idx == ATOMIC_FETCH_UCHAR (deferp->df_max))
77: idx = 0;
78:
79: /*
80: * If the write pointer bumps into the read pointer, then the defer
81: * table is full and we should complain. A possible alternative
82: * strategy would be to wait for the other processor, but that is only
83: * a good idea if we have the machinery to interrupt it available,
84: * which we currently do not.
85: */
86:
87: if (idx != ATOMIC_FETCH_UCHAR (deferp->df_read)) {
88: /*
89: * Store the updated write pointer and prepare to return
90: * success.
91: */
92:
93: ATOMIC_STORE_UCHAR (deferp->df_write, idx);
94: idx = 0;
95: } else {
96:
97: cmn_err (CE_WARN, "table overflow in DEFER ()");
98: idx = 1; /* flag failure to the caller */
99: }
100:
101: UNLOCK (deferp->df_wlock, prev_pl);
102:
103: return idx;
104: }
105:
106:
107: /*
108: *-STATUS:
109: * For the Implementors only.
110: *
111: *-NAME:
112: * defer_int_cpu Defer a routine on a specified CPU.
113: *
114: *-SYNOPSIS:
115: * #include <kernel/defer.h>
116: *
117: * int defer_int_cpu (void (* funcp) (void), processorid_t cpuid);
118: *
119: *-ARGUMENTS:
120: * funcp Pointer to the function to be executed upon the given
121: * processor's return from kernel execution to user-level
122: * execution.
123: *
124: * cpuid Processor on which "funcp" is to be executed.
125: *
126: *-DESCRIPTION:
127: * defer_int_cpu () requests that a function be executed on the given CPU
128: * at a priority higher than any user-level code. If the given CPU is
129: * currently executing kernel code, the function will be run before user-
130: * level execution is resumed. The routine is run at a priority lower
131: * than any interrupt-level code; if the implementation permits, the
132: * routine will be run at a priority higher than base kernel code, but
133: * this is not guaranteed.
134: *
135: * The implementation will make a best effort to ensure that the deferred
136: * function is executed promptly. However, some hardware configurations
137: * may not permit one CPU to interrupt another under software control, so
138: * if the specified CPU is currently running at user level it may not
139: * execute the deferred function for some time.
140: *
141: *-RETURN VALUE:
142: * 0 is returned on success. If the specified CPU is invalid, or the
143: * deferred-function table for the specified CPU is full, then a non-zero
144: * error value is returned.
145: *
146: *-LEVEL:
147: * Base or interrupt.
148: *
149: *-NOTES:
150: * Does not sleep.
151: *
152: * It is currently unspecified whether the function pointed to by "funcp"
153: * is permitted to contend for locks held by the caller.
154: */
155:
156: #if __USE_PROTO__
157: int (defer_int_cpu) (__deffuncp_t funcp, processorid_t cpuid)
158: #else
159: int
160: defer_int_cpu __ARGS ((funcp, cpuid))
161: __deffuncp_t funcp;
162: processorid_t cpuid;
163: #endif
164: {
165: dcdata_t * dcdatap;
166: int retval;
167:
168: ASSERT (funcp != NULL);
169:
170: if ((dcdatap = ddi_cpu_ref (cpuid)) == NULL)
171: return -1;
172:
173: retval = DEFER (& dcdatap->dc_defint, funcp);
174:
175: ddi_cpu_unref (dcdatap);
176: return retval;
177: }
178:
179:
180: /*
181: *-STATUS:
182: * For the Implementors only.
183: *
184: *-NAME:
185: * defer_int_any Defer a routine on an unspecified CPU.
186: *
187: *-SYNOPSIS:
188: * #include <kernel/defer.h>
189: *
190: * int defer_int_any (void (* funcp) (void));
191: *
192: *-ARGUMENTS:
193: * funcp Pointer to the function to be executed upon some
194: * processor's return from kernel execution to user-level
195: * execution.
196: *
197: *-DESCRIPTION:
198: * defer_int_any () requests that a function be executed at some future
199: * time convenient to the implementation. The routine will be run at a
200: * priority higher than any user-level code, and lower than any
201: * interrupt-level code; if the implementation permits, the function will
202: * be run at a priority higher than base kernel code, but this is not
203: * guaranteed.
204: *
205: * The function will be executed on the first CPU available. However, a
206: * typical implementation would not interrupt user-level execution on
207: * any other CPUs merely to run deferred functions.
208: *
209: *-RETURN VALUE:
210: * 0 is returned on success. If the global deferred-function table is
211: * full, then a non-zero error value is returned.
212: *
213: *-LEVEL:
214: * Base or interrupt.
215: *
216: *-NOTES:
217: * Does not sleep.
218: *
219: * It is currently unspecified whether the function pointed to by "funcp"
220: * is permitted to contend for locks held by the caller.
221: */
222:
223: #if __USE_PROTO__
224: int (defer_int_any) (__deffuncp_t funcp)
225: #else
226: int
227: defer_int_any __ARGS ((funcp))
228: __deffuncp_t funcp;
229: #endif
230: {
231: return DEFER (& ddi_global_data ()->dg_defint, funcp);
232: }
233:
234:
235: /*
236: *-STATUS:
237: * For the Implementors only.
238: *
239: *-NAME:
240: * defer_int_here Defer a routine on the current CPU.
241: *
242: *-SYNOPSIS:
243: * #include <kernel/defer.h>
244: *
245: * int defer_int_here (void (* funcp) (void));
246: *
247: *-ARGUMENTS:
248: * funcp Pointer to the function to be executed upon this
249: * processor's return from kernel execution to user-level
250: * execution.
251: *
252: *-DESCRIPTION:
253: * defer_int_here () requests that a function be executed at some future
254: * time convenient to the implementation on the current CPU. The routine
255: * will be run at a priority higher than any user-level code, and lower
256: * than any interrupt-level code; if the implementation permits, the
257: * function will run at a level higher than base kernel code, but this is
258: * not guaranteed.
259: *
260: *-RETURN VALUE:
261: * 0 is returned on success. If the current CPUs deferred-function table
262: * is full, then a non-zero error value is returned.
263: *
264: *-LEVEL:
265: * Base or interrupt.
266: *
267: *-NOTES:
268: * Does not sleep.
269: *
270: * It is currently unspecified whether the function pointed to by "funcp"
271: * is permitted to contend for locks held by the caller.
272: */
273:
274: #if __USE_PROTO__
275: int (defer_int_here) (__deffuncp_t funcp)
276: #else
277: int
278: defer_int_here __ARGS ((funcp))
279: __deffuncp_t funcp;
280: #endif
281: {
282: return DEFER (& ddi_cpu_data ()->dc_defint, funcp);
283: }
284:
285:
286: /*
287: *-STATUS:
288: * For the Implementors only.
289: *
290: *-NAME:
291: * defer_proc_cpu Defer a routine on a specified CPU.
292: *
293: *-SYNOPSIS:
294: * #include <kernel/defer.h>
295: *
296: * int defer_proc_cpu (void (* funcp) (void), processorid_t cpuid);
297: *
298: *-ARGUMENTS:
299: * funcp Pointer to the function to be executed upon the given
300: * processor's return from kernel execution to user-level
301: * execution.
302: *
303: * cpuid Processor on which "funcp" is to be executed.
304: *
305: *-DESCRIPTION:
306: * defer_proc_cpu () requests that a function be executed on the given CPU
307: * at a priority higher than any user-level code. If the given CPU is
308: * currently executing kernel code, the function will be run before user-
309: * level execution is resumed.
310: *
311: * The implementation will make a best effort to ensure that the deferred
312: * function is executed promptly. However, some hardware configurations
313: * may not permit one CPU to interrupt another under software control, so
314: * if the specified CPU is currently running at user level it may not
315: * execute the deferred function for some time.
316: *
317: *-RETURN VALUE:
318: * 0 is returned on success. If the specified CPU is invalid, or the
319: * deferred-function table for the specified CPU is full, then a non-zero
320: * error value is returned.
321: *
322: *-LEVEL:
323: * Base or interrupt.
324: *
325: *-NOTES:
326: * Does not sleep.
327: *
328: * It is currently unspecified whether the function pointed to by "funcp"
329: * is permitted to contend for locks held by the caller.
330: */
331:
332: #if __USE_PROTO__
333: int (defer_proc_cpu) (__deffuncp_t funcp, processorid_t cpuid)
334: #else
335: int
336: defer_proc_cpu __ARGS ((funcp, cpuid))
337: __deffuncp_t funcp;
338: processorid_t cpuid;
339: #endif
340: {
341: dcdata_t * dcdatap;
342: int retval;
343:
344: ASSERT (funcp != NULL);
345:
346: if ((dcdatap = ddi_cpu_ref (cpuid)) == NULL)
347: return -1;
348:
349: retval = DEFER (& dcdatap->dc_defproc, funcp);
350:
351: ddi_cpu_unref (dcdatap);
352: return retval;
353: }
354:
355:
356: /*
357: *-STATUS:
358: * For the Implementors only.
359: *
360: *-NAME:
361: * defer_proc_any Defer a routine on an unspecified CPU.
362: *
363: *-SYNOPSIS:
364: * #include <kernel/defer.h>
365: *
366: * int defer_proc_any (void (* funcp) (void));
367: *
368: *-ARGUMENTS:
369: * funcp Pointer to the function to be executed upon some
370: * processor's return from kernel execution to user-level
371: * execution.
372: *
373: *-DESCRIPTION:
374: * defer_proc_any () requests that a function be executed at some future
375: * time convenient to the implementation. The routine will be run at a
376: * priority higher than any user-level code, and lower than any
377: * interrupt-level code or kernel code.
378: *
379: * The function will be executed on the first CPU available. However, a
380: * typical implementation would not interrupt user-level execution on
381: * any other CPUs merely to run deferred functions.
382: *
383: *-RETURN VALUE:
384: * 0 is returned on success. If the global deferred-function table is
385: * full, then a non-zero error value is returned.
386: *
387: *-LEVEL:
388: * Base or interrupt.
389: *
390: *-NOTES:
391: * Does not sleep.
392: *
393: * It is currently unspecified whether the function pointed to by "funcp"
394: * is permitted to contend for locks held by the caller.
395: */
396:
397: #if __USE_PROTO__
398: int (defer_proc_any) (__deffuncp_t funcp)
399: #else
400: int
401: defer_proc_any __ARGS ((funcp))
402: __deffuncp_t funcp;
403: #endif
404: {
405: return DEFER (& ddi_global_data ()->dg_defproc, funcp);
406: }
407:
408:
409: /*
410: *-STATUS:
411: * For the Implementors only.
412: *
413: *-NAME:
414: * defer_proc_here Defer a routine on the current CPU.
415: *
416: *-SYNOPSIS:
417: * #include <kernel/defer.h>
418: *
419: * int defer_proc_here (void (* funcp) (void));
420: *
421: *-ARGUMENTS:
422: * funcp Pointer to the function to be executed upon this
423: * processor's return from kernel execution to user-level
424: * execution.
425: *
426: *-DESCRIPTION:
427: * defer_proc_here () requests that a function be executed at some futur
428: * time convenient to the implementation on the current CPU. The routine
429: * will be run at a priority higher than any user-level code, and lower
430: * than any interrupt-level code or kernel code.
431: *
432: *-RETURN VALUE:
433: * 0 is returned on success. If the current CPUs deferred-function table
434: * is full, then a non-zero error value is returned.
435: *
436: *-LEVEL:
437: * Base or interrupt.
438: *
439: *-NOTES:
440: * Does not sleep.
441: *
442: * It is currently unspecified whether the function pointed to by "funcp"
443: * is permitted to contend for locks held by the caller.
444: */
445:
446: #if __USE_PROTO__
447: int (defer_proc_here) (__deffuncp_t funcp)
448: #else
449: int
450: defer_proc_here __ARGS ((funcp))
451: __deffuncp_t funcp;
452: #endif
453: {
454: return DEFER (& ddi_cpu_data ()->dc_defproc, funcp);
455: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.