|
» |
|
|
|
| | |
The thread of a parent process forks a child process. The
child process inherits the scheduling policy and priority of the
parent process. As with the parent thread, it is the child thread
whose scheduling policy and priority will be used. The following figure illustates the flow of creation. Each thread in a process is independently
scheduled. Each thread contains its own scheduling policy and
priority Thread scheduling policies and priorities may be
assigned before a thread is created (in the threads attributes object)
or set dynamically while a thread is running. Each thread may be bound directly to a CPU. Each thread may be suspended (and later resumed)
by any thread within the process.
The following scheduling attributes may be set in the threads
attribute object. The newly created thread will contain these scheduling
attributes: - contentionscope
PTHREAD_SCOPE_SYSTEM
specifies a bound (1 x 1, kernel-spacel) thread. When a bound thread
is created, both a user thread and a kernel-scheduled entity are
created. PTHREAD_SCOPE_PROCESS will
specify an unbound (M x N, combination user- and kernel-space) thread.
(Note, HP-UX release 10.30 does not support unbound threads.) - inheritsched
PTHREAD_INHERIT_SCHED
specifies that the created thread will inherit its scheduling values
from the creating thread, instead of from the threads attribute
object. PTHREAD_EXPLICIT_SCHED specifies
that the created thread will get its scheduling values from the
threads attribute object. - schedpolicy
The scheduling policy of the newly created thread - schedparam
The scheduling parameter (priority) of the newly
created thread.
Timeline | |
A process and its thread change with the passage of time.
A thread's priority is adjusted four key times, as shown
in the next figure and described in the table that follows.. Table 1-24 Thread priority
adjustments Interval | What happens |
---|
10 milliseconds | The clock-interrupt handling routine clock_int()
adjusts a time interval on the monarch every clock tick. The monarch
processor calls hardclock() to
handle clock ticks on the monarch for general maintenance (such
as disk and LAN states). hardclock()
calls per_spu_hardclock() to charge
the running thread with cpu time accumulated (kt_cpu). | 40 milliseconds | per_spu_hardclock()
determines the running thread has accumulated 40ms of time and calls
setpri(). setpri()
calls calcusrpri() to adjust the
running thread's user priority (kt_usrpri). | 100 milliseconds | By default, 10 clock ticks represents the value
of timeslice, the configurable kernel parameter that defines the
amount of time one thread is allowed to run before the CPU is given
to the next thread. Once a timeslice interval has expired a call
to swtch() is made to enact a context
switch. | one second | statdaemon()
loops on the thread list and once every second calls schedcpu()
to update all thread priorities. The kt_usrpri
priority is given to the thread on the next context switch; if
in user mode kt_usrpri is given
immediately. |
Thread Scheduling Routines | |
The following table summarizes the principal thread scheduling
routines. Table 1-25 Thread scheduling
routines Routine | Purpose |
---|
hardclock() | Runs on the monarch processor to handle clock
ticks. | per_spu_hardclock() | handles per-processor hardclock activities. | setpri() | Called with a thread as its argument and returns
a user priority for that thread. Calls calcusrpri()
to get the new user priority. If the new priority is stronger than
that of the currently running thread, setpri()
generates an MPSCHED interrupt
on the processor executing that thread, stores the new user priority
in kt_usrpri and returns it to
its caller. | calcusrpri() | The user priority (kt_usrpri)
portion of setpri(). calcusrpri()
uses the kt_cpu and p_nice(proc)
fields of the thread, tt, to determine
tt's user priority and
return that value without changing any fields in *tt.
If tt is a RTPRIO
or RTSCHED thread, kt_usrpri
is the current value of kt_pri. | swtch() | Finds the most deserving runnable thread, takes
it off the run queue, and sets it to run. | statdaemon() | A general-purpose kernel process run once per
second to check and update process and virtual memory artifacts,
such as signal queueing and free protection IDs. Calls schedcpu()
to recompute thread priorities and statistics. | schedcpu() | Once a second, schedcpu()
loops through the thread list to update thread scheduling priorities.
If the system has more than one SPU, it balances SPU loads. schedcpu
updates thread usage information (kt_prevrecentcycles
and kt_fractioncpu), calculates
new kt_cpu for the current thread
(info used by setpri(), updates
the statistics of runnable threads on run queues and those swapped
out, and awakens the swapper. Calls setpri(). | setrq() | Routine used to put threads onto the run queues.
Set the appropriate protection (spl7
in UP case, thread lock in MP case). Assert valid HP-UX priority
and scheduling policy and perform policy-specific setup | remrq() | Routine used to remove a thread from its run
queue. With a valid kt_link, set the appropriate protection (spl7
in the UP case or thread lock in MP case). Find the processor on
which the thread is running. Decrement the thread count on run queues.
Update the mpinfo structure. Restore the old spl
level, update RTSCHED counts if
necessary. Adjust the kt_pri, return
to schedcpu. |
Adjusting a Thread Priority | |
Every 10 msecs, the routine hardclock()
is called with spinlock SPL5 to
disable I/O modules and software interrupts. hardclock()
calls the per-processor routine per_spu_hardclock(),
which looks for threads whose priority is high enough to run. ( Searching
the processor run queues depends on the scheduling policy). If a
thread is found, the MPSCHED_INT_BIT
in the processor EIRR (External Interrupt Request Register) is set. When the system receives an MPSCHED_INT
interrupt while running a thread in user mode, the trap handler
puts the thread on a run queue and switches context, to bring in
the high- priority thread. If the current executing thread is the thread with the highest
priority, it is given 100ms (one timeslice) to run. hardclock()
calls setpri() every 40ms to review the thread's working
priority (kt_pri). setpri() adjusts
the user priority (kt_usrpri) of
a time-share thread process based on cpu
usage and nice values. While
a time-share thread is running, kt_cpu
time increases and its priority (kt_pri)
worsens. RTSCHED or RTPRIO
thread priorities do not change. Every 1 second, schedcpu()
decrements the kt_cpu value for
each thread on the run queue. setpri() is
called to calculate a new priority of the current thread being examined
in the schedcpu() loop. remrq() is
called to remove that thread from the run queue and then setrq()
places the thread back into the run queue according to its new priority. If a process is sleeping or on a swap device (that is, not
on the run queue), the user priority (kt_usrpri)
is adjusted in setpri() and kt_pri
is set in schedcpu().
|