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