summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2007-09-02 20:36:32 +0000
committerLennart Poettering <lennart@poettering.net>2007-09-02 20:36:32 +0000
commit2f7b6fead11e781e6071df09ea1c3ae2cadb845c (patch)
treef5cf42be31b56a1c31c4cfe1252fa20787768873
parent8cf822a3d9d73f3c273ac64976995b8d3fc1fa47 (diff)
add new pa_will_need() API for paging in memory
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1745 fefdeb5f-60dc-0310-8127-8f9354f1896f
-rw-r--r--src/pulsecore/core-util.c70
-rw-r--r--src/pulsecore/core-util.h2
2 files changed, 72 insertions, 0 deletions
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 82c0ea3c..d231b658 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -54,6 +54,10 @@
#include <sys/capability.h>
#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
#ifdef HAVE_PTHREAD
#include <pthread.h>
#endif
@@ -1241,3 +1245,69 @@ char *pa_make_path_absolute(const char *p) {
pa_xfree(cwd);
return r;
}
+
+void *pa_will_need(const void *p, size_t l) {
+#ifdef RLIMIT_MEMLOCK
+ struct rlimit rlim;
+#endif
+ const void *a;
+ size_t size;
+ int r;
+ size_t bs;
+
+ pa_assert(p);
+ pa_assert(l > 0);
+
+ a = PA_PAGE_ALIGN_PTR(p);
+ size = (const uint8_t*) p + l - (const uint8_t*) a;
+
+ if ((r = posix_madvise((void*) a, size, POSIX_MADV_WILLNEED)) == 0) {
+ pa_log_debug("posix_madvise() worked fine!");
+ return (void*) p;
+ }
+
+ /* Most likely the memory was not mmap()ed from a file and thus
+ * madvise() didn't work, so let's misuse mlock() do page this
+ * stuff back into RAM. Yeah, let's fuck with the MM! It's so
+ * inviting, the man page of mlock() tells us: "All pages that
+ * contain a part of the specified address range are guaranteed to
+ * be resident in RAM when the call returns successfully." */
+
+#ifdef RLIMIT_MEMLOCK
+ pa_assert_se(getrlimit(RLIMIT_MEMLOCK, &rlim) == 0);
+
+ if (rlim.rlim_cur < PA_PAGE_SIZE) {
+ pa_log_debug("posix_madvise() failed, resource limits don't allow mlock(), can't page in data: %s", pa_cstrerror(r));
+ return (void*) p;
+ }
+
+ bs = PA_PAGE_ALIGN(rlim.rlim_cur);
+#else
+ bs = PA_PAGE_SIZE*4;
+#endif
+
+ pa_log_debug("posix_madvise() failed, trying mlock(): %s", pa_cstrerror(r));
+
+ while (size > 0 && bs > 0) {
+
+ if (bs > size)
+ bs = size;
+
+ if (mlock(a, bs) < 0) {
+ bs = PA_PAGE_ALIGN(bs / 2);
+ continue;
+ }
+
+ pa_assert_se(munlock(a, bs) == 0);
+
+ a = (const uint8_t*) a + bs;
+ size -= bs;
+ }
+
+ if (bs <= 0)
+ pa_log_debug("mlock() failed too, giving up: %s", pa_cstrerror(errno));
+ else
+ pa_log_debug("mlock() worked fine!");
+
+ return (void*) p;
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 54749280..fcafe63d 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -100,6 +100,8 @@ char *pa_truncate_utf8(char *c, size_t l);
char *pa_getcwd(void);
char *pa_make_path_absolute(const char *p);
+void *pa_will_need(const void *p, size_t l);
+
static inline int pa_is_power_of_two(unsigned n) {
return !(n & (n - 1));
}