Implement function to drop priority of current thread

This function is useful for libraries like ecore and evas that have to
set some worker threads. The first thing these threads should do is to
call this function, so the main thread might continue running without
the worker threads interrupting it too much.



SVN revision: 52651
This commit is contained in:
Lucas De Marchi 2010-09-23 20:38:48 +00:00
parent 54a6fa2a68
commit a95105a888
9 changed files with 210 additions and 0 deletions

View File

@ -148,6 +148,7 @@ extern "C" {
#include "eina_benchmark.h"
#include "eina_convert.h"
#include "eina_cpu.h"
#include "eina_sched.h"
#include "eina_tiler.h"
#include "eina_hamster.h"
#include "eina_matrixsparse.h"

View File

@ -42,6 +42,7 @@ eina_trash.h \
eina_iterator.h \
eina_main.h \
eina_cpu.h \
eina_sched.h \
eina_tiler.h \
eina_hamster.h \
eina_matrixsparse.h \

View File

@ -0,0 +1,26 @@
/* EINA - EFL data type library
* Copyright (C) 2010 ProFUSION embedded systems
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EINA_SCHED_H_
#define EINA_SCHED_H_
#include "eina_types.h"
EAPI void eina_sched_prio_drop(void);
#endif /* EINA_SCHED_H_ */

View File

@ -37,6 +37,7 @@ eina_binshare.c \
eina_stringshare.c \
eina_ustringshare.c \
eina_cpu.c \
eina_sched.c \
eina_tiler.c \
eina_hamster.c \
eina_safety_checks.c \

View File

@ -0,0 +1,93 @@
/* EINA - EFL data type library
* Copyright (C) 2010 ProFUSION embedded systems
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef EFL_HAVE_THREADS
# include <pthread.h>
# ifdef __linux__
# include <sched.h>
# include <sys/time.h>
# include <sys/resource.h>
# include <errno.h>
# endif
#endif
#include "eina_log.h"
#define RTNICENESS 5
#define NICENESS 5
/**
* @brief Lower priority of current thread.
*
* It's used by worker threads so they use up background cpu and do not stall
* the main thread If current thread is running with real-time priority, we
* decrease our priority by @c RTNICENESS. This is done in a portable way.
*
* Otherwise (we are running with SCHED_OTHER policy) 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 as of now. In this case the nice level is
* incremented on this thread by @c NICENESS.
*/
EAPI void
eina_sched_prio_drop(void)
{
#ifdef EFL_HAVE_THREADS
struct sched_param param;
int pol, prio, ret;
pthread_t pthread_id;
pthread_id = pthread_self();
ret = pthread_getschedparam(pthread_id, &pol, &param);
if (ret)
{
EINA_LOG_ERR("Unable to query sched parameters");
return;
}
if (EINA_UNLIKELY(pol == SCHED_RR || pol == SCHED_FIFO))
{
prio = sched_get_priority_max(pol);
param.sched_priority += RTNICENESS;
if (prio > 0 && param.sched_priority > prio)
param.sched_priority = prio;
pthread_setschedparam(pthread_id, pol, &param);
}
#ifdef __linux__
else
{
errno = 0;
prio = getpriority(PRIO_PROCESS, 0);
if (errno == 0)
{
prio += NICENESS;
if (prio > 19)
prio = 19;
setpriority(PRIO_PROCESS, 0, prio);
}
}
#endif
#else
EINA_LOG_ERR("Eina does not have support for threads enabled");
#endif
}

View File

@ -39,6 +39,7 @@ eina_test_ustr.c \
eina_test_binshare.c \
eina_test_array.c \
eina_test_error.c \
eina_test_sched.c \
eina_test_log.c \
eina_test_magic.c \
eina_test_inlist.c \

View File

@ -62,6 +62,7 @@ static const Eina_Test_Case etc[] = {
{ "String", eina_test_str },
{ "Unicode String", eina_test_ustr },
{ "QuadTree", eina_test_quadtree },
{ "Sched", eina_test_sched },
{ NULL, NULL }
};

View File

@ -50,5 +50,6 @@ void eina_test_str(TCase *tc);
void eina_test_ustr(TCase *tc);
void eina_test_quadtree(TCase *tc);
void eina_test_fp(TCase *tc);
void eina_test_sched(TCase *tc);
#endif /* EINA_SUITE_H_ */

View File

@ -0,0 +1,85 @@
/* EINA - EFL data type library
* Copyright (C) 2008 Cedric Bail
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library;
* if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#if defined(EFL_HAVE_THREADS) && defined __linux__
#include <pthread.h>
#include <errno.h>
#include <sys/resource.h>
#endif
#include "eina_suite.h"
#include "Eina.h"
#if defined(EFL_HAVE_THREADS) && defined __linux__
/*
* TODO: Test if RT priorities are right. However, make check should be run as
* root.
*/
static void *
_thread_run(void *arg __UNUSED__)
{
int niceval = getpriority(PRIO_PROCESS, 0);
int niceval2;
eina_sched_prio_drop();
niceval2 = getpriority(PRIO_PROCESS, 0);
fail_if((niceval2 != 19) && (niceval2 != niceval+5));
return NULL;
}
START_TEST(eina_test_sched_prio_drop)
{
int niceval = getpriority(PRIO_PROCESS, 0);
int niceval2;
pthread_t tid;
eina_init();
pthread_create(&tid, NULL, _thread_run, NULL);
niceval2 = getpriority(PRIO_PROCESS, 0);
/* niceness of main thread should not have changed */
fail_if(niceval2 != niceval);
pthread_join(tid, NULL);
/* niceness of main thread should not have changed */
fail_if(niceval2 != niceval);
eina_shutdown();
}
END_TEST
#else
START_TEST(eina_test_sched_prio_drop)
{
fail_if(1);
}
END_TEST
#endif
void
eina_test_sched(TCase *tc)
{
tcase_add_test(tc, eina_test_sched_prio_drop);
}