Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 Jul 2011 14:37:02 +0400
From:      Dmitry Krivenok <krivenok.dmitry@gmail.com>
To:        freebsd-hackers@freebsd.org
Subject:   pri_to_rtp returns invalid initial priority
Message-ID:  <CAJN_NGbep3qtsGO17F7GRsKUZLEaL%2B0-MF=Br5=yFy-ON8OTYg@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
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@gmail.com
skype: krivenok_dmitry
jabber: krivenok_dmitry@jabber.ru
icq: 242-526-443



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJN_NGbep3qtsGO17F7GRsKUZLEaL%2B0-MF=Br5=yFy-ON8OTYg>