Implement function to drop priority of current thread
authorlucas <lucas@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 23 Sep 2010 20:38:48 +0000 (20:38 +0000)
committerlucas <lucas@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 23 Sep 2010 20:38:48 +0000 (20:38 +0000)
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.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/eina@52651 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/include/Eina.h
src/include/Makefile.am
src/include/eina_sched.h [new file with mode: 0644]
src/lib/Makefile.am
src/lib/eina_sched.c [new file with mode: 0644]
src/tests/Makefile.am
src/tests/eina_suite.c
src/tests/eina_suite.h
src/tests/eina_test_sched.c [new file with mode: 0644]

index dad45a2..eb0263f 100644 (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"
index 98b12f2..f04b297 100644 (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 \
diff --git a/src/include/eina_sched.h b/src/include/eina_sched.h
new file mode 100644 (file)
index 0000000..607b9f5
--- /dev/null
@@ -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_ */
index 7018549..49587d3 100644 (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 \
diff --git a/src/lib/eina_sched.c b/src/lib/eina_sched.c
new file mode 100644 (file)
index 0000000..d1c84de
--- /dev/null
@@ -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
+}
index a414348..b0a3f8e 100644 (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     \
index 78f2d8a..3958440 100644 (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 }
 };
 
index b63cb60..c7dedca 100644 (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_ */
diff --git a/src/tests/eina_test_sched.c b/src/tests/eina_test_sched.c
new file mode 100644 (file)
index 0000000..19c187f
--- /dev/null
@@ -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);
+}