Re: [PATCH] make setpriority POSIX compliant; introducePRIO_THREAD extension

From: Denys Vlasenko
Date: Mon Sep 01 2008 - 10:19:23 EST


On Mon, 2008-09-01 at 16:12 +0200, Denys Vlasenko wrote:
> Patch is run tested. I will post test program etc as a reply.

Test program is attached.
Build with "gcc -o prio_vda3 prio_vda3.c -lpthread".
Output:

start test program
CHILD1: TID:3269 getpriority:0
CHILD1: PID:3269 getpriority:0
setpriority(PRIO_PROCESS, 3269, -10)
THREAD CHILD: TID:3270 getpriority:-2
THREAD CHILD: PID:3269 getpriority:-10
THREAD CHILD: TID:3271 getpriority:-4
THREAD CHILD: PID:3269 getpriority:-10
THREAD CHILD: TID:3272 getpriority:-6
THREAD CHILD: PID:3269 getpriority:-10
THREAD CHILD: TID:3273 getpriority:-8
THREAD CHILD: PID:3269 getpriority:-10
CHILD2: TID:3269 getpriority:-10
CHILD2: PID:3269 getpriority:-10
Joined!
Joined!
Joined!
Joined!

log of instrumented kernel:

(no threads created yet, only one tid exists)
getpriority:
PRIO_PROCESS: pid 3269 tgid 3269: niceval=20
PRIO_PROCESS: returning retval=20
PRIO_PROCESS: pid 3269 tgid 3269: niceval=20
PRIO_PROCESS: returning retval=20
(5 threads are created)
setpriority(PRIO_PROCESS, pid, -10):
setting prio of pid 3269 tgid 3269 to -10
setting prio of pid 3270 tgid 3269 to -10
setting prio of pid 3271 tgid 3269 to -10
setting prio of pid 3272 tgid 3269 to -10
setting prio of pid 3273 tgid 3269 to -10
setpriority(3 /*PRIO_THREAD*/, syscall(SYS_gettid), -1);
setting prio of pid 3270 tgid 3269 to -1
setpriority(PRIO_PROCESS, syscall(SYS_gettid), -2);
setting prio of pid 3270 tgid 3269 to -2

Above you see how setpriority(PRIO_PROCESS) can set prio for all threads
or only for one.

prio = getpriority(PRIO_PROCESS, tid);
PRIO_PROCESS: pid 3270 tgid 3269: niceval=22
PRIO_PROCESS: returning retval=22
prio = getpriority(PRIO_PROCESS, pid);
PRIO_PROCESS: pid 3269 tgid 3269: niceval=30
PRIO_PROCESS: pid 3270 tgid 3269: niceval=22
PRIO_PROCESS: pid 3271 tgid 3269: niceval=30
PRIO_PROCESS: pid 3272 tgid 3269: niceval=30
PRIO_PROCESS: pid 3273 tgid 3269: niceval=30
PRIO_PROCESS: returning retval=30

Same for getpriority.

The rest is analogous:

setting prio of pid 3271 tgid 3269 to -3
setting prio of pid 3271 tgid 3269 to -4
PRIO_PROCESS: pid 3271 tgid 3269: niceval=24
PRIO_PROCESS: returning retval=24
PRIO_PROCESS: pid 3269 tgid 3269: niceval=30
PRIO_PROCESS: pid 3271 tgid 3269: niceval=24
PRIO_PROCESS: pid 3272 tgid 3269: niceval=30
PRIO_PROCESS: pid 3273 tgid 3269: niceval=30
PRIO_PROCESS: returning retval=30
setting prio of pid 3272 tgid 3269 to -5
setting prio of pid 3272 tgid 3269 to -6
PRIO_PROCESS: pid 3272 tgid 3269: niceval=26
PRIO_PROCESS: returning retval=26
PRIO_PROCESS: pid 3269 tgid 3269: niceval=30
PRIO_PROCESS: pid 3272 tgid 3269: niceval=26
PRIO_PROCESS: pid 3273 tgid 3269: niceval=30
PRIO_PROCESS: returning retval=30
setting prio of pid 3273 tgid 3269 to -7
setting prio of pid 3273 tgid 3269 to -8
PRIO_PROCESS: pid 3273 tgid 3269: niceval=28
PRIO_PROCESS: returning retval=28
PRIO_PROCESS: pid 3269 tgid 3269: niceval=30
PRIO_PROCESS: pid 3273 tgid 3269: niceval=28
PRIO_PROCESS: returning retval=30
PRIO_PROCESS: pid 3269 tgid 3269: niceval=30
PRIO_PROCESS: returning retval=30
PRIO_PROCESS: pid 3269 tgid 3269: niceval=30
PRIO_PROCESS: returning retval=30

Patch with instrumentation is attached too.
--
vda


#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <memory.h>

#define THREAD_NUM 5

static void printprio(const char *pfx)
{
int prio;
pid_t tid = syscall(SYS_gettid);
pid_t pid = getpid();
prio = getpriority(PRIO_PROCESS, tid);
printf("%sTID:%d getpriority:%d\n", pfx, tid, prio);
prio = getpriority(PRIO_PROCESS, pid);
printf("%sPID:%d getpriority:%d\n", pfx, pid, prio);
}

int threadno;

static void* threadfunc(void *dummy)
{
sleep(1); /* wait for parent to setpriority */
setpriority(3 /*PRIO_THREAD*/, syscall(SYS_gettid), -(++threadno));
setpriority(PRIO_PROCESS, syscall(SYS_gettid), -(++threadno));
printprio("THREAD CHILD: ");
pthread_exit(0);
}

int main()
{
pid_t pid = fork();
if (pid) {
/* parent */
int status;
printf("start test program\n");
sleep(1); /* wait for threads to start in child */
printf("setpriority(PRIO_PROCESS, %d, -10)\n", pid);
if (setpriority(PRIO_PROCESS, pid, -10) < 0) {
perror("setpriority PRIO_PROCESS");
exit(1);
}
wait(&status);
} else {
/* child */
int i;
pthread_t thread_id[THREAD_NUM];

printprio("CHILD1: ");
for (i = 1; i < THREAD_NUM; i++) {
usleep(30*1000);
pthread_create(&thread_id[i], NULL, &threadfunc, NULL);
}

usleep(30*1000);
sleep(1); /* wait for parent to setpriority */
printprio("CHILD2: ");

for (i = 1; i < THREAD_NUM; i++) {
pthread_join(thread_id[i], NULL);
printf("Joined!\n");
}
}
return 0;
}
--- a/kernel/sys.c.orig 2008-09-01 12:50:22.000000000 +0200
+++ b/kernel/sys.c 2008-09-01 15:11:45.000000000 +0200
@@ -162,15 +162,22 @@
else
p = current;
if (p)
+{printk("setting prio of pid %d tgid %d to %d\n", p->pid, p->tgid, niceval);
error = set_one_prio(p, niceval, error);
+}
break;
case PRIO_PROCESS:
if (who)
pid = find_vpid(who);
- else
+ else {
pid = task_pid(current);
+ who = current->pid;
+ }
do_each_pid_thread(pid, PIDTYPE_PID, p) {
- error = set_one_prio(p, niceval, error);
+ if (who == p->pid || who == p->tgid) {
+printk("setting prio of pid %d tgid %d to %d\n", p->pid, p->tgid, niceval);
+ error = set_one_prio(p, niceval, error);
+ }
} while_each_pid_thread(pid, PIDTYPE_PID, p);
break;
case PRIO_PGRP:
@@ -231,18 +238,25 @@
niceval = 20 - task_nice(p);
if (niceval > retval)
retval = niceval;
+printk("PRIO_THREAD: pid %d tgid %d: niceval=%ld retval=%ld\n", p->pid, p->tgid, niceval, retval);
}
break;
case PRIO_PROCESS:
if (who)
pid = find_vpid(who);
- else
+ else {
pid = task_pid(current);
+ who = current->pid;
+ }
do_each_pid_thread(pid, PIDTYPE_PID, p) {
- niceval = 20 - task_nice(p);
- if (niceval > retval)
- retval = niceval;
+ if (who == p->pid || who == p->tgid) {
+ niceval = 20 - task_nice(p);
+ if (niceval > retval)
+ retval = niceval;
+printk("PRIO_PROCESS: pid %d tgid %d: niceval=%ld\n", p->pid, p->tgid, niceval);
+ }
} while_each_pid_thread(pid, PIDTYPE_PID, p);
+printk("PRIO_PROCESS: returning retval=%ld\n", retval);
break;
case PRIO_PGRP:
if (who)