diff options
author | Lennart Poettering <lennart@poettering.net> | 2007-09-02 20:36:32 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2007-09-02 20:36:32 +0000 |
commit | 2f7b6fead11e781e6071df09ea1c3ae2cadb845c (patch) | |
tree | f5cf42be31b56a1c31c4cfe1252fa20787768873 | |
parent | 8cf822a3d9d73f3c273ac64976995b8d3fc1fa47 (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.c | 70 | ||||
-rw-r--r-- | src/pulsecore/core-util.h | 2 |
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)); } |