From a95105a888dac0e13dc3e05c2c177efb20c5701d Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Thu, 23 Sep 2010 20:38:48 +0000 Subject: [PATCH] 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 --- legacy/eina/src/include/Eina.h | 1 + legacy/eina/src/include/Makefile.am | 1 + legacy/eina/src/include/eina_sched.h | 26 +++++++ legacy/eina/src/lib/Makefile.am | 1 + legacy/eina/src/lib/eina_sched.c | 93 +++++++++++++++++++++++++ legacy/eina/src/tests/Makefile.am | 1 + legacy/eina/src/tests/eina_suite.c | 1 + legacy/eina/src/tests/eina_suite.h | 1 + legacy/eina/src/tests/eina_test_sched.c | 85 ++++++++++++++++++++++ 9 files changed, 210 insertions(+) create mode 100644 legacy/eina/src/include/eina_sched.h create mode 100644 legacy/eina/src/lib/eina_sched.c create mode 100644 legacy/eina/src/tests/eina_test_sched.c diff --git a/legacy/eina/src/include/Eina.h b/legacy/eina/src/include/Eina.h index dad45a2f67..eb0263f6c2 100644 --- a/legacy/eina/src/include/Eina.h +++ b/legacy/eina/src/include/Eina.h @@ -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" diff --git a/legacy/eina/src/include/Makefile.am b/legacy/eina/src/include/Makefile.am index 98b12f276b..f04b2978f8 100644 --- a/legacy/eina/src/include/Makefile.am +++ b/legacy/eina/src/include/Makefile.am @@ -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 \ diff --git a/legacy/eina/src/include/eina_sched.h b/legacy/eina/src/include/eina_sched.h new file mode 100644 index 0000000000..607b9f5b85 --- /dev/null +++ b/legacy/eina/src/include/eina_sched.h @@ -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 . + */ + +#ifndef EINA_SCHED_H_ +#define EINA_SCHED_H_ + +#include "eina_types.h" + +EAPI void eina_sched_prio_drop(void); + +#endif /* EINA_SCHED_H_ */ diff --git a/legacy/eina/src/lib/Makefile.am b/legacy/eina/src/lib/Makefile.am index 70185498ec..49587d3414 100644 --- a/legacy/eina/src/lib/Makefile.am +++ b/legacy/eina/src/lib/Makefile.am @@ -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 \ diff --git a/legacy/eina/src/lib/eina_sched.c b/legacy/eina/src/lib/eina_sched.c new file mode 100644 index 0000000000..d1c84de495 --- /dev/null +++ b/legacy/eina/src/lib/eina_sched.c @@ -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 . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef EFL_HAVE_THREADS +# include +# ifdef __linux__ +# include +# include +# include +# include +# 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, ¶m); + 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, ¶m); + } +#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 +} diff --git a/legacy/eina/src/tests/Makefile.am b/legacy/eina/src/tests/Makefile.am index a414348dd6..b0a3f8e37b 100644 --- a/legacy/eina/src/tests/Makefile.am +++ b/legacy/eina/src/tests/Makefile.am @@ -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 \ diff --git a/legacy/eina/src/tests/eina_suite.c b/legacy/eina/src/tests/eina_suite.c index 78f2d8ac96..39584408fe 100644 --- a/legacy/eina/src/tests/eina_suite.c +++ b/legacy/eina/src/tests/eina_suite.c @@ -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 } }; diff --git a/legacy/eina/src/tests/eina_suite.h b/legacy/eina/src/tests/eina_suite.h index b63cb608ce..c7dedca8e8 100644 --- a/legacy/eina/src/tests/eina_suite.h +++ b/legacy/eina/src/tests/eina_suite.h @@ -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_ */ diff --git a/legacy/eina/src/tests/eina_test_sched.c b/legacy/eina/src/tests/eina_test_sched.c new file mode 100644 index 0000000000..19c187fa72 --- /dev/null +++ b/legacy/eina/src/tests/eina_test_sched.c @@ -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 . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if defined(EFL_HAVE_THREADS) && defined __linux__ +#include +#include +#include +#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); +}