pri_to_rtp returns invalid initial priority

Dmitry Krivenok krivenok.dmitry at gmail.com
Thu Jul 7 10:37:03 UTC 2011


Hi Hackers,
I've developed a simple kld which demonstrates a problem I found on my
FreeBSD-8.2.

/////////////////////////////////////////////////////////////////////////////////////////////
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/pcpu.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/kthread.h>
#include <sys/uio.h>
#include <sys/cpuset.h>
#include <sys/types.h>
#include <sys/lock.h>
#include <sys/sema.h>

static struct sema sem;

/* ###########################################################################*/

static void
set_prio(
    struct thread *td,
    u_short type,
    u_short prio)
{
    struct rtprio rtp;
    int r;
    rtp.type = type;
    rtp.prio = prio;
    r = rtp_to_pri(&rtp, td);
    if (r != 0)
        printf("Unable to set priority of type %u to %u (error code:
%d).\n", type, prio, r);
}

/* ###########################################################################*/

static void
print_prio(
    struct thread *td,
    const char *prefix)
{
    struct rtprio rtp;
    pri_to_rtp(td, &rtp);
    printf("%s priority: %u, type: %u.\n", prefix, rtp.prio, rtp.type);
}

/* ###########################################################################*/

static void
set_and_print(
    struct thread *td,
    u_short type,
    u_short prio,
    const char *prefix)
{
    set_prio(td, type, prio);
    print_prio(td, prefix);
}

/* ###########################################################################*/

static void
kthread_run(
    void)
{
    struct thread *td = curthread;

    sema_wait(&sem);

    print_prio(td, "[NEW] Initial TS");
    set_and_print(td, RTP_PRIO_NORMAL, PRI_MIN_TIMESHARE -
PRI_MIN_TIMESHARE, "[NEW] Min TS");
    set_and_print(td, RTP_PRIO_NORMAL, (PRI_MAX_TIMESHARE -
PRI_MIN_TIMESHARE) / 2, "[NEW] Mid TS");
    set_and_print(td, RTP_PRIO_NORMAL, PRI_MAX_TIMESHARE -
PRI_MIN_TIMESHARE, "[NEW] Max TS");
    set_and_print(td, RTP_PRIO_REALTIME, RTP_PRIO_MIN - RTP_PRIO_MIN,
"[NEW] Min RT");
    set_and_print(td, RTP_PRIO_REALTIME, (RTP_PRIO_MAX - RTP_PRIO_MIN)
/ 2, "[NEW] Mid RT");
    set_and_print(td, RTP_PRIO_REALTIME, RTP_PRIO_MAX - RTP_PRIO_MIN,
"[NEW] Max RT");

    sema_destroy(&sem);
    kthread_exit();
}

/* ###########################################################################*/

static int
event_handler(
    struct module *module,
    int event,
    void *arg)
{
    if (event == MOD_LOAD) {
        struct kthread_desc desc;
        struct thread *td = curthread;
        desc.arg0 = "my_thr";
        desc.func = kthread_run;
        desc.global_threadpp = NULL;

        sema_init(&sem, 0, "my_sem");
        kthread_start(&desc);

        print_prio(td, "[MAIN] Initial TS");
        set_and_print(td, RTP_PRIO_NORMAL, PRI_MIN_TIMESHARE -
PRI_MIN_TIMESHARE, "[MAIN] Min TS");
        set_and_print(td, RTP_PRIO_NORMAL, (PRI_MAX_TIMESHARE -
PRI_MIN_TIMESHARE) / 2, "[MAIN] Mid TS");
        set_and_print(td, RTP_PRIO_NORMAL, PRI_MAX_TIMESHARE -
PRI_MIN_TIMESHARE, "[MAIN] Max TS");
        set_and_print(td, RTP_PRIO_REALTIME, RTP_PRIO_MIN -
RTP_PRIO_MIN, "[MAIN] Min RT");
        set_and_print(td, RTP_PRIO_REALTIME, (RTP_PRIO_MAX -
RTP_PRIO_MIN) / 2, "[MAIN] Mid RT");
        set_and_print(td, RTP_PRIO_REALTIME, RTP_PRIO_MAX -
RTP_PRIO_MIN, "[MAIN] Max RT");

        sema_post(&sem);
    }
    if (event == MOD_UNLOAD) {

    }
    return 0;
};

/* ###########################################################################*/

static moduledata_t thr_conf = {
    "thr",                                 /* module name */
    event_handler,                         /* event handler */
    NULL                                   /* extra data */
};

/* ###########################################################################*/

DECLARE_MODULE(thr, thr_conf, SI_SUB_KLD, SI_ORDER_ANY);
/////////////////////////////////////////////////////////////////////////////////////////////

On FreeBSD-8.2 I get the following results:

[MAIN] Initial TS priority: 65508, type: 3.
[MAIN] Min TS priority: 0, type: 3.
[MAIN] Mid TS priority: 31, type: 3.
[MAIN] Max TS priority: 63, type: 3.
[MAIN] Min RT priority: 0, type: 2.
[MAIN] Mid RT priority: 15, type: 2.
[MAIN] Max RT priority: 31, type: 2.
[NEW] Initial TS priority: 65504, type: 3.
[NEW] Min TS priority: 0, type: 3.
[NEW] Mid TS priority: 31, type: 3.
[NEW] Max TS priority: 63, type: 3.
[NEW] Min RT priority: 0, type: 2.
[NEW] Mid RT priority: 15, type: 2.
[NEW] Max RT priority: 31, type: 2.

[MAIN] Initial TS priority: 20, type: 3.
[MAIN] Min TS priority: 0, type: 3.
[MAIN] Mid TS priority: 31, type: 3.
[MAIN] Max TS priority: 63, type: 3.
[MAIN] Min RT priority: 0, type: 2.
[MAIN] Mid RT priority: 15, type: 2.
[MAIN] Max RT priority: 31, type: 2.
[NEW] Initial TS priority: 65504, type: 3.
[NEW] Min TS priority: 0, type: 3.
[NEW] Mid TS priority: 31, type: 3.
[NEW] Max TS priority: 63, type: 3.
[NEW] Min RT priority: 0, type: 2.
[NEW] Mid RT priority: 15, type: 2.
[NEW] Max RT priority: 31, type: 2.

[MAIN] Initial TS priority: 65531, type: 3.
[MAIN] Min TS priority: 0, type: 3.
[MAIN] Mid TS priority: 31, type: 3.
[MAIN] Max TS priority: 63, type: 3.
[MAIN] Min RT priority: 0, type: 2.
[MAIN] Mid RT priority: 15, type: 2.
[MAIN] Max RT priority: 31, type: 2.
[NEW] Initial TS priority: 65504, type: 3.
[NEW] Min TS priority: 0, type: 3.
[NEW] Mid TS priority: 31, type: 3.
[NEW] Max TS priority: 63, type: 3.
[NEW] Min RT priority: 0, type: 2.
[NEW] Mid RT priority: 15, type: 2.
[NEW] Max RT priority: 31, type: 2.

Note that initial priorities are almost always wrong (but sometimes
they are okay).
It looks like a negative priority was saved in rrprio.prio which is u_short.

I tried my kld on FreeBSD-CURRENT but got only correct results:

[MAIN] Initial TS priority: 52, type: 3.
[MAIN] Min TS priority: 0, type: 3.
[MAIN] Mid TS priority: 51, type: 3.
[MAIN] Max TS priority: 103, type: 3.
[MAIN] Min RT priority: 0, type: 2.
[MAIN] Mid RT priority: 15, type: 2.
[MAIN] Max RT priority: 31, type: 2.
[NEW] Initial TS priority: 0, type: 3.
[NEW] Min TS priority: 0, type: 3.
[NEW] Mid TS priority: 51, type: 3.
[NEW] Max TS priority: 103, type: 3.
[NEW] Min RT priority: 0, type: 2.
[NEW] Mid RT priority: 15, type: 2.
[NEW] Max RT priority: 31, type: 2.

[MAIN] Initial TS priority: 7, type: 3.
[MAIN] Min TS priority: 0, type: 3.
[MAIN] Mid TS priority: 51, type: 3.
[MAIN] Max TS priority: 103, type: 3.
[MAIN] Min RT priority: 0, type: 2.
[MAIN] Mid RT priority: 15, type: 2.
[MAIN] Max RT priority: 31, type: 2.
[NEW] Initial TS priority: 0, type: 3.
[NEW] Min TS priority: 0, type: 3.
[NEW] Mid TS priority: 51, type: 3.
[NEW] Max TS priority: 103, type: 3.
[NEW] Min RT priority: 0, type: 2.
[NEW] Mid RT priority: 15, type: 2.
[NEW] Max RT priority: 31, type: 2.

I guess either the problem was fixed in FreeBSD-CURRENT or it is still
in both 8.2 and CURRENT
but for some reason (e.g. race)  I cannot hit it on CURRENT.
The latter is unlikely (but still possible) because I run it lots of
times on CURRENT:
for ((i=0; i<10000; i++)) do sudo make load unload >/dev/null && dmesg
| tail -n 14 | grep "MAIN.*Initial" ; done
but didn't see the problem.

I tried to compare priority-related stuff in 8.2 and CURRENT tries but
didn't find a change
which could fix that problem.

Could someone more experienced in kernel programming please tell me
what is wrong here?
Is it a problem which was really fixed in CURRENT (when, where?) or is
it a bug which doesn't
show itself on my CURRENT box?

Thanks in advance!

P.S.
In case you want to reproduce this problem please save the code above
in thr.c and create the
following Makefile:
########################################################
# Declare Name of kernel module
KMOD    =  thr
# Enumerate Source files for kernel module
SRCS    =  thr.c
# Include kernel module makefile
.include <bsd.kmod.mk>
########################################################

Then type
$ make
$ sudo make load unload
$ dmesg | tail -n 14


-- 
Sincerely yours, Dmitry V. Krivenok
e-mail: krivenok.dmitry at gmail.com
skype: krivenok_dmitry
jabber: krivenok_dmitry at jabber.ru
icq: 242-526-443


More information about the freebsd-hackers mailing list