This code is here to prevent the premature death of thread when
apps killall of them, before recreating them again. This avoid
call to pthread_create and increase throughput. The only information
that I couldn't determine pragmatically is the timing. So that's
the time the main loop has to create another Ecore_Thread, before
needing to call pthread_create again.
SVN revision: 54633
match ecore_thread_feedback_run better.
NOTE: I know it breaks API/ABI compatibility for that call,
but that's the only sane solution I could found.
SVN revision: 53370
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, ¶m);
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, ¶m);
}
#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
note: I've chosen to consolidate typedefs where possible to simplify things
my time is limited this week, so feel free to expand on the doxy stubs I've added if you know what they do
SVN revision: 50803
TO FUTURE MIKE: you were too tired to update the doxy last night and instead of writing the doxy updates you fell asleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
SVN revision: 50682
NOTE: if you build ecore without pthread support, you really should know
that it is a bad idea. Only people without pthread support on their
device/C library should disable it.
SVN revision: 50200
that still integrate cleanly with the EFL.
ecore_thread_run need two callbacks :
* func_heavy is called from another thread and should not use the
EFL except Eina, but carefully.
* func_end is called when func_heavy is done, but from inside ecore
main loop, so you can at this point call every EFL functions without
fear.
Note :
The system automatically detect how many CPU you have and will spread
the load on all of them.
You must not assume that the result will come in the same order you
requested it. Depend on each CPU load and how heavy the function on it
are.
SVN revision: 41555