diff options
-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)); } |