|
|
#include <sys/types.h> #include <sys/procset.h> #include <sys/priocntl.h> #include <sys/fppriocntl.h> #include <sys/tspriocntl.h>long priocntl(idtype_t idtype, id_t id, int cmd, void *arg);
The priocntl system call gets or sets scheduler parameters of a set of processes or LWPs. The input arguments:
Here are the valid values for idtype that are defined in <priocntl.h>, and their corresponding ID types in id. In this table, ``process'' also means LWP.
idtype | Interpretation of id |
---|---|
P_PID | process ID (of a single process) |
P_PPID | parent process ID |
P_PGID | process group ID |
P_LWPID | LWP ID |
P_SID | session ID |
P_CID | class ID |
P_UID | effective user ID |
P_GID | effective group ID |
P_ALL | all processes and LWPs |
Here are the valid values for cmd, their meanings, and the type of arg:
priocntl commands
cmd | arg Type | Function |
---|---|---|
PC_GETCID | pcinfo_t | get class ID and attributes |
PC_GETCLINFO | pcinfo_t | get class name and attributes |
PC_SETPARMS | pcparms_t | set class and scheduling parameters |
PC_GETPARMS | pcparms_t | get class and scheduling parameters |
Here are the values priocntl returns on success:
The PC_GETCID and PC_GETCLINFO commands retrieve scheduler parameters for a class based on the class ID or class name. Both commands use the pcinfo structure to send arguments and receive return values:
typedef struct pcinfo { id_t pc_cid; /* class id */ char pc_clname[PC_CLNMSZ]; /* class name */ long pc_clinfo[PC_CLINFOSZ]; /* class information */ } pcinfo_t;
The
PC_GETCID
command gets scheduler class ID and parameters given the class name.
The class ID is used in some of the other
priocntl
commands to specify a scheduler class.
The valid class names are
TS
for time-sharing,
FC
for fixed class,
and
FP
for fixed priority.
For the fixed priority class, pc_clinfo contains an fpinfo structure, which holds fp_maxpri, the maximum valid fixed priority; in the default configuration, this is the highest priority any process or LWP can have. The minimum valid fixed priority is zero. fp_maxpri is a configurable value; see ``Process scheduling'' for information on how to configure process and LWP priorities.
typedef struct fpinfo { short fp_maxpri; /* maximum fixed priority */ } fpinfo_t;
For the time-sharing class, pc_clinfo contains a tsinfo structure, which holds ts_maxupri, the maximum time-sharing user priority. The minimum time-sharing user priority is -ts_maxupri. ts_maxupri is also a configurable value.
typedef struct tsinfo { short ts_maxupri; /* limits of user priority range */ } tsinfo_t;
For the fixed class, pc_clinfo contains a fcinfo structure, which holds fc_maxupri, the maximum fixed class user priority. The minimum fixed class user priority is -fc_maxupri. fc_maxupri is also a configurable value.
typedef struct fcinfo { short fc_maxupri; /* limits of user priority range */ } fcinfo_t;
The following program is a cheap substitute for priocntl -l; it gets and prints the range of valid priorities for the time-sharing and fixed priority scheduler classes.
/* * Get scheduler class IDs and priority ranges. */#include <sys/types.h> #include <sys/priocntl.h> #include <sys/fppriocntl.h> #include <sys/tspriocntl.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h>
main () { pcinfo_t pcinfo; tsinfo_t *tsinfop; fpinfo_t *fpinfop; short maxtsupri, maxfppri;
/* time sharing */ (void) strcpy (pcinfo.pc_clname, "TS"); if (priocntl (0L, 0L, PC_GETCID, &pcinfo) == -1L) { perror ("PC_GETCID failed for time-sharing class"); exit (1); } tsinfop = (struct tsinfo *) pcinfo.pc_clinfo; maxtsupri = tsinfop->ts_maxupri; (void) printf("Time sharing: ID %ld, priority range -%d through %d\n", pcinfo.pc_cid, maxtsupri, maxtsupri);
/* fixed priority */ (void) strcpy(pcinfo.pc_clname, "FP"); if (priocntl (0L, 0L, PC_GETCID, &pcinfo) == -1L) { perror ("PC_GETCID failed for fixed priority class"); exit (2); } fpinfop = (struct fpinfo *) pcinfo.pc_clinfo; maxfppri = fpinfop->fp_maxpri; (void) printf("Fixed priority: ID %ld, priority range 0 through %d\n", pcinfo.pc_cid, maxfppri); return (0); }
The following screen shows the output of this program, called
getcid
in this example.
$ getcid
Time sharing: ID 1, priority range -20 through 20
Fixed priority: ID 2, priority range 0 through 59
The following function is useful in the examples below. Given a class name, it uses PC_GETCID to return the class ID and maximum priority in the class.
/* * Return class ID and maximum priority. * Input argument name is class name. * Maximum priority is returned in *maxpri. */id_t schedinfo (name, maxpri) char *name; short *maxpri; { pcinfo_t info; tsinfo_t *tsinfop; fpinfo_t *fpinfop;
(void) strcpy(info.pc_clname, name); if (priocntl (0L, 0L, PC_GETCID, &info) == -1L) { return (-1); } if (strcmp(name, "TS") == 0) { tsinfop = (struct tsinfo *) info.pc_clinfo; *maxpri = tsinfop->ts_maxupri; } else if (strcmp(name, "FP") == 0) { fpinfop = (struct fpinfo *) info.pc_clinfo; *maxpri = fpinfop->fp_maxpri; } else { return (-1); } return (info.pc_cid); }
The PC_GETCLINFO command gets a scheduler class name and parameters given the class ID. This command makes it easy to write applications that make no assumptions about what classes are configured.
The following program uses PC_GETCLINFO to get the class name of a process or LWP based on the process ID. This program assumes the existence of a function getclassID, that retrieves the class ID of a process or LWP given the process ID; this function is given in the following section.
/* Get scheduler class name given process ID. */main (argc, argv) int argc; char *argv[]; { pcinfo_t pcinfo; id_t pid, classID; id_t getclassID();
if ((pid = atoi(argv[1])) <= 0) { perror ("bad pid"); exit (1); } if ((classID = getclassID(pid)) == -1) { perror ("unknown class ID"); exit (2); } pcinfo.pc_cid = classID; if (priocntl (0L, 0L, PC_GETCLINFO, &pcinfo) == -1L) { perror ("PC_GETCLINFO failed"); exit (3); } (void) printf("process ID %d, class %s\n", pid, pcinfo.pc_clname); }
The PC_GETPARMS command gets and the PC_SETPARMS command sets scheduler parameters for processes and LWPs. Both commands use the pcparms structure to send arguments or receive return values:
typedef struct pcparms { id_t pc_cid; /* process or LWP class */ long pc_clparms[PC_CLPARMSZ]; /* class specific */ } pcparms_t;
Ignoring class-specific information for the moment, we can write a simple function for returning the scheduler class ID of a process or LWP, as promised in the previous section.
/* * Return scheduler class ID of process or LWP with ID pid. */getclassID (pid) id_t pid; { pcparms_t pcparms;
pcparms.pc_cid = PC_CLNULL; if (priocntl(P_PID, pid, PC_GETPARMS, &pcparms) == -1) { return (-1); } return (pcparms.pc_cid); }
For the real-time class, For the fixed priority class, pc_clparms contains an fpparms structure. fpparms holds scheduler parameters specific to the
typedef struct fpparms { short fp_pri; /* fixed priority */ ulong fp_tqsecs; /* seconds in time quantum */ long fp_tqnsecs; /* additional nsecs in quantum */ } fpparms_t;
fp_pri is the fixed priority; fp_tqsecs is the number of seconds and fp_tqnsecs is the number of additional nanoseconds in a time slice. That is, fp_tqsecs seconds plus fp_tqnsecs nanoseconds is the interval an LWP may use the CPU without sleeping before the scheduler gives another LWP a chance at the CPU.
For the time-sharing class, pc_clparms contains a tsparms structure. tsparms holds the scheduler parameter specific to the time-sharing class:
typedef struct tsparms { short ts_uprilim; /* user priority limit */ short ts_upri; /* user priority */ } tsparms_t;
ts_upri is the user priority, the user-controlled component of a time-sharing priority. ts_uprilim is the user priority limit, the maximum user priority a process or LWP may set for itself without being a privileged user. These values are described above in the discussion of the -s option of the priocntl command. Both the user priority and the user priority limit must be within the range reported by the priocntl -l command; this range is also reported by the PC_GETCID and PC_GETCLINFO commands to the priocntl system call.
The PC_GETPARMS command gets the scheduler class and parameters of a single process or LWP. The return value of the priocntl is the process ID of the process or LWP whose parameters are returned in the pcparms structure. The process or LWP chosen depends on the idtype and id arguments to priocntl and on the value of pcparms.pc_cid, which contains PC_CLNULL or a class ID returned by PC_GETCID:
What gets returned by PC_GETPARMS
pc_cid | |||
---|---|---|---|
Number of processes
selected by idtype and id | FP class ID | TS class ID | PC_CLNULL |
1 | FP parameters of process or LWP selected | TS parameters of process or LWP selected | class and parameters of process or LWP selected |
More than 1 | FP parameters of highest-priority FP process or LWP | TS parameters of process or LWP with highest user priority | (error) |
If idtype and id select a single process or LWP and pc_cid does not conflict with the class of that process or LWP, priocntl returns the scheduler parameters of the process or LWP. If they select more than one process or LWP of a single scheduler class, priocntl returns parameters using class-specific criteria as shown in the table. priocntl returns an error in the following cases:
The following program takes a process ID as its input and prints the scheduler class and class-specific parameters of that process or LWP:
/* * Get scheduler class and parameters of * process or LWP whose pid is input argument. */main (argc, argv) int argc; char *argv[]; { pcparms_t pcparms; fpparms_t *fpparmsp; tsparms_t *tsparmsp; id_t pid, fpID, tsID; id_t schedinfo(); short priority, tsmaxpri, fpmaxpri; ulong secs; long nsecs;
pcparms.pc_cid = PC_CLNULL; fpparmsp = (fpparms_t *) pcparms.pc_clparms; tsparmsp = (tsparms_t *) pcparms.pc_clparms; if ((pid = atoi(argv[1])) <= 0) { perror ("bad pid"); exit (1); }
/* get scheduler properties for this pid */ if (priocntl(P_PID, pid, PC_GETPARMS, &pcparms) == -1) { perror ("GETPARMS failed"); exit (2); }
/* get class IDs and maximum priorities for TS and FP */ if ((tsID = schedinfo ("TS", &tsmaxpri)) == -1) { perror ("schedinfo failed for TS"); exit (3); } if ((fpID = schedinfo ("FP", &fpmaxpri)) == -1) { perror ("schedinfo failed for FP"); exit (4); }
/* print results */ if (pcparms.pc_cid == fpID) { priority = fpparmsp->fp_pri; secs = fpparmsp->fp_tqsecs; nsecs = fpparmsp->fp_tqnsecs; (void) printf ("process %d: FP priority %d\n", pid, priority); (void) printf ("time slice %ld secs, %ld nsecs\n", secs, nsecs); } else if (pcparms.pc_cid == tsID) { priority = tsparmsp->ts_upri; (void) printf ("process %d: TS priority %d\n", pid, priority); } else { printf ("Unknown scheduler class %d\n", pcparms.pc_cid); exit (5); } return (0); }
The PC_SETPARMS command sets the scheduler class and parameters of a set of processes or LWPs. The idtype and id input arguments specify the processes or LWPs to be changed. The pcparms structure contains the new parameters: pc_cid contains the ID of the scheduler class to which the processes or LWPs are to be assigned, as returned by PC_GETCID; pc_clparms contains the class-specific parameters:
The following program takes a process ID as input, makes the process or LWP a fixed priority process or LWP with the highest valid priority minus 1, and gives it the default time slice for that priority. The program calls the schedinfo function listed above to get the real-time fixed priority class ID and maximum priority.
/* * Input arg is proc ID. Make process or LWP a fixed priority * process or LWP with highest priority minus 1. */main (argc, argv) int argc; char *argv[]; { pcparms_t pcparms; fpparms_t *fpparmsp; id_t pid, fpID; id_t schedinfo(); short maxrtpri; short maxfppri;
if ((pid = atoi(argv[1])) <= 0) { perror ("bad pid"); exit (1); }
/* Get highest valid FP priority. */ if ((fpID = schedinfo ("FP", &maxfppri)) == -1) { perror ("schedinfo failed for FP"); exit (2); }
/* Change proc to FP, highest prio - 1, default time slice */ pcparms.pc_cid = fpID; fpparmsp = (struct fpparms *) pcparms.pc_clparms; fpparmsp->fp_pri = maxfppri - 1; fpparmsp->fp_tqnsecs = FP_TQDEF;
if (priocntl(P_PID, pid, PC_SETPARMS, &pcparms) == -1) { perror ("PC_SETPARMS failed"); exit (3); } }
The following table lists the special values fp_tqnsecs can take when PC_SETPARMS is used on fixed priority processes and LWPs. When any of these is used, fp_tqsecs is ignored. These values are defined in the header file fppriocntl.h:
fp_tqnsecs | Time slice |
---|---|
FP_TQINF | infinite |
FP_TQDEF | default |
FP_NOCHANGE | unchanged |
FP_TQINF specifies an infinite time slice. FP_TQDEF specifies the default time slice configured for the fixed priority being set with the SETPARMS call. FP_NOCHANGE specifies no change from the current time slice; this value is useful, for example, when you change process or LWP priority but do not want to change the time slice. (You can also use FP_NOCHANGE in the fp_pri field to change a time slice without changing the priority.)