Print this page
OS-2366 ddi_periodic_add(9F) is entirely rubbish (MORE)
OS-2366 ddi_periodic_add(9F) is entirely rubbish


   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  22 /*        All Rights Reserved   */
  23 
  24 /*
  25  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  26  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
  27  */
  28 
  29 #include <sys/param.h>
  30 #include <sys/t_lock.h>
  31 #include <sys/types.h>
  32 #include <sys/tuneable.h>
  33 #include <sys/sysmacros.h>
  34 #include <sys/systm.h>
  35 #include <sys/cpuvar.h>
  36 #include <sys/lgrp.h>
  37 #include <sys/user.h>
  38 #include <sys/proc.h>
  39 #include <sys/callo.h>
  40 #include <sys/kmem.h>
  41 #include <sys/var.h>
  42 #include <sys/cmn_err.h>
  43 #include <sys/swap.h>
  44 #include <sys/vmsystm.h>
  45 #include <sys/class.h>
  46 #include <sys/time.h>
  47 #include <sys/debug.h>
  48 #include <sys/vtrace.h>
  49 #include <sys/spl.h>
  50 #include <sys/atomic.h>
  51 #include <sys/dumphdr.h>
  52 #include <sys/archsystm.h>
  53 #include <sys/fs/swapnode.h>
  54 #include <sys/panic.h>
  55 #include <sys/disp.h>
  56 #include <sys/msacct.h>
  57 #include <sys/mem_cage.h>
  58 
  59 #include <vm/page.h>
  60 #include <vm/anon.h>
  61 #include <vm/rm.h>
  62 #include <sys/cyclic.h>
  63 #include <sys/cpupart.h>
  64 #include <sys/rctl.h>
  65 #include <sys/task.h>
  66 #include <sys/sdt.h>
  67 #include <sys/ddi_timer.h>
  68 #include <sys/random.h>
  69 #include <sys/modctl.h>
  70 #include <sys/zone.h>
  71 
  72 /*
  73  * for NTP support
  74  */
  75 #include <sys/timex.h>
  76 #include <sys/inttypes.h>
  77 
  78 #include <sys/sunddi.h>
  79 #include <sys/clock_impl.h>
  80 
  81 /*
  82  * clock() is called straight from the clock cyclic; see clock_init().
  83  *
  84  * Functions:
  85  *      reprime clock
  86  *      maintain date
  87  *      jab the scheduler


 299 /*
 300  * Cache aligned, per CPU structure with lbolt usage statistics.
 301  */
 302 static lbolt_cpu_t *lb_cpu;
 303 
 304 /*
 305  * Single, cache aligned, structure with all the information required by
 306  * the lbolt implementation.
 307  */
 308 lbolt_info_t *lb_info;
 309 
 310 
 311 int one_sec = 1; /* turned on once every second */
 312 static int fsflushcnt;  /* counter for t_fsflushr */
 313 int     dosynctodr = 1; /* patchable; enable/disable sync to TOD chip */
 314 int     tod_needsync = 0;       /* need to sync tod chip with software time */
 315 static int tod_broken = 0;      /* clock chip doesn't work */
 316 time_t  boot_time = 0;          /* Boot time in seconds since 1970 */
 317 cyclic_id_t clock_cyclic;       /* clock()'s cyclic_id */
 318 cyclic_id_t deadman_cyclic;     /* deadman()'s cyclic_id */
 319 cyclic_id_t ddi_timer_cyclic;   /* cyclic_timer()'s cyclic_id */
 320 
 321 extern void     clock_tick_schedule(int);
 322 
 323 static int lgrp_ticks;          /* counter to schedule lgrp load calcs */
 324 
 325 /*
 326  * for tod fault detection
 327  */
 328 #define TOD_REF_FREQ            ((longlong_t)(NANOSEC))
 329 #define TOD_STALL_THRESHOLD     (TOD_REF_FREQ * 3 / 2)
 330 #define TOD_JUMP_THRESHOLD      (TOD_REF_FREQ / 2)
 331 #define TOD_FILTER_N            4
 332 #define TOD_FILTER_SETTLE       (4 * TOD_FILTER_N)
 333 static int tod_faulted = TOD_NOFAULT;
 334 
 335 static int tod_status_flag = 0;         /* used by tod_validate() */
 336 
 337 static hrtime_t prev_set_tick = 0;      /* gethrtime() prior to tod_set() */
 338 static time_t prev_set_tod = 0;         /* tv_sec value passed to tod_set() */
 339 


 930          */
 931         if (wake_sched) {
 932                 t = &t0;
 933                 thread_lock(t);
 934                 if (t->t_state == TS_STOPPED) {
 935                         runin = runout = 0;
 936                         wake_sched = 0;
 937                         t->t_whystop = 0;
 938                         t->t_whatstop = 0;
 939                         t->t_schedflag &= ~TS_ALLSTART;
 940                         THREAD_TRANSITION(t);
 941                         setfrontdq(t);
 942                 }
 943                 thread_unlock(t);
 944         }
 945 }
 946 
 947 void
 948 clock_init(void)
 949 {
 950         cyc_handler_t clk_hdlr, timer_hdlr, lbolt_hdlr;
 951         cyc_time_t clk_when, lbolt_when;
 952         int i, sz;
 953         intptr_t buf;
 954 
 955         /*
 956          * Setup handler and timer for the clock cyclic.
 957          */
 958         clk_hdlr.cyh_func = (cyc_func_t)clock;
 959         clk_hdlr.cyh_level = CY_LOCK_LEVEL;
 960         clk_hdlr.cyh_arg = NULL;
 961 
 962         clk_when.cyt_when = 0;
 963         clk_when.cyt_interval = nsec_per_tick;
 964 
 965         /*
 966          * cyclic_timer is dedicated to the ddi interface, which
 967          * uses the same clock resolution as the system one.
 968          */
 969         timer_hdlr.cyh_func = (cyc_func_t)cyclic_timer;
 970         timer_hdlr.cyh_level = CY_LOCK_LEVEL;
 971         timer_hdlr.cyh_arg = NULL;
 972 
 973         /*
 974          * The lbolt cyclic will be reprogramed to fire at a nsec_per_tick
 975          * interval to satisfy performance needs of the DDI lbolt consumers.
 976          * It is off by default.
 977          */
 978         lbolt_hdlr.cyh_func = (cyc_func_t)lbolt_cyclic;
 979         lbolt_hdlr.cyh_level = CY_LOCK_LEVEL;
 980         lbolt_hdlr.cyh_arg = NULL;
 981 
 982         lbolt_when.cyt_interval = nsec_per_tick;
 983 
 984         /*
 985          * Allocate cache line aligned space for the per CPU lbolt data and
 986          * lbolt info structures, and initialize them with their default
 987          * values. Note that these structures are also cache line sized.
 988          */
 989         sz = sizeof (lbolt_info_t) + CPU_CACHE_COHERENCE_SIZE;
 990         buf = (intptr_t)kmem_zalloc(sz, KM_SLEEP);
 991         lb_info = (lbolt_info_t *)P2ROUNDUP(buf, CPU_CACHE_COHERENCE_SIZE);
 992 
 993         if (hz != HZ_DEFAULT)


1028          * lbolt_hybrid points at lbolt_bootstrap until now. The LBOLT_* macros
1029          * and lbolt_debug_{enter,return} use this value as an indication that
1030          * the initializaion above hasn't been completed. Setting lbolt_hybrid
1031          * to either lbolt_{cyclic,event}_driven here signals those code paths
1032          * that the lbolt related structures can be used.
1033          */
1034         if (lbolt_cyc_only) {
1035                 lbolt_when.cyt_when = 0;
1036                 lbolt_hybrid = lbolt_cyclic_driven;
1037         } else {
1038                 lbolt_when.cyt_when = CY_INFINITY;
1039                 lbolt_hybrid = lbolt_event_driven;
1040         }
1041 
1042         /*
1043          * Grab cpu_lock and install all three cyclics.
1044          */
1045         mutex_enter(&cpu_lock);
1046 
1047         clock_cyclic = cyclic_add(&clk_hdlr, &clk_when);
1048         ddi_timer_cyclic = cyclic_add(&timer_hdlr, &clk_when);
1049         lb_info->id.lbi_cyclic_id = cyclic_add(&lbolt_hdlr, &lbolt_when);
1050 
1051         mutex_exit(&cpu_lock);
1052 }
1053 
1054 /*
1055  * Called before calcloadavg to get 10-sec moving loadavg together
1056  */
1057 
1058 static int
1059 genloadavg(struct loadavg_s *avgs)
1060 {
1061         int avg;
1062         int spos; /* starting position */
1063         int cpos; /* moving current position */
1064         int i;
1065         int slen;
1066         hrtime_t hr_avg;
1067 
1068         /* 10-second snapshot, calculate first positon */




   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  22 /*        All Rights Reserved   */
  23 
  24 /*
  25  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
  26  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
  27  */
  28 
  29 #include <sys/param.h>
  30 #include <sys/t_lock.h>
  31 #include <sys/types.h>
  32 #include <sys/tuneable.h>
  33 #include <sys/sysmacros.h>
  34 #include <sys/systm.h>
  35 #include <sys/cpuvar.h>
  36 #include <sys/lgrp.h>
  37 #include <sys/user.h>
  38 #include <sys/proc.h>
  39 #include <sys/callo.h>
  40 #include <sys/kmem.h>
  41 #include <sys/var.h>
  42 #include <sys/cmn_err.h>
  43 #include <sys/swap.h>
  44 #include <sys/vmsystm.h>
  45 #include <sys/class.h>
  46 #include <sys/time.h>
  47 #include <sys/debug.h>
  48 #include <sys/vtrace.h>
  49 #include <sys/spl.h>
  50 #include <sys/atomic.h>
  51 #include <sys/dumphdr.h>
  52 #include <sys/archsystm.h>
  53 #include <sys/fs/swapnode.h>
  54 #include <sys/panic.h>
  55 #include <sys/disp.h>
  56 #include <sys/msacct.h>
  57 #include <sys/mem_cage.h>
  58 
  59 #include <vm/page.h>
  60 #include <vm/anon.h>
  61 #include <vm/rm.h>
  62 #include <sys/cyclic.h>
  63 #include <sys/cpupart.h>
  64 #include <sys/rctl.h>
  65 #include <sys/task.h>
  66 #include <sys/sdt.h>
  67 #include <sys/ddi_periodic.h>
  68 #include <sys/random.h>
  69 #include <sys/modctl.h>
  70 #include <sys/zone.h>
  71 
  72 /*
  73  * for NTP support
  74  */
  75 #include <sys/timex.h>
  76 #include <sys/inttypes.h>
  77 
  78 #include <sys/sunddi.h>
  79 #include <sys/clock_impl.h>
  80 
  81 /*
  82  * clock() is called straight from the clock cyclic; see clock_init().
  83  *
  84  * Functions:
  85  *      reprime clock
  86  *      maintain date
  87  *      jab the scheduler


 299 /*
 300  * Cache aligned, per CPU structure with lbolt usage statistics.
 301  */
 302 static lbolt_cpu_t *lb_cpu;
 303 
 304 /*
 305  * Single, cache aligned, structure with all the information required by
 306  * the lbolt implementation.
 307  */
 308 lbolt_info_t *lb_info;
 309 
 310 
 311 int one_sec = 1; /* turned on once every second */
 312 static int fsflushcnt;  /* counter for t_fsflushr */
 313 int     dosynctodr = 1; /* patchable; enable/disable sync to TOD chip */
 314 int     tod_needsync = 0;       /* need to sync tod chip with software time */
 315 static int tod_broken = 0;      /* clock chip doesn't work */
 316 time_t  boot_time = 0;          /* Boot time in seconds since 1970 */
 317 cyclic_id_t clock_cyclic;       /* clock()'s cyclic_id */
 318 cyclic_id_t deadman_cyclic;     /* deadman()'s cyclic_id */

 319 
 320 extern void     clock_tick_schedule(int);
 321 
 322 static int lgrp_ticks;          /* counter to schedule lgrp load calcs */
 323 
 324 /*
 325  * for tod fault detection
 326  */
 327 #define TOD_REF_FREQ            ((longlong_t)(NANOSEC))
 328 #define TOD_STALL_THRESHOLD     (TOD_REF_FREQ * 3 / 2)
 329 #define TOD_JUMP_THRESHOLD      (TOD_REF_FREQ / 2)
 330 #define TOD_FILTER_N            4
 331 #define TOD_FILTER_SETTLE       (4 * TOD_FILTER_N)
 332 static int tod_faulted = TOD_NOFAULT;
 333 
 334 static int tod_status_flag = 0;         /* used by tod_validate() */
 335 
 336 static hrtime_t prev_set_tick = 0;      /* gethrtime() prior to tod_set() */
 337 static time_t prev_set_tod = 0;         /* tv_sec value passed to tod_set() */
 338 


 929          */
 930         if (wake_sched) {
 931                 t = &t0;
 932                 thread_lock(t);
 933                 if (t->t_state == TS_STOPPED) {
 934                         runin = runout = 0;
 935                         wake_sched = 0;
 936                         t->t_whystop = 0;
 937                         t->t_whatstop = 0;
 938                         t->t_schedflag &= ~TS_ALLSTART;
 939                         THREAD_TRANSITION(t);
 940                         setfrontdq(t);
 941                 }
 942                 thread_unlock(t);
 943         }
 944 }
 945 
 946 void
 947 clock_init(void)
 948 {
 949         cyc_handler_t clk_hdlr, lbolt_hdlr;
 950         cyc_time_t clk_when, lbolt_when;
 951         int i, sz;
 952         intptr_t buf;
 953 
 954         /*
 955          * Setup handler and timer for the clock cyclic.
 956          */
 957         clk_hdlr.cyh_func = (cyc_func_t)clock;
 958         clk_hdlr.cyh_level = CY_LOCK_LEVEL;
 959         clk_hdlr.cyh_arg = NULL;
 960 
 961         clk_when.cyt_when = 0;
 962         clk_when.cyt_interval = nsec_per_tick;
 963 
 964         /*








 965          * The lbolt cyclic will be reprogramed to fire at a nsec_per_tick
 966          * interval to satisfy performance needs of the DDI lbolt consumers.
 967          * It is off by default.
 968          */
 969         lbolt_hdlr.cyh_func = (cyc_func_t)lbolt_cyclic;
 970         lbolt_hdlr.cyh_level = CY_LOCK_LEVEL;
 971         lbolt_hdlr.cyh_arg = NULL;
 972 
 973         lbolt_when.cyt_interval = nsec_per_tick;
 974 
 975         /*
 976          * Allocate cache line aligned space for the per CPU lbolt data and
 977          * lbolt info structures, and initialize them with their default
 978          * values. Note that these structures are also cache line sized.
 979          */
 980         sz = sizeof (lbolt_info_t) + CPU_CACHE_COHERENCE_SIZE;
 981         buf = (intptr_t)kmem_zalloc(sz, KM_SLEEP);
 982         lb_info = (lbolt_info_t *)P2ROUNDUP(buf, CPU_CACHE_COHERENCE_SIZE);
 983 
 984         if (hz != HZ_DEFAULT)


1019          * lbolt_hybrid points at lbolt_bootstrap until now. The LBOLT_* macros
1020          * and lbolt_debug_{enter,return} use this value as an indication that
1021          * the initializaion above hasn't been completed. Setting lbolt_hybrid
1022          * to either lbolt_{cyclic,event}_driven here signals those code paths
1023          * that the lbolt related structures can be used.
1024          */
1025         if (lbolt_cyc_only) {
1026                 lbolt_when.cyt_when = 0;
1027                 lbolt_hybrid = lbolt_cyclic_driven;
1028         } else {
1029                 lbolt_when.cyt_when = CY_INFINITY;
1030                 lbolt_hybrid = lbolt_event_driven;
1031         }
1032 
1033         /*
1034          * Grab cpu_lock and install all three cyclics.
1035          */
1036         mutex_enter(&cpu_lock);
1037 
1038         clock_cyclic = cyclic_add(&clk_hdlr, &clk_when);

1039         lb_info->id.lbi_cyclic_id = cyclic_add(&lbolt_hdlr, &lbolt_when);
1040 
1041         mutex_exit(&cpu_lock);
1042 }
1043 
1044 /*
1045  * Called before calcloadavg to get 10-sec moving loadavg together
1046  */
1047 
1048 static int
1049 genloadavg(struct loadavg_s *avgs)
1050 {
1051         int avg;
1052         int spos; /* starting position */
1053         int cpos; /* moving current position */
1054         int i;
1055         int slen;
1056         hrtime_t hr_avg;
1057 
1058         /* 10-second snapshot, calculate first positon */