I/O priority support with cfq scheduler (needs new kernel patch)
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Sat, 17 Jun 2006 15:23:50 +0000 (15:23 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Sat, 17 Jun 2006 15:23:50 +0000 (15:23 +0000)
lib/base/Makefile.am
lib/base/filepush.cpp
lib/base/filepush.h
lib/base/ioprio.cpp [new file with mode: 0644]
lib/base/ioprio.h [new file with mode: 0644]
lib/components/file_eraser.cpp
lib/dvb/demux.cpp
lib/dvb/pvrparse.cpp
lib/dvb/tstools.cpp
main/enigma.cpp

index cd1a157..6ea9d03 100644 (file)
@@ -8,5 +8,5 @@ libenigma_base_a_SOURCES = \
        init.cpp message.cpp thread.cpp \
        smartptr.cpp estring.cpp connection.cpp \
        filepush.cpp encoding.cpp console.cpp rawfile.cpp \
-       nconfig.cpp
+       nconfig.cpp ioprio.cpp
 
index d12b8ef..554c784 100644 (file)
@@ -6,7 +6,8 @@
 
 #define PVR_COMMIT 1
 
-eFilePushThread::eFilePushThread(): m_messagepump(eApp, 0)
+eFilePushThread::eFilePushThread(int io_prio_class, int io_prio_level)
+       :prio_class(io_prio_class), prio(io_prio_level), m_messagepump(eApp, 0)
 {
        m_stop = 0;
        m_sg = 0;
@@ -21,6 +22,8 @@ static void signal_handler(int x)
 
 void eFilePushThread::thread()
 {
+       setIoPrio(prio_class, prio);
+
        off_t dest_pos = 0, source_pos = 0;
        size_t bytes_read = 0;
        
@@ -28,7 +31,7 @@ void eFilePushThread::thread()
        size_t current_span_remaining = 0;
        
        size_t written_since_last_sync = 0;
-       
+
        int already_empty = 0;
        eDebug("FILEPUSH THREAD START");
        
@@ -40,7 +43,6 @@ void eFilePushThread::thread()
        
        hasStarted();
        
-       dest_pos = lseek(m_fd_dest, 0, SEEK_CUR);
        source_pos = m_raw_source.lseek(0, SEEK_CUR);
        
                /* m_stop must be evaluated after each syscall. */
@@ -61,15 +63,16 @@ void eFilePushThread::thread()
                                // ... we would stop the thread
                        }
 
-//                     posix_fadvise(m_fd_dest, dest_pos, w, POSIX_FADV_DONTNEED);
-
-                       dest_pos += w;
                        written_since_last_sync += w;
-                       
-                       if (written_since_last_sync >= 2048*1024)
+
+                       if (written_since_last_sync >= 512*1024)
                        {
-                               fdatasync(m_fd_dest);
-                               written_since_last_sync = 0;
+                               int toflush = written_since_last_sync > 2*1024*1024 ?
+                                       2*1024*1024 : written_since_last_sync &~ 4095; // write max 2MB at once
+                               dest_pos = lseek(m_fd_dest, 0, SEEK_CUR);
+                               dest_pos -= toflush;
+                               posix_fadvise(m_fd_dest, dest_pos, toflush, POSIX_FADV_DONTNEED);
+                               written_since_last_sync -= toflush;
                        }
 
 //                     printf("FILEPUSH: wrote %d bytes\n", w);
@@ -145,7 +148,8 @@ void eFilePushThread::thread()
                }
 //             printf("FILEPUSH: read %d bytes\n", m_buf_end);
        }
-       
+       fdatasync(m_fd_dest);
+
        eDebug("FILEPUSH THREAD STOP");
 }
 
index 35671cd..0749cd4 100644 (file)
@@ -2,6 +2,7 @@
 #define __lib_base_filepush_h
 
 #include <lib/base/thread.h>
+#include <lib/base/ioprio.h>
 #include <libsig_comp.h>
 #include <lib/base/message.h>
 #include <sys/types.h>
@@ -16,8 +17,9 @@ public:
 
 class eFilePushThread: public eThread, public Object
 {
+       int prio_class, prio;
 public:
-       eFilePushThread();
+       eFilePushThread(int prio_class=IOPRIO_CLASS_BE, int prio_level=0);
        void thread();
        void stop();
        void start(int sourcefd, int destfd);
diff --git a/lib/base/ioprio.cpp b/lib/base/ioprio.cpp
new file mode 100644 (file)
index 0000000..2ada736
--- /dev/null
@@ -0,0 +1,78 @@
+#include <lib/base/ioprio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/ptrace.h>
+#include <asm/unistd.h>
+
+#include <lib/base/eerror.h>
+
+extern "C" int sys_ioprio_set(int, int, int);
+extern "C" int sys_ioprio_get(int, int);
+
+#if defined(__i386__)
+#define __NR_ioprio_set                289
+#define __NR_ioprio_get                290
+#elif defined(__ppc__)
+#define __NR_ioprio_set                273
+#define __NR_ioprio_get                274
+#elif defined(__x86_64__)
+#define __NR_ioprio_set                251
+#define __NR_ioprio_get                252
+#elif defined(__ia64__)
+#define __NR_ioprio_set                1274
+#define __NR_ioprio_get                1275
+#elif defined(__mips__)
+#define __NR_ioprio_set                4284
+#define __NR_ioprio_get                4285
+#else
+#error "Unsupported arch"
+#endif
+
+_syscall3(int, ioprio_set, int, which, int, who, int, ioprio);
+_syscall2(int, ioprio_get, int, which, int, who);
+
+#define IOPRIO_CLASS_SHIFT     13
+
+enum {
+       IOPRIO_WHO_PROCESS = 1,
+       IOPRIO_WHO_PGRP,
+       IOPRIO_WHO_USER,
+};
+
+const char *to_prio[] = { "none", "realtime", "best-effort", "idle", };
+
+void setIoPrio(int prio_class, int prio)
+{
+       if (prio_class < 0 || prio_class > 3)
+       {
+               eDebug("prio class(%d) out of valid range (0..3)", prio_class);
+               return;
+       }
+       if (prio < 0 || prio > 7)
+       {
+               eDebug("prio level(%d) out of range (0..7)", prio);
+               return;
+       }
+       if (ioprio_set(IOPRIO_WHO_PROCESS, 0 /*pid 0 .. current process*/, prio | prio_class << IOPRIO_CLASS_SHIFT) == -1)
+               eDebug("setIoPrio failed (%m) !");
+       else
+               eDebug("setIoPrio %s level %d ok", to_prio[prio_class], prio);
+}
+
+void printIoPrio()
+{
+       int pid = 0, ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid);
+
+       eDebug("pid=%d, %d", pid, ioprio);
+
+       if (ioprio == -1)
+               eDebug("ioprio_get(%m)");
+       else {
+               int ioprio_class = ioprio >> IOPRIO_CLASS_SHIFT;
+               ioprio = ioprio & 0xff;
+               eDebug("%s: prio %d", to_prio[ioprio_class], ioprio);
+       }
+}
diff --git a/lib/base/ioprio.h b/lib/base/ioprio.h
new file mode 100644 (file)
index 0000000..498a473
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __LIB_BASE_IOPRIO_H_
+#define __LIB_BASE_IOPRIO_H_
+
+void setIoPrio(int prio_class, int prio=7);
+void printIoPrio();
+
+enum {
+       IOPRIO_CLASS_NONE,
+       IOPRIO_CLASS_RT,
+       IOPRIO_CLASS_BE,
+       IOPRIO_CLASS_IDLE,
+};
+
+#endif // __LIB_BASE_IOPRIO_H_
index 6cacf04..ea68eb4 100644 (file)
@@ -1,4 +1,5 @@
 #include <lib/components/file_eraser.h>
+#include <lib/base/ioprio.h>
 #include <lib/base/eerror.h>
 #include <lib/base/init.h>
 #include <lib/base/init_num.h>
@@ -33,9 +34,15 @@ eBackgroundFileEraser::~eBackgroundFileEraser()
 void eBackgroundFileEraser::thread()
 {
        hasStarted();
+
        nice(5);
+
+       setIoPrio(IOPRIO_CLASS_BE, 7);
+
        reset();
+
        runLoop();
+
        stop_thread_timer.stop();
 }
 
@@ -68,7 +75,7 @@ void eBackgroundFileEraser::gotMessage(const Message &msg )
                                        eDebug("file %s erased", msg.filename);
                                free((char*)msg.filename);
                        }
-                       stop_thread_timer.start(2000, true); // stop thread in two seconds
+                       stop_thread_timer.start(1000, true); // stop thread in one seconds
                        break;
                case Message::quit:
                        quit(0);
index c6d3b10..b0d9b40 100644 (file)
@@ -412,7 +412,7 @@ private:
 };
 
 eDVBRecordFileThread::eDVBRecordFileThread()
-       : m_ts_parser(m_stream_info)
+       :eFilePushThread(IOPRIO_CLASS_RT, 7), m_ts_parser(m_stream_info)
 {
        m_current_offset = 0;
 }
index 4b8da89..a611332 100644 (file)
@@ -63,7 +63,7 @@ void eMPEGStreamInformation::fixupDiscontinuties()
        if (!m_access_points.size())
                return;
                
-       eDebug("Fixing discontinuities ...");
+//     eDebug("Fixing discontinuities ...");
 
                        /* if we have no delta at the beginning, extrapolate it */
        if ((m_access_points.find(0) == m_access_points.end()) && (m_access_points.size() > 1))
@@ -77,7 +77,7 @@ void eMPEGStreamInformation::fixupDiscontinuties()
                        tdiff *= first->first;
                        tdiff /= diff;
                        m_timestamp_deltas[0] = first->second - tdiff;
-                       eDebug("first delta is %08llx", first->second - tdiff);
+//                     eDebug("first delta is %08llx", first->second - tdiff);
                }
        }
 
@@ -92,16 +92,16 @@ void eMPEGStreamInformation::fixupDiscontinuties()
                
                if (llabs(diff) > (90000*5)) // 5sec diff
                {
-                       eDebug("%llx < %llx, have discont. new timestamp is %llx (diff is %llx)!", current, lastpts_t, i->second, diff);
+//                     eDebug("%llx < %llx, have discont. new timestamp is %llx (diff is %llx)!", current, lastpts_t, i->second, diff);
                        currentDelta = i->second - lastpts_t; /* FIXME: should be the extrapolated new timestamp, based on the current rate */
-                       eDebug("current delta now %llx, making current to %llx", currentDelta, i->second - currentDelta);
+//                     eDebug("current delta now %llx, making current to %llx", currentDelta, i->second - currentDelta);
                        m_timestamp_deltas[i->first] = currentDelta;
                }
                lastpts_t = i->second - currentDelta;
        }
        
        
-       eDebug("ok, found %d disconts.", m_timestamp_deltas.size());
+//     eDebug("ok, found %d disconts.", m_timestamp_deltas.size());
 
 #if 0  
        for (off_t x=0x25807E34ULL; x < 0x25B3CF70; x+= 100000)
index 4ee2626..87791c9 100644 (file)
@@ -36,7 +36,7 @@ int eDVBTSTools::openFile(const char *filename)
                m_use_streaminfo = 1;
        else
        {
-               eDebug("no recorded stream information available");
+//             eDebug("no recorded stream information available");
                m_use_streaminfo = 0;
        }
        
@@ -267,7 +267,7 @@ void eDVBTSTools::calcEnd()
                m_end_valid = 0;
                
                m_futile = 0;
-               eDebug("file size changed, recalc length");
+//             eDebug("file size changed, recalc length");
        }
        
        int maxiter = 10;
index 0600062..5a22110 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <lib/actions/action.h>
 #include <lib/driver/rc.h>
+#include <lib/base/ioprio.h>
 #include <lib/base/ebase.h>
 #include <lib/base/eerror.h>
 #include <lib/base/init.h>
@@ -191,7 +192,9 @@ int main(int argc, char **argv)
        printf("executing main\n");
        
        bsodCatchSignals();
-       
+
+       setIoPrio(IOPRIO_CLASS_BE, 3);
+
        python.execute("mytest", "__main__");
        
        if (exit_code == 5) /* python crash */