7

I need to manage a pool of threads having different priorities, so I wrote the following thread startup procedure:

static
int startup(thrd_t *thrd, thrd_sync_t *sync, int prio)
{
    pthread_attr_t attr;
    int err;
    struct sched_param param = {
        .sched_priority = prio
    };

    assert(pthread_attr_init(&attr) == 0);
    assert(pthread_attr_setschedpolicy(&attr, SCHED_FIFO) == 0);
    assert(pthread_attr_setschedparam(&attr, &param) == 0);
    err = pthread_create(&thrd->handler, &attr, thread_routine, (void *)thrd);
    pthread_attr_destroy(&attr);

    return err;
}

In principle the unprivileged user should not be allowed to execute this code: the pthread_create() call should return EPERM because of the security implications of running a thread with high priority.

Unexpectedly it works for the normal user, but it doesn't respect the given priority at all.

I tried to modify the code by removing the pthread_attr_t and by setting the scheduling attribute once the thread has been created:

static
int startup(thrd_t *thrd, thrd_sync_t *sync, int prio)
{
    pthread_attr_t attr;
    int err;
    struct sched_param param = {
        .sched_priority = prio
    };

    err = pthread_create(&thrd->handler, NULL /*&attr*/, thread_routine,
                         (void *)thrd);
    if (err != 0) return err;

    err = pthread_setschedparam(thrd->handler, SCHED_FIFO, &param);
    if (err != 0) return err;

    return err;
}

This approach by the way is much more difficult to manage, since in case of error I need to kill the newly created thread. At least it seems to work properly with respect to permission requirements (only root can execute this), but still priorities are not respected.

Am I doing something wrong?

EDIT

I've just added the following piece of code which is executed by every thread:

static
void getinfo ()
{
    struct sched_param param;
    int policy;

    sched_getparam(0, &param);
    DEBUG_FMT("Priority of this process: %d", param.sched_priority);

    pthread_getschedparam(pthread_self(), &policy, &param);

    DEBUG_FMT("Priority of the thread: %d, current policy is: %d and should be %d",
              param.sched_priority, policy, SCHED_FIFO);
}

With the first method (namely pthread_attr_t approach) it turns out that the pthread_attr_setschedpolicy is totally not effective, since the priority is 0 and the policy is not SCHED_FIFO.

With the second method (namely pthread_setschedparam approach) the function prints the expected data, but the execution keeps behaving in a wrong way.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Dacav
  • 13,590
  • 11
  • 60
  • 87
  • 1
    How do you determine the calls aren't respected? I've encountered something similar, but the API was simply not implemented and failed as such. – Ioan Jul 08 '10 at 19:56
  • @Ioan: See the updated version of the question. – Dacav Jul 08 '10 at 20:17
  • 2
    OT: don't put code inside `assert()`. If this is compiled with assert disabled, the code will not be executed. – bstpierre Jul 15 '10 at 17:04
  • @bstpierre: Really? Thanks for this information! I used to do this a lot in my code, expecially in order to check malloc() to return something not NULL! So it seems it's time for hard fixes in all my libraries, I owe you a beer! – Dacav Jul 16 '10 at 10:53
  • 1
    if `NDEBUG` is defined, `assert(x)` is a noop. – bstpierre Jul 16 '10 at 14:37

1 Answers1

9

I think you also have to use pthread_attr_setinheritsched to ensure that your changes to the priority setting are taken into account. From the man page:

PTHREAD_INHERIT_SCHED Specifies that the scheduling policy and associated attributes are to be inherited from the creating thread, and the scheduling attributes in this attr argument are to be ignored.

PTHREAD_EXPLICIT_SCHED Specifies that the scheduling policy and associated attributes are to be set to the corresponding values from this attribute object.

And a little bit further in the man page, you have :

The default setting of the inherit-scheduler attribute in a newly initialized thread attributes object is PTHREAD_INHERIT_SCHED.

Loufylouf
  • 697
  • 5
  • 13
Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • It worked! Thanks a lot: this solves one of the two problems. However it's rather counterintuitive: if I'm specifying you a priority, probably it's because I want you to use it, right? :) Now I shall find the reason of the wrong behavior: maybe a bug? – Dacav Jul 08 '10 at 21:39
  • @Dacav: could you elaborate your second problem a bit more? not sure that I get it. Bugs in that area (but your own ;-) are very unlikely. You didn't say much about the system you are running, but nowadays thread implementations are really well tested billions of times every day. – Jens Gustedt Jul 08 '10 at 21:44
  • for the moment my program is just a scaffold: real business logic shall be added later. In order to test the priority every thread starts by waiting on a condition variable, which is subsequently broadcasted. Then every thread keeps writing bogus on stderr. What I expect is watching at higher priority threads' bogus before lower priority threads' one. I suspect that my dual-core is responsible of unexpected interleaving... I'm thinking about a good test, right now. – Dacav Jul 08 '10 at 21:59
  • lol, now I got it :). By saying “maybe a bug” I mean “maybe a bug *in my code*”. I usually absume the library code to be correct. :) – Dacav Jul 08 '10 at 22:17