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