efl/legacy
Lucas De Marchi 19c1b1e899 Fix priority dropping
Lowering priority was wrong. Some bugs:

1) You don't lower the priority by setting the scheduler policy to some
   of the real-time ones (SCHED_RR or SCHER_FIFO). If you do so, you are
   actually increasing the priority of the workers and your main thread
   you be preempted and stalled until the workers complete their job.
   Fortunately this will only happen if your programming is running as
   root, as normal users (without CAP_SYS_NICE) are unable to set
   priority to real-time values.

2) setpriority() and getpriority() are not part of pthread and you can't
   use the id returned by pthread. Manpage explicitly says so on
   pthread_self(3):
   "The  thread ID returned by pthread_self() is not the same thing as the
       kernel thread ID returned by a call to gettid(2)."

   Since glibc does not have a gettid, here we are using
   syscall(SYS_gettid)

This patch was tested with the program below. Compile and run:
   $ gcc p_hello2.c -o p_hello2 -lpthread
   $ ./p_hello2 10

You'll see that the main thread remains with its priority and threads
created by the main thread change their own niceness.

 #include <errno.h>
 #include <pthread.h>
 #include <sched.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/resource.h>
 #include <sys/syscall.h>
 #include <sys/time.h>
 #include <sys/types.h>

/* Lower priority of current thread.
 *
 * It's used by worker threads so they use up "bg cpu" as it was really intended
 * to work. If current thread is running with real-time priority, we decrease
 * our priority by 5. This is done in a portable way.  Otherwise we are
 * running with SCHED_OTHER policy and there's no portable way to set the nice
 * level on current thread. In Linux, it does work and it's the only one that is
 * implemented.
 */
static void
_ecore_thread_pri_drop(void)
{
   struct sched_param param;
   int pol, prio, ret;
   pid_t tid;
   pthread_t pthread_id;

   pthread_id = pthread_self();
   ret = pthread_getschedparam(pthread_id, &pol, &param);
   if (ret)
     {
        fprintf(stderr, "Unable to query sched parameters\n");
        return;
     }

   if (pol == SCHED_RR || pol == SCHED_FIFO)
     {
        prio = sched_get_priority_max(pol);
        param.sched_priority += 5;
        if (prio > 0 && param.sched_priority > prio)
           param.sched_priority = prio;

        pthread_setschedparam(pthread_id, pol, &param);
     }
 #ifdef __linux__
   else
     {
        tid = syscall(SYS_gettid);
        errno = 0;
        prio = getpriority(PRIO_PROCESS, tid);
        if (errno == 0)
          {
             prio += 5;
             if (prio > 19)
                prio = 19;

             setpriority(PRIO_PROCESS, tid, prio);
          }
     }
 #endif
}

/*
 * p_hello.c -- a hello program (in pthread)
 */
 #define MAX_THREAD 1000

typedef struct {
    int id;
} parm;

void *hello(void *arg)
{
    parm *p=(parm *)arg;
    pid_t tid;
    int prio;
    tid =  syscall(SYS_gettid);
    printf("[%d] Hello from node %d\n", tid, p->id);
    pthread_yield();

    printf("[%d] HELLO!\n", tid);

    _ecore_thread_pri_drop();

    prio = getpriority(PRIO_PROCESS, tid);
    printf("[%d] New nice value: %d\n", tid, prio);
    return (NULL);
}

int main(int argc, char* argv[]) {
    int n,i;
    pthread_t *threads;
    pthread_attr_t pthread_custom_attr;
    parm *p;

    pid_t tid;
    int prio;

    if (argc != 2)
    {
        printf ("Usage: %s n\n  where n is no. of threads\n",argv[0]);
        exit(1);
    }

    n=atoi(argv[1]);

    if ((n < 1) || (n > MAX_THREAD)) {
        printf ("The no of thread should between 1 and %d.\n",MAX_THREAD);
        exit(1);
    }

    threads = (pthread_t *)malloc(n * sizeof(*threads));
    pthread_attr_init(&pthread_custom_attr);

    p = (parm *)malloc(n * sizeof(parm));
    /* Start up thread */

    tid = syscall(SYS_gettid);
    for (i=0; i<n; i++) {
        prio = getpriority(PRIO_PROCESS, tid);
        printf("[%d] root thread nice value: %d\n", tid, prio);

        p[i].id=i;
        pthread_create(&threads[i], &pthread_custom_attr, hello, (void *)(p+i));
    }

    /* Synchronize the completion of each thread. */

    for (i=0; i<n; i++) {
        pthread_join(threads[i],NULL);
    }
    free(p);

    return 0;
}



SVN revision: 52040
2010-09-09 12:45:39 +00:00
..
ecore Fix priority dropping 2010-09-09 11:48:31 +00:00
edje * edje: cleanup collection early if the file is dangling. 2010-09-08 13:45:21 +00:00
eet Fix common misspellings 2010-09-08 03:26:19 +00:00
eeze Fix stringshare usage in eeze_udev_test 2010-09-07 10:48:25 +00:00
efreet Fix common misspellings 2010-09-08 11:27:59 +00:00
eina Fix common misspellings 2010-09-09 02:19:54 +00:00
eio * eio: make it compile on Windows. Thanks Vincent ! 2010-09-07 15:47:11 +00:00
embryo Fix common misspellings 2010-09-08 03:33:11 +00:00
emotion * emotion: fix build of static module. 2010-08-30 16:18:11 +00:00
ethumb Ethumb: make distcheck fixes 2010-09-02 20:12:08 +00:00
evas Fix priority dropping 2010-09-09 12:45:39 +00:00
evil remove -pedantic, too much noise 2010-08-23 06:53:43 +00:00