139 140#define FREQ2BT(freq, bt) \ 141{ \ 142 (bt)->sec = 0; \ 143 (bt)->frac = ((uint64_t)0x8000000000000000 / (freq)) << 1; \ 144} 145#define BT2FREQ(bt) \ 146 (((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) / \ 147 ((bt)->frac >> 1)) 148 149/* 150 * Timer broadcast IPI handler. 151 */ 152int 153hardclockintr(void) 154{ 155 struct bintime now; 156 struct pcpu_state *state; 157 int done; 158 159 if (doconfigtimer() || busy) 160 return (FILTER_HANDLED); 161 state = DPCPU_PTR(timerstate); 162 now = state->now; 163 CTR4(KTR_SPARE2, "ipi at %d: now %d.%08x%08x", 164 curcpu, now.sec, (unsigned int)(now.frac >> 32), 165 (unsigned int)(now.frac & 0xffffffff)); 166 done = handleevents(&now, 0); 167 return (done ? FILTER_HANDLED : FILTER_STRAY); 168} 169 170/* 171 * Handle all events for specified time on this CPU 172 */ 173static int 174handleevents(struct bintime *now, int fake) 175{ 176 struct bintime t; 177 struct trapframe *frame; 178 struct pcpu_state *state; 179 uintfptr_t pc; 180 int usermode; 181 int done, runs; 182 183 CTR4(KTR_SPARE2, "handle at %d: now %d.%08x%08x", 184 curcpu, now->sec, (unsigned int)(now->frac >> 32), 185 (unsigned int)(now->frac & 0xffffffff)); 186 done = 0; 187 if (fake) { 188 frame = NULL; 189 usermode = 0; 190 pc = 0; 191 } else { 192 frame = curthread->td_intr_frame; 193 usermode = TRAPF_USERMODE(frame); 194 pc = TRAPF_PC(frame); 195 } 196#ifdef KDTRACE_HOOKS 197 /* 198 * If the DTrace hooks are configured and a callback function 199 * has been registered, then call it to process the high speed 200 * timers. 201 */ 202 if (!fake && cyclic_clock_func[curcpu] != NULL) 203 (*cyclic_clock_func[curcpu])(frame); 204#endif 205 runs = 0; 206 state = DPCPU_PTR(timerstate); 207 while (bintime_cmp(now, &state->nexthard, >=)) { 208 bintime_add(&state->nexthard, &hardperiod); 209 runs++; 210 } 211 if (runs && fake < 2) { 212 hardclock_anycpu(runs, usermode); 213 done = 1; 214 } 215 while (bintime_cmp(now, &state->nextstat, >=)) { 216 if (fake < 2) 217 statclock(usermode); 218 bintime_add(&state->nextstat, &statperiod); 219 done = 1; 220 } 221 if (profiling) { 222 while (bintime_cmp(now, &state->nextprof, >=)) { 223 if (!fake) 224 profclock(usermode, pc); 225 bintime_add(&state->nextprof, &profperiod); 226 done = 1; 227 } 228 } else 229 state->nextprof = state->nextstat; 230 getnextcpuevent(&t, 0); 231 if (fake == 2) { 232 state->nextevent = t; 233 return (done); 234 } 235 ET_HW_LOCK(state); 236 if (!busy) { 237 state->idle = 0; 238 state->nextevent = t; 239 loadtimer(now, 0); 240 } 241 ET_HW_UNLOCK(state); 242 return (done); 243} 244 245/* 246 * Schedule binuptime of the next event on current CPU. 247 */ 248static void 249getnextcpuevent(struct bintime *event, int idle) 250{ 251 struct bintime tmp; 252 struct pcpu_state *state; 253 int skip; 254 255 state = DPCPU_PTR(timerstate); 256 *event = state->nexthard; 257 if (idle) { /* If CPU is idle - ask callouts for how long. */ 258 skip = 4; 259 if (curcpu == CPU_FIRST() && tc_min_ticktock_freq > skip) 260 skip = tc_min_ticktock_freq; 261 skip = callout_tickstofirst(hz / skip) - 1; 262 CTR2(KTR_SPARE2, "skip at %d: %d", curcpu, skip); 263 tmp = hardperiod; 264 bintime_mul(&tmp, skip); 265 bintime_add(event, &tmp); 266 } else { /* If CPU is active - handle all types of events. */ 267 if (bintime_cmp(event, &state->nextstat, >)) 268 *event = state->nextstat; 269 if (profiling && 270 bintime_cmp(event, &state->nextprof, >)) 271 *event = state->nextprof; 272 } 273} 274 275/* 276 * Schedule binuptime of the next event on all CPUs. 277 */ 278static void 279getnextevent(struct bintime *event) 280{ 281 struct pcpu_state *state; 282#ifdef SMP 283 int cpu; 284#endif 285 int c; 286 287 state = DPCPU_PTR(timerstate); 288 *event = state->nextevent; 289 c = curcpu; 290#ifdef SMP 291 if ((timer->et_flags & ET_FLAGS_PERCPU) == 0) { 292 CPU_FOREACH(cpu) { 293 if (curcpu == cpu) 294 continue; 295 state = DPCPU_ID_PTR(cpu, timerstate); 296 if (bintime_cmp(event, &state->nextevent, >)) { 297 *event = state->nextevent; 298 c = cpu; 299 } 300 } 301 } 302#endif 303 CTR5(KTR_SPARE2, "next at %d: next %d.%08x%08x by %d", 304 curcpu, event->sec, (unsigned int)(event->frac >> 32), 305 (unsigned int)(event->frac & 0xffffffff), c); 306} 307 308/* Hardware timer callback function. */ 309static void 310timercb(struct eventtimer *et, void *arg) 311{ 312 struct bintime now; 313 struct bintime *next; 314 struct pcpu_state *state; 315#ifdef SMP 316 int cpu, bcast; 317#endif 318 319 /* Do not touch anything if somebody reconfiguring timers. */ 320 if (busy) 321 return; 322 /* Update present and next tick times. */ 323 state = DPCPU_PTR(timerstate); 324 if (et->et_flags & ET_FLAGS_PERCPU) { 325 next = &state->nexttick; 326 } else 327 next = &nexttick; 328 if (periodic) { 329 now = *next; /* Ex-next tick time becomes present time. */ 330 bintime_add(next, &timerperiod); /* Next tick in 1 period. */ 331 } else { 332 binuptime(&now); /* Get present time from hardware. */ 333 next->sec = -1; /* Next tick is not scheduled yet. */ 334 } 335 state->now = now; 336 CTR4(KTR_SPARE2, "intr at %d: now %d.%08x%08x", 337 curcpu, now.sec, (unsigned int)(now.frac >> 32), 338 (unsigned int)(now.frac & 0xffffffff)); 339 340#ifdef SMP 341 /* Prepare broadcasting to other CPUs for non-per-CPU timers. */ 342 bcast = 0; 343 if ((et->et_flags & ET_FLAGS_PERCPU) == 0 && smp_started) { 344 CPU_FOREACH(cpu) { 345 state = DPCPU_ID_PTR(cpu, timerstate); 346 ET_HW_LOCK(state); 347 state->now = now; 348 if (bintime_cmp(&now, &state->nextevent, >=)) { 349 state->nextevent.sec++; 350 if (curcpu != cpu) { 351 state->ipi = 1; 352 bcast = 1; 353 } 354 } 355 ET_HW_UNLOCK(state); 356 } 357 } 358#endif 359 360 /* Handle events for this time on this CPU. */ 361 handleevents(&now, 0); 362 363#ifdef SMP 364 /* Broadcast interrupt to other CPUs for non-per-CPU timers. */ 365 if (bcast) { 366 CPU_FOREACH(cpu) { 367 if (curcpu == cpu) 368 continue; 369 state = DPCPU_ID_PTR(cpu, timerstate); 370 if (state->ipi) { 371 state->ipi = 0; 372 ipi_cpu(cpu, IPI_HARDCLOCK); 373 } 374 } 375 } 376#endif 377} 378 379/* 380 * Load new value into hardware timer. 381 */ 382static void 383loadtimer(struct bintime *now, int start) 384{ 385 struct pcpu_state *state; 386 struct bintime new; 387 struct bintime *next; 388 uint64_t tmp; 389 int eq; 390 391 if (timer->et_flags & ET_FLAGS_PERCPU) { 392 state = DPCPU_PTR(timerstate); 393 next = &state->nexttick; 394 } else 395 next = &nexttick; 396 if (periodic) { 397 if (start) { 398 /* 399 * Try to start all periodic timers aligned 400 * to period to make events synchronous. 401 */ 402 tmp = ((uint64_t)now->sec << 36) + (now->frac >> 28); 403 tmp = (tmp % (timerperiod.frac >> 28)) << 28; 404 new.sec = 0; 405 new.frac = timerperiod.frac - tmp; 406 if (new.frac < tmp) /* Left less then passed. */ 407 bintime_add(&new, &timerperiod); 408 CTR5(KTR_SPARE2, "load p at %d: now %d.%08x first in %d.%08x", 409 curcpu, now->sec, (unsigned int)(now->frac >> 32), 410 new.sec, (unsigned int)(new.frac >> 32)); 411 *next = new; 412 bintime_add(next, now); 413 et_start(timer, &new, &timerperiod); 414 } 415 } else { 416 getnextevent(&new); 417 eq = bintime_cmp(&new, next, ==); 418 CTR5(KTR_SPARE2, "load at %d: next %d.%08x%08x eq %d", 419 curcpu, new.sec, (unsigned int)(new.frac >> 32), 420 (unsigned int)(new.frac & 0xffffffff), 421 eq); 422 if (!eq) { 423 *next = new; 424 bintime_sub(&new, now); 425 et_start(timer, &new, NULL); 426 } 427 } 428} 429 430/* 431 * Prepare event timer parameters after configuration changes. 432 */ 433static void 434setuptimer(void) 435{ 436 int freq; 437 438 if (periodic && (timer->et_flags & ET_FLAGS_PERIODIC) == 0) 439 periodic = 0; 440 else if (!periodic && (timer->et_flags & ET_FLAGS_ONESHOT) == 0) 441 periodic = 1; 442 singlemul = MIN(MAX(singlemul, 1), 20); 443 freq = hz * singlemul; 444 while (freq < (profiling ? profhz : stathz)) 445 freq += hz; 446 freq = round_freq(timer, freq); 447 FREQ2BT(freq, &timerperiod); 448} 449 450/* 451 * Reconfigure specified per-CPU timer on other CPU. Called from IPI handler. 452 */ 453static int 454doconfigtimer(void) 455{ 456 struct bintime now; 457 struct pcpu_state *state; 458 459 state = DPCPU_PTR(timerstate); 460 switch (atomic_load_acq_int(&state->action)) { 461 case 1: 462 binuptime(&now); 463 ET_HW_LOCK(state); 464 loadtimer(&now, 1); 465 ET_HW_UNLOCK(state); 466 state->handle = 0; 467 atomic_store_rel_int(&state->action, 0); 468 return (1); 469 case 2: 470 ET_HW_LOCK(state); 471 et_stop(timer); 472 ET_HW_UNLOCK(state); 473 state->handle = 0; 474 atomic_store_rel_int(&state->action, 0); 475 return (1); 476 } 477 if (atomic_readandclear_int(&state->handle) && !busy) { 478 binuptime(&now); 479 handleevents(&now, 0); 480 return (1); 481 } 482 return (0); 483} 484 485/* 486 * Reconfigure specified timer. 487 * For per-CPU timers use IPI to make other CPUs to reconfigure. 488 */ 489static void 490configtimer(int start) 491{ 492 struct bintime now, next; 493 struct pcpu_state *state; 494 int cpu; 495 496 if (start) { 497 setuptimer(); 498 binuptime(&now); 499 } 500 critical_enter(); 501 ET_HW_LOCK(DPCPU_PTR(timerstate)); 502 if (start) { 503 /* Initialize time machine parameters. */ 504 next = now; 505 bintime_add(&next, &timerperiod); 506 if (periodic) 507 nexttick = next; 508 else 509 nexttick.sec = -1; 510 CPU_FOREACH(cpu) { 511 state = DPCPU_ID_PTR(cpu, timerstate); 512 state->now = now; 513 state->nextevent = next; 514 if (periodic) 515 state->nexttick = next; 516 else 517 state->nexttick.sec = -1; 518 state->nexthard = next; 519 state->nextstat = next; 520 state->nextprof = next; 521 hardclock_sync(cpu); 522 } 523 busy = 0; 524 /* Start global timer or per-CPU timer of this CPU. */ 525 loadtimer(&now, 1); 526 } else { 527 busy = 1; 528 /* Stop global timer or per-CPU timer of this CPU. */ 529 et_stop(timer); 530 } 531 ET_HW_UNLOCK(DPCPU_PTR(timerstate)); 532#ifdef SMP 533 /* If timer is global or there is no other CPUs yet - we are done. */ 534 if ((timer->et_flags & ET_FLAGS_PERCPU) == 0 || !smp_started) { 535 critical_exit(); 536 return; 537 } 538 /* Set reconfigure flags for other CPUs. */ 539 CPU_FOREACH(cpu) { 540 state = DPCPU_ID_PTR(cpu, timerstate); 541 atomic_store_rel_int(&state->action, 542 (cpu == curcpu) ? 0 : ( start ? 1 : 2)); 543 } 544 /* Broadcast reconfigure IPI. */ 545 ipi_all_but_self(IPI_HARDCLOCK); 546 /* Wait for reconfiguration completed. */ 547restart: 548 cpu_spinwait(); 549 CPU_FOREACH(cpu) { 550 if (cpu == curcpu) 551 continue; 552 state = DPCPU_ID_PTR(cpu, timerstate); 553 if (atomic_load_acq_int(&state->action)) 554 goto restart; 555 } 556#endif 557 critical_exit(); 558} 559 560/* 561 * Calculate nearest frequency supported by hardware timer. 562 */ 563static int 564round_freq(struct eventtimer *et, int freq) 565{ 566 uint64_t div; 567 568 if (et->et_frequency != 0) { 569 div = lmax((et->et_frequency + freq / 2) / freq, 1); 570 if (et->et_flags & ET_FLAGS_POW2DIV) 571 div = 1 << (flsl(div + div / 2) - 1); 572 freq = (et->et_frequency + div / 2) / div; 573 } 574 if (et->et_min_period.sec > 0) 575 freq = 0; 576 else if (et->et_min_period.frac != 0) 577 freq = min(freq, BT2FREQ(&et->et_min_period)); 578 if (et->et_max_period.sec == 0 && et->et_max_period.frac != 0) 579 freq = max(freq, BT2FREQ(&et->et_max_period)); 580 return (freq); 581} 582 583/* 584 * Configure and start event timers (BSP part). 585 */ 586void 587cpu_initclocks_bsp(void) 588{ 589 struct pcpu_state *state; 590 int base, div, cpu; 591 592 mtx_init(&et_hw_mtx, "et_hw_mtx", NULL, MTX_SPIN); 593 CPU_FOREACH(cpu) { 594 state = DPCPU_ID_PTR(cpu, timerstate); 595 mtx_init(&state->et_hw_mtx, "et_hw_mtx", NULL, MTX_SPIN); 596 } 597#ifdef SMP 598 callout_new_inserted = cpu_new_callout; 599#endif 600 periodic = want_periodic; 601 /* Grab requested timer or the best of present. */ 602 if (timername[0]) 603 timer = et_find(timername, 0, 0); 604 if (timer == NULL && periodic) { 605 timer = et_find(NULL, 606 ET_FLAGS_PERIODIC, ET_FLAGS_PERIODIC); 607 } 608 if (timer == NULL) { 609 timer = et_find(NULL, 610 ET_FLAGS_ONESHOT, ET_FLAGS_ONESHOT); 611 } 612 if (timer == NULL && !periodic) { 613 timer = et_find(NULL, 614 ET_FLAGS_PERIODIC, ET_FLAGS_PERIODIC); 615 } 616 if (timer == NULL) 617 panic("No usable event timer found!"); 618 et_init(timer, timercb, NULL, NULL); 619 620 /* Adapt to timer capabilities. */ 621 if (periodic && (timer->et_flags & ET_FLAGS_PERIODIC) == 0) 622 periodic = 0; 623 else if (!periodic && (timer->et_flags & ET_FLAGS_ONESHOT) == 0) 624 periodic = 1; 625 if (timer->et_flags & ET_FLAGS_C3STOP) 626 cpu_disable_deep_sleep++; 627 628 /* 629 * We honor the requested 'hz' value. 630 * We want to run stathz in the neighborhood of 128hz. 631 * We would like profhz to run as often as possible. 632 */ 633 if (singlemul <= 0 || singlemul > 20) { 634 if (hz >= 1500 || (hz % 128) == 0) 635 singlemul = 1; 636 else if (hz >= 750) 637 singlemul = 2; 638 else 639 singlemul = 4; 640 } 641 if (periodic) { 642 base = round_freq(timer, hz * singlemul); 643 singlemul = max((base + hz / 2) / hz, 1); 644 hz = (base + singlemul / 2) / singlemul; 645 if (base <= 128) 646 stathz = base; 647 else { 648 div = base / 128; 649 if (div >= singlemul && (div % singlemul) == 0) 650 div++; 651 stathz = base / div; 652 } 653 profhz = stathz; 654 while ((profhz + stathz) <= 128 * 64) 655 profhz += stathz; 656 profhz = round_freq(timer, profhz); 657 } else { 658 hz = round_freq(timer, hz); 659 stathz = round_freq(timer, 127); 660 profhz = round_freq(timer, stathz * 64); 661 } 662 tick = 1000000 / hz; 663 FREQ2BT(hz, &hardperiod); 664 FREQ2BT(stathz, &statperiod); 665 FREQ2BT(profhz, &profperiod); 666 ET_LOCK(); 667 configtimer(1); 668 ET_UNLOCK(); 669} 670 671/* 672 * Start per-CPU event timers on APs. 673 */ 674void 675cpu_initclocks_ap(void) 676{ 677 struct bintime now; 678 struct pcpu_state *state; 679 680 state = DPCPU_PTR(timerstate); 681 binuptime(&now); 682 ET_HW_LOCK(state); 683 if ((timer->et_flags & ET_FLAGS_PERCPU) == 0 && periodic) { 684 state->now = nexttick; 685 bintime_sub(&state->now, &timerperiod); 686 } else 687 state->now = now; 688 hardclock_sync(curcpu); 689 handleevents(&state->now, 2); 690 if (timer->et_flags & ET_FLAGS_PERCPU) 691 loadtimer(&now, 1); 692 ET_HW_UNLOCK(state); 693} 694 695/* 696 * Switch to profiling clock rates. 697 */ 698void 699cpu_startprofclock(void) 700{ 701 702 ET_LOCK(); 703 if (periodic) { 704 configtimer(0); 705 profiling = 1; 706 configtimer(1); 707 } else 708 profiling = 1; 709 ET_UNLOCK(); 710} 711 712/* 713 * Switch to regular clock rates. 714 */ 715void 716cpu_stopprofclock(void) 717{ 718 719 ET_LOCK(); 720 if (periodic) { 721 configtimer(0); 722 profiling = 0; 723 configtimer(1); 724 } else 725 profiling = 0; 726 ET_UNLOCK(); 727} 728 729/* 730 * Switch to idle mode (all ticks handled). 731 */ 732void 733cpu_idleclock(void) 734{ 735 struct bintime now, t; 736 struct pcpu_state *state; 737 738 if (idletick || busy || 739 (periodic && (timer->et_flags & ET_FLAGS_PERCPU)) 740#ifdef DEVICE_POLLING 741 || curcpu == CPU_FIRST() 742#endif 743 ) 744 return; 745 state = DPCPU_PTR(timerstate); 746 if (periodic) 747 now = state->now; 748 else 749 binuptime(&now); 750 CTR4(KTR_SPARE2, "idle at %d: now %d.%08x%08x", 751 curcpu, now.sec, (unsigned int)(now.frac >> 32), 752 (unsigned int)(now.frac & 0xffffffff)); 753 getnextcpuevent(&t, 1); 754 ET_HW_LOCK(state); 755 state->idle = 1; 756 state->nextevent = t; 757 if (!periodic) 758 loadtimer(&now, 0); 759 ET_HW_UNLOCK(state); 760} 761 762/* 763 * Switch to active mode (skip empty ticks). 764 */ 765void 766cpu_activeclock(void) 767{ 768 struct bintime now; 769 struct pcpu_state *state; 770 struct thread *td; 771 772 state = DPCPU_PTR(timerstate); 773 if (state->idle == 0 || busy) 774 return; 775 if (periodic) 776 now = state->now; 777 else 778 binuptime(&now); 779 CTR4(KTR_SPARE2, "active at %d: now %d.%08x%08x", 780 curcpu, now.sec, (unsigned int)(now.frac >> 32), 781 (unsigned int)(now.frac & 0xffffffff)); 782 spinlock_enter(); 783 td = curthread; 784 td->td_intr_nesting_level++; 785 handleevents(&now, 1); 786 td->td_intr_nesting_level--; 787 spinlock_exit(); 788} 789 790#ifdef SMP 791static void 792cpu_new_callout(int cpu, int ticks) 793{ 794 struct bintime tmp; 795 struct pcpu_state *state; 796 797 CTR3(KTR_SPARE2, "new co at %d: on %d in %d", 798 curcpu, cpu, ticks); 799 state = DPCPU_ID_PTR(cpu, timerstate); 800 ET_HW_LOCK(state); 801 if (state->idle == 0 || busy) { 802 ET_HW_UNLOCK(state); 803 return; 804 } 805 /* 806 * If timer is periodic - just update next event time for target CPU. 807 * If timer is global - there is chance it is already programmed. 808 */ 809 if (periodic || (timer->et_flags & ET_FLAGS_PERCPU) == 0) { 810 state->nextevent = state->nexthard; 811 tmp = hardperiod; 812 bintime_mul(&tmp, ticks - 1); 813 bintime_add(&state->nextevent, &tmp); 814 if (periodic || 815 bintime_cmp(&state->nextevent, &nexttick, >=)) { 816 ET_HW_UNLOCK(state); 817 return; 818 } 819 } 820 /* 821 * Otherwise we have to wake that CPU up, as we can't get present 822 * bintime to reprogram global timer from here. If timer is per-CPU, 823 * we by definition can't do it from here. 824 */ 825 ET_HW_UNLOCK(state); 826 if (timer->et_flags & ET_FLAGS_PERCPU) { 827 state->handle = 1; 828 ipi_cpu(cpu, IPI_HARDCLOCK); 829 } else { 830 if (!cpu_idle_wakeup(cpu)) 831 ipi_cpu(cpu, IPI_AST); 832 } 833} 834#endif 835 836/* 837 * Report or change the active event timers hardware. 838 */ 839static int 840sysctl_kern_eventtimer_timer(SYSCTL_HANDLER_ARGS) 841{ 842 char buf[32]; 843 struct eventtimer *et; 844 int error; 845 846 ET_LOCK(); 847 et = timer; 848 snprintf(buf, sizeof(buf), "%s", et->et_name); 849 ET_UNLOCK(); 850 error = sysctl_handle_string(oidp, buf, sizeof(buf), req); 851 ET_LOCK(); 852 et = timer; 853 if (error != 0 || req->newptr == NULL || 854 strcasecmp(buf, et->et_name) == 0) { 855 ET_UNLOCK(); 856 return (error); 857 } 858 et = et_find(buf, 0, 0); 859 if (et == NULL) { 860 ET_UNLOCK(); 861 return (ENOENT); 862 } 863 configtimer(0); 864 et_free(timer); 865 if (et->et_flags & ET_FLAGS_C3STOP) 866 cpu_disable_deep_sleep++; 867 if (timer->et_flags & ET_FLAGS_C3STOP) 868 cpu_disable_deep_sleep--; 869 periodic = want_periodic; 870 timer = et; 871 et_init(timer, timercb, NULL, NULL); 872 configtimer(1); 873 ET_UNLOCK(); 874 return (error); 875} 876SYSCTL_PROC(_kern_eventtimer, OID_AUTO, timer, 877 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 878 0, 0, sysctl_kern_eventtimer_timer, "A", "Chosen event timer"); 879 880/* 881 * Report or change the active event timer periodicity. 882 */ 883static int 884sysctl_kern_eventtimer_periodic(SYSCTL_HANDLER_ARGS) 885{ 886 int error, val; 887 888 val = periodic; 889 error = sysctl_handle_int(oidp, &val, 0, req); 890 if (error != 0 || req->newptr == NULL) 891 return (error); 892 ET_LOCK(); 893 configtimer(0); 894 periodic = want_periodic = val; 895 configtimer(1); 896 ET_UNLOCK(); 897 return (error); 898} 899SYSCTL_PROC(_kern_eventtimer, OID_AUTO, periodic, 900 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 901 0, 0, sysctl_kern_eventtimer_periodic, "I", "Enable event timer periodic mode"); 902 903#endif
|