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