Bug 46119

Summary: Priority problems for SCHED_OTHER using pthreads
Product: Base System Reporter: steff <steff>
Component: standardsAssignee: freebsd-standards (Nobody) <standards>
Status: Open ---    
Severity: Affects Only Me CC: steff
Priority: Normal    
Version: Unspecified   
Hardware: Any   
OS: Any   

Description steff 2002-12-09 10:20:00 UTC
	The POSIX functions sched_get_priority_max and sched_get_priority_min, is used for retrieving the max and min priority for a given scheduling policy.
	When you compile and execute a C++ program containing the line {cout << "max SCHED_OTHER = " << sched_get_priority_max(SCHED_OTHER) 
	<< ", min SCHED_OTHER = " << sched_get_priority_min(SCHED_OTHER) << endl;} the output is "max SCHED_OTHER = 20, , min SCHED_OTHER = -20".
	However, when I try to set the priority for a pthread_attr_t to anything not within the range [0:31], the value is reset to 15. This suggests that
	fx. -15 is not a valid value for the priority of a SCHED_OTHER policed thread, even though the POSIX functions sched_get_priority_min/max has a 
	different opinion. I've tried to bypass the routines that set the priority for the pthread_attr_t-object using a sort of hack, and this actually
	enables me to set the value to what ever I wan't (since I'm bypassing any kind of errorchecking). But when I attempt to create a thread using this
	pthread_attr_t-object the core is dumped. So basically, I can't create threads with priorities other then [0:31] eventhough sched_get_priority_min/max
	says I should be able to.

Fix: 

Well that really depends wether its the sched_get_priority_min/max macros that is incorrect or its the core functions of freeBSD.
	My knowledge of FreeBSD or any kind of UNIX type-OS dates only 4 months back, so I'm not really the right person to ask about this.
How-To-Repeat: 
    #include <iostream.h>
    #include <pthread.h>
    #include <errno.h>
    #include <time.h>

    //This is our own copy of the struct defined in the freebsd-cvs repository, in the pthread library, prefixed with 'snuf_'
    struct snuf_pthread_attr {
        int sched_policy;
        int sched_inherit;
        int sched_interval;
        int prio;
        int suspend;
        int flags;
        void    *arg_attr;
        void    (*cleanup_attr) ();
        void    *stackaddr_attr;
        size_t  stacksize_attr;
        size_t  guardsize_attr;
    };


void main()
{
    pthread_t dummy;
    pthread_attr_t p_attr;
    struct sched_param schedparam;
    pthread_attr_init(&p_attr);
    pthread_attr_setdetachstate(&p_attr,PTHREAD_CREATE_DETACHED);
    pthread_attr_setinheritsched(&p_attr,PTHREAD_EXPLICIT_SCHED);
    int code = pthread_attr_setschedpolicy(&p_attr, SCHED_OTHER);
    if ( code != 0 )
    {
        printf("Policy couldn't be set: %d\n", code );
        if ( code == EINVAL )
        {
            printf( "[EINVAL].\n" );

            exit( 0 );
        }
        if ( code == ENOTSUP )
        {
            printf( "[ENOTSUP].\n" );

            exit( 0 );
        }

    }
    cout << "max SCHED_OTHER = " << sched_get_priority_max(SCHED_OTHER) << ", min SCHED_OTHER = " << sched_get_priority_min(SCHED_OTHER) << endl;
    schedparam.sched_priority = -15;				//Attempting to set priority to -15
    pthread_attr_setschedparam(&p_attr, &schedparam);
    if ( code != 0 )
    {
        printf("pthread_attr_setschedparam failed: %d\n", code );
        if ( code == EINVAL )
        {
            printf( "[EINVAL].\n" );

            exit( 0 );
        }
        if ( code == ENOTSUP )
        {
            printf( "[ENOTSUP].\n" );

            exit( 0 );
        }
    }
    //Read the value of the structmember prio using the snuf-struct..
    cout << "address: " << p_attr << " prio would be: " << ((snuf_pthread_attr *)(p_attr))->prio << endl;
    //You can attempt to set the value of prio without any of the errorchecking provided by pthread_attr_setschedparam function
    //but this should first be attempted when you've certified that the pthread_attr_setschedparam isn't able to set the priovalue
    //to anything other then [0:31]
    //((snuf_pthread_attr *)(p_attr))->prio = 0;
    
    //Reading the value of the parameter:
    code = pthread_attr_getschedparam(&p_attr, &schedparam);
    if ( code != 0 )
    {
        printf("Thread pthread_attr_getschedparam Failed: %d\n", code );
        if ( code == EINVAL )
        {
            printf( "[EINVAL] -> Report this as a bug.\n" );

            exit( 0 );
        }
    }
    cout << "Read the schedparam.prio to: " << schedparam.priority << endl;

    cout << "CREATING THREAD NOW!!!!\n";
    code = pthread_create(&dummy, &p_attr, (void *(*)(void*))(INSERT_YOUR_OWN_FUNCTION_HERE), (void*)0);
    if ( code != 0 )
    {
        printf("Thread Creation Failed: %d\n", code );
        if ( code == EAGAIN )
        {
            printf( "[EAGAIN] -> Report this as a bug.\n" );

            exit( 0 );
        }
    }

    pthread_attr_destroy(&p_attr);
    sleep(10);	//Sleeping so that the program doesn't exit right away..
}
Comment 1 David Xu freebsd_committer freebsd_triage 2006-11-27 03:02:52 UTC
I really would like to see SCHED_OTHER only returns one level of
priority, that means, for sched_get_priority_min(SCHED_OTHER) and
sched_get_priority_max(SCHED_OTHER), it will return only zero
instead of other ranges, because for time-sharing scheduling,
knowing and adjusting thread's userland priority is meaningless,
the priority is ephemeral.

David Xu
Comment 2 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 08:01:21 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped