DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 

priocntl(S)


priocntl -- process scheduler control

Synopsis

   #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);

Description

The schedulable entity for the system is the light-weight process (LWP). Scheduling priorities and classes are attributes of LWPs and not processes. The priocntl system call gets or sets scheduler parameters for a lightweight process (LWP) or a set of LWPs.

Four priority classes are supported. The time-sharing class (TS) adjusts priorities dynamically in an attempt to provide good response time to interactive LWPs and good throughput to CPU-intensive LWPs. The fixed class (FC) is similar to the time-sharing policy, except that it does not adjust priorities. The fixed priority class (FP) supports real-time scheduling, and allows administrators to set priorities for individual LWPs. There is also a system (sys) class that uses a fixed-priority policy to run kernel processes. The system class is reserved for use by the kernel; users may neither add nor remove a process from the system class.

In the default configuration, the highest-priority fixed priority class LWP always gets the CPU as soon as it is runnable, even if system class processes are runnable. It is important to note that the indiscriminate use of fixed priority LWPs can have a dramatic negative effect on overall system performance, particularly the performance of time-sharing LWPs.

priocntl provides an interface for specifying a set of processes or LWPs to which the system call is to apply. The priocntlset system call provides the same functions as priocntl, but allows a more general interface for specifying the set of processes to which the system call is to apply.

For priocntl, the idtype and id arguments are used together to specify the set of processes or LWPs. The interpretation of id depends on the value of idtype. The possible values for idtype and corresponding interpretations of id are as follows:


P_PID
id is a process ID specifying a single process; the priocntl system call applies to all LWPs associated with the process.

P_PPID
id is a parent process ID. The priocntl system call applies to all LWPs associated with all processes with the specified parent process ID.

P_PGID
id is a process group ID. The priocntl system call applies to all LWPs associated with all processes in the specified process group.

P_LWPID
id is interpreted as the LWP identifier of an LWP within the calling process, and the priocntl call applies only to that LWP.

P_SID
id is a session ID. The priocntl system call applies to all LWPs associated with all processes in the specified session.

P_CID
id is a class ID (returned by priocntl PC_GETCID as explained below). The priocntl system call applies to all LWPs associated with all processes in the specified class.

P_UID
id is a user ID. The priocntl system call applies to all LWPs associated with all processes with this effective user ID.

P_GID
id is a group ID. The priocntl system call applies to all LWPs associated with all processes with this effective group ID.

P_ALL
The priocntl system call applies to all existing LWPs. The value of id is ignored. The permission restrictions described below still apply.

An id value of P_MYID can be used with the idtype value to specify the calling process's process ID, parent process ID, process group ID, session ID, class ID, user ID, group ID, or the LWP ID of the calling LWP.

To change the scheduling parameters of an LWP (using the PC_SETPARMS command as explained below) the real or effective user ID of the LWP calling priocntl must match the real or effective user ID of the receiving LWP or the calling LWP must have appropriate privilege. See the subsections below for details for each class. These are the minimum permission requirements enforced for all classes. An individual class can impose additional permissions requirements when setting processes to that class or when setting class-specific scheduling parameters.

The sys scheduling class exists for scheduling the execution of certain special system processes. It is not possible to change the class of any LWP to sys. In addition, any processes in the sys class that are included in a specified set of processes are disregarded by priocntl. For example, an idtype of P_UID and an id value of zero would specify all processes with a user ID of zero except processes in the sys class and (if changing the parameters using PC_SETPARMS) the init process.

The init process is a special case. In order for a priocntl call to change the class or other scheduling parameters of the init process (process ID 1), it must be the only process specified by idtype and id. The init process may be assigned to any class configured on the system, but the time-sharing class is almost always the appropriate choice.

The data type and value of arg are specific to the type of command specified by cmd.

Use the structure of type PC_GETCID and PC_GETCLINFO containing the following members:

       id_t    pc_cid;                 /* Class id */
       char    pc_clname[PC_CLNMSZ];   /* Class name */
       long    pc_clinfo[PC_CLINFOSZ]; /* Class information */

pc_cid is a class ID returned by priocntl PC_GETCID. pc_clname is a buffer of size PC_CLNMSZ (defined in sys/priocntl.h) used to hold the class name (FP for or TS for time-sharing).

pc_clinfo is a buffer of size PC_CLINFOSZ (defined in sys/priocntl.h) used to return data describing the attributes of a specific class. The format of this data is class-specific and is described under the appropriate heading below.

The PC_SETPARMS and PC_GETPARMS commands use a structure containing the following members:

       id_t    pc_cid;                  /* Process class */
       long    pc_clparms[PC_CLPARMSZ]; /* Class-specific params */

pc_cid is a class ID (returned by priocntl PC_GETCID). The special class ID PC_CLNULL can also be assigned to pc_cid when using the PC_GETPARMS command as explained below.

The pc_clparms buffer holds class-specific scheduling parameters. The format of this parameter data for a particular class is described under the appropriate heading below. PC_CLPARMSZ is the length of the pc_clparms buffer and is defined in sys/priocntl.h.

The following commands are supported:

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

 +-------------+-----------+-------------------------------------+
 |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 |
 +-------------+-----------+-------------------------------------+

PC_GETCID and PC_GETCLINFO

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'' in Programming with system calls and libraries 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.


NOTE: All the following examples omit the lines that include header files. The examples compile with the same header files as in the first example above.

/*
 *  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); }

PC_GETPARMS and PC_SETPARMS

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)

                                     pc_cid
 Number of       FP class ID      TS class ID     PC_CLNULL
 processes
 selected by
 idtype and id
 1               FP parameters    TS parameters   class and
                 of process or    of process or   parameters of
                 LWP selected     LWP selected    process or LWP
                                                  selected
 More than 1     FP parameters    TS parameters   (error)
                 of highest-      of process or
                 priority FP      LWP with
                 process or LWP   highest user
                                  priority

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_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.)

Return values

On success, priocntl returns values dependent on the command used: On failure, priocntl returns -1 and sets errno to indicate the reason for the failure.

Errors

In the following conditions, priocntl fails and sets errno to:

EAGAIN
An attempt to change the class of an LWP failed because of insufficient resources other than memory (for example, class-specific kernel data structures).

EINVAL
The argument cmd was invalid, an invalid or unconfigured class was specified, or a parameter specified was invalid.

EFAULT
All or part of the area pointed to by a data pointer is outside the address space of the LWP.

ENOMEM
An attempt to change the class of an LWP failed because of insufficient memory.

EPERM
An attempt was made to change the system time-sharing or fixed priority defaults, and the calling LWP does not have the P_TSHAR or P_RTIME privileges (respectively, for the two classes).

EPERM
The effective user ID of the calling LWP does not match the effective user ID of the target LWP, and the calling LWP does not have the P_OWNER privilege.

EPERM
An attempt was made to change the class of the target LWP to fixed priority (from any class) and the calling LWP does not have the P_OWNER and the P_RTIME privileges.

EPERM
An attempt was made to change the priority of a fixed priority LWP and the calling LWP does not have the P_OWNER and the P_RTIME privileges.

EPERM
An attempt was made to raise the priority of a time-sharing LWP, or raise the ts_prilim of the LWP above 0, and the calling LWP does not have the P_OWNER and the P_TSHAR privileges.

EPERM
An attempt was made to use the PC_SETAGEPARMS command and the calling LWP did not have the P_SYSOPS privilege.

ERANGE
The requested time quantum is out of range.

ESRCH
None of the specified LWPs exist.

References

dispadmin(ADM), exec(S), fork(S), fc_dptbl(F), fp_dptbl(F), nice(S), priocntl(C), priocntlset(S), ts_dptbl(F)

Notices

Considerations for threads programming

The priocntl(S) system call should not be used to change the priority of multiplexed threads. Doing so may interfere with the scheduling of threads by the Threads Library.
© 2005 The SCO Group, Inc. All rights reserved.
SCO OpenServer Release 6.0.0 - 01 June 2005