efl/legacy/ecore
Lucas De Marchi 325e08065d 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] tid=%lu\n", tid);

    _ecore_thread_pri_drop();

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

void 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);
}



SVN revision: 52039
2010-09-09 11:48:31 +00:00
..
debian update debian files too 2010-03-08 08:19:51 +00:00
doc Fix common misspellings 2010-09-08 11:23:42 +00:00
m4 Fix common misspellings 2010-09-08 11:23:42 +00:00
po and now ecore is 1.0.0 ready too. 2010-08-16 08:17:24 +00:00
src Fix priority dropping 2010-09-09 11:48:31 +00:00
.cvsignore split ecore.pc into multiple pc files, one for each sub module. 2007-03-21 15:30:23 +00:00
AUTHORS /me has done ecore-related thingies. 2010-06-23 08:53:54 +00:00
COPYING fix up copyings likewise. nicely standardised templateish. 2010-08-16 03:00:16 +00:00
ChangeLog Wed Jun 8 16:56:30 2005 Michael Jennings (mej) 2005-06-08 20:51:06 +00:00
INSTALL and now ecore is 1.0.0 ready too. 2010-08-16 08:17:24 +00:00
Makefile.am again - pass distcheck! 2010-08-20 02:48:54 +00:00
NEWS damn you salizar! damn you! 2003-09-23 08:09:32 +00:00
README.in * ecore: add some information about Ecore_Thread. 2010-08-19 08:57:55 +00:00
autogen.sh Gettext support in Ecore_Getopt. Thanks to k-s :) 2009-09-01 14:15:37 +00:00
configure.ac Remove the possibility to build ecore_config (which was deprecated anyway). 2010-08-24 06:37:37 +00:00
ecore-cocoa.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-con.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-config.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-directfb.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-evas.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-fb.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-file.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-imf-evas.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-imf.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-input-evas.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-input.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-ipc.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-sdl.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-win32.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-wince.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore-x.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore.pc.in Move Ecore.h (and associated headers) to own dir. 2010-07-09 06:23:19 +00:00
ecore.spec.in Fix build on RHEL5. Please provide feedback for these changes as I 2010-05-12 18:19:11 +00:00
ecore.supp more suppressions 2004-10-19 16:40:25 +00:00

README.in

Ecore @VERSION@

******************************************************************************

 FOR ANY ISSUES PLEASE EMAIL:
 enlightenment-devel@lists.sourceforge.net
  
******************************************************************************
  
Requirements:
-------------

Must:
  libc
  libm
  eina (1.0.0 or better)
  (For windows you also need: evil)
  
Recommended:
  libX11
  libXext
  libXcursor
  libXprint
  libXinerama
  libXrandr
  libXss
  libXrender
  libXcomposite
  libXfixes
  libXdamage
  libXdpms
  libXtest
  OpenSSL
  CURL
  evas (1.0.0 or better)

Optional:
  XCB
  SDL
  DirectFB

Ecore is a clean and tiny event loop library with many modules to do
lots of convenient things for a programmer, to save time and effort.

It's small and lean, designed to work on embedded systems all the way
to large and powerful multi-cpu workstations. It serialises all system
signals, events etc. into a single event queue, that is easily
processed without needing to worry about concurrency. A properly
written, event-driven program using this kind of programming doesn't
need threads, nor has to worry about concurrency. It turns a program
into a state machine, and makes it very robust and easy to follow.

Ecore gives you other handy primitives, such as timers to tick over
for you and call specified functions at particular times so the
programmer can use this to do things, like animate, or time out on
connections or tasks that take too long etc.

Idle handlers are provided too, as well as calls on entering an idle
state (often a very good time to update the state of the program). All
events that enter the system are passed to specific callback functions
that the program sets up to handle those events. Handling them is
simple and other Ecore modules produce more events on the queue,
coming from other sources such as file descriptors etc.

Ecore also help you work in a multi threaded environment and setup a
thread pool that help you use the EFL on multi-cpu system. It help split
the part that can't be called outside of the ecore main loop from the
computation heavy function that could run on another CPU. Be aware that
Evas and most of Ecore API is not thread safe and should only be called
in the main loop. Eina and Eet could be used, if done carefully, in any
heavy function on another cpu.

Ecore also lets you have functions called when file descriptors become
active for reading or writing, allowing for streamlined, non-blocking
IO.

------------------------------------------------------------------------------
COMPILING AND INSTALLING:

  ./configure
  make
(as root unless you are installing in your users directories):
  make install