19.1. The System Clock ThreadThe Solaris clock thread performs routine processing as a lock-level client of the cyclic subsystem (Section 19.4). For example, it triggers the dispatcher to recalculate thread priorities at regular intervals, and also initiates callout queue processing. Figure 19.1 shows the interaction between the system timing interfaces and subsystems. Figure 19.1. Clock and Timer Interactions
The kernel installs a cyclic to call the clock thread at regular intervals, by default 100 times per second. With each clock interrupt, a handler is entered. It performs the following functions:
Once the clock interrupt handling is completed, the clock interrupt thread is context-switched off the processor, and the thread that was executing when the interrupt occurred resumes. 19.1.1. Thread Tick ProcessingTick processing is done for each kernel thread (if that thread is not an interrupt handler or an operating system kernel thread) running on a CPU. The kernel determines whether it is necessary to do tick processing for a thread by comparing the thread's t_lbolt with lbolt. if ((!thread_away) && (lbolt - t->t_lbolt != 0)) { t->t_lbolt = lbolt; clock_tick(t); } The clock_tick() code is passed the kernel thread ID and invokes the scheduling-class-specific clock-tick function, that is, ts_tick() for timeshare and interactive class threads and rt_tick() for real-time class threads. These functions are discussed in "Real-Time Tick Processing." on page 229. Briefly, the functions determine if the thread has used up its time quantum, and they take the thread off the processor if it has. Back in the clock_tick() function, the following actions are performed:
The update completes the clock-tick processing for the thread. 19.1.2. DTrace Providers for Tick ProcessingSome DTrace static probes are part of the sched provider. # dtrace -l -n 'sched:::' |grep tick 2870 sched genunix clock_tick tick 12666 sched TS ts_tick schedctl-nopreempt 30273 sched FX fx_tick schedctl-nopreempt The sched tick probe fires as a part of clock-tick-based accounting. In clock-tick-based accounting, CPU accounting is performed by examination of the threads and processes running when a fixed-interval interrupt fires. The lwpsinfo_t that corresponds to the thread that is being assigned CPU time is pointed to by args[0]. The psinfo_t that corresponds to the process that contains the thread is pointed to by args[1]. typedef struct psinfo { int pr_nlwp; /* number of active lwps in the process */ pid_t pr_pid; /* unique process id */ pid_t pr_ppid; /* process id of parent */ pid_t pr_pgid; /* pid of process group leader */ pid_t pr_sid; /* session id */ uid_t pr_uid; /* real user id */ uid_t pr_euid; /* effective user id */ gid_t pr_gid; /* real group id */ gid_t pr_egid; /* effective group id */ uintptr_t pr_addr; /* address of process */ dev_t pr_ttydev; /* controlling tty device (or PRNODEV) */ timestruc_t pr_start; /* process start time, from the epoch */ char pr_fname[PRFNSZ]; /* name of execed file */ char pr_psargs[PRARGSZ]; /* initial characters of arg list */ int pr_argc; /* initial argument count */ uintptr_t pr_argv; /* address of initial argument vector */ uintptr_t pr_envp; /* address of initial environment vector */ char pr_dmodel; /* data model of the process */ taskid_t pr_taskid; /* task id */ projid_t pr_projid; /* project id */ poolid_t pr_poolid; /* pool id */ zoneid_t pr_zoneid; /* zone id */ } psinfo_t; |