mmap-cache.c revision f65425cbc4385b4f5b20ded641cbb07ad6a0938f
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen This file is part of systemd.
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen Copyright 2012 Lennart Poettering
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen systemd is free software; you can redistribute it and/or modify it
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen under the terms of the GNU Lesser General Public License as published by
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen (at your option) any later version.
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen systemd is distributed in the hope that it will be useful, but
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen Lesser General Public License for more details.
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen You should have received a copy of the GNU Lesser General Public License
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
a2ba62c719224a4b47751623ca5e8b0333f49721Lennart Poettering#define WINDOW_SIZE (8ULL*1024ULL*1024ULL)
09bee74d7a5f266b175baa19892fa84a9da51d7fTom Gundersentypedef struct Window {
09bee74d7a5f266b175baa19892fa84a9da51d7fTom Gundersentypedef struct FileDescriptor {
e1ea665edac17d75fce01b72dadfa3211b60df2cEugene Yakubovichstatic int mmap_cache_peek_fd_index(MMapCache *m, int fd, unsigned *fd_index);
e1ea665edac17d75fce01b72dadfa3211b60df2cEugene Yakubovichstatic void mmap_cache_window_unmap(MMapCache *m, unsigned w) {
e1ea665edac17d75fce01b72dadfa3211b60df2cEugene Yakubovichstatic void mmap_cache_window_add_lru(MMapCache *m, unsigned w) {
e1ea665edac17d75fce01b72dadfa3211b60df2cEugene Yakubovich assert(m->windows[m->lru_last].lru_next == (unsigned) -1);
e1ea665edac17d75fce01b72dadfa3211b60df2cEugene Yakubovichstatic void mmap_cache_window_remove_lru(MMapCache *m, unsigned w) {
12e0f830f592ec4c6bb49ac7ae1e0e84f74105e3Tom Gundersen assert(m->windows[v->lru_prev].lru_next == w);
7c99d940c11e4da1863a218b6b70dd16e65b7518Tom Gundersen m->windows[v->lru_prev].lru_next = v->lru_next;
12e0f830f592ec4c6bb49ac7ae1e0e84f74105e3Tom Gundersen assert(m->windows[v->lru_next].lru_prev == w);
5347925a59530bd4e6616eb8c8d43a02c3e14c46Tom Gundersen m->windows[v->lru_next].lru_prev = v->lru_prev;
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic void mmap_cache_fd_add(MMapCache *m, unsigned fd_index, unsigned w) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen if (m->by_fd[fd_index].windows != (unsigned) -1) {
9505d3c6deda0452c22ab2ed47bca74b98d87a17Tom Gundersen assert(m->windows[m->by_fd[fd_index].windows].by_fd_prev == (unsigned) -1);
09bee74d7a5f266b175baa19892fa84a9da51d7fTom Gundersen m->windows[m->by_fd[fd_index].windows].by_fd_prev = w;
9505d3c6deda0452c22ab2ed47bca74b98d87a17Tom Gundersenstatic void mmap_cache_fd_remove(MMapCache *m, unsigned fd_index, unsigned w) {
3ac8e5433f20bfb5e12b918252643106a2de52afTom Gundersen assert(v->by_fd_next == (unsigned) -1 || m->windows[v->by_fd_next].fd == v->fd);
9505d3c6deda0452c22ab2ed47bca74b98d87a17Tom Gundersen assert(v->by_fd_prev == (unsigned) -1 || m->windows[v->by_fd_prev].fd == v->fd);
9505d3c6deda0452c22ab2ed47bca74b98d87a17Tom Gundersen assert(m->windows[v->by_fd_prev].by_fd_next == w);
9505d3c6deda0452c22ab2ed47bca74b98d87a17Tom Gundersen m->windows[v->by_fd_prev].by_fd_next = v->by_fd_next;
9505d3c6deda0452c22ab2ed47bca74b98d87a17Tom Gundersen assert(m->windows[v->by_fd_next].by_fd_prev == w);
9505d3c6deda0452c22ab2ed47bca74b98d87a17Tom Gundersen m->windows[v->by_fd_next].by_fd_prev = v->by_fd_prev;
9505d3c6deda0452c22ab2ed47bca74b98d87a17Tom Gundersenstatic void mmap_cache_context_unset(MMapCache *m, unsigned c) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersenstatic void mmap_cache_context_set(MMapCache *m, unsigned c, unsigned w) {
f579559b3a14c1f1ef96c372e7626c4733e6ef7dTom Gundersen if (m->by_context[c] == w)
assert(m);
if (m->windows) {
for (w = 0; w < m->n_windows; w++)
mmap_cache_window_unmap(m, w);
free(m);
MMapCache *m;
return NULL;
if (!m->windows) {
mmap_cache_free(m);
return NULL;
if (!m->by_context) {
mmap_cache_free(m);
return NULL;
if (!m->by_fd) {
mmap_cache_free(m);
return NULL;
assert(m);
m->n_ref++;
assert(m);
mmap_cache_free(m);
m->n_ref--;
return NULL;
Window *v;
unsigned fd_index;
assert(m);
assert(w);
*w = m->n_windows ++;
return -E2BIG;
*w = m->lru_first;
v = m->windows + *w;
mmap_cache_window_unmap(m, *w);
if (v->fd >= 0) {
mmap_cache_window_remove_lru(m, *w);
assert(m);
w = m->lru_first;
Window *v;
v = m->windows + w;
if (v->ptr) {
mmap_cache_window_unmap(m, w);
w = v->lru_next;
static int mmap_cache_put(
MMapCache *m,
int fd,
unsigned fd_index,
int prot,
unsigned context,
void **ret) {
Window *v;
assert(m);
woffset = 0;
if (d != MAP_FAILED)
return -errno;
r = mmap_cache_make_room(m);
return -ENOMEM;
r = mmap_cache_allocate_window(m, &w);
v = m->windows + w;
v->ptr = d;
v->n_ref = 0;
mmap_cache_window_add_lru(m, w);
FileDescriptor *j;
assert(m);
for (r = 0; r < m->n_fds; r++)
FileDescriptor *j;
assert(m);
return -E2BIG;
static bool mmap_cache_test_window(
MMapCache *m,
Window *v;
assert(m);
v = m->windows + w;
static int mmap_cache_current(
MMapCache *m,
int fd,
unsigned context,
void **ret) {
Window *v;
assert(m);
v = m->windows + w;
static int mmap_cache_find(
MMapCache *m,
int fd,
unsigned fd_index,
unsigned context,
void **ret) {
assert(m);
v = m->windows + w;
w = v->by_fd_next;
int mmap_cache_get(
MMapCache *m,
int fd,
int prot,
unsigned context,
void **ret) {
unsigned fd_index;
assert(m);
unsigned fd_index, c, w;
assert(m);
for (c = 0; c < m->contexts_max; c++) {
w = m->by_context[c];
mmap_cache_context_unset(m, c);
Window *v;
v = m->windows + w;
mmap_cache_window_unmap(m, w);
memmove(m->by_fd + fd_index, m->by_fd + fd_index + 1, (m->n_fds - (fd_index + 1)) * sizeof(FileDescriptor));
m->n_fds --;
unsigned fd_index, c, w;
assert(m);
for (c = 0; c < m->contexts_max; c++) {
w = m->by_context[c];
mmap_cache_context_unset(m, c);
Window *v;
v = m->windows + w;
mmap_cache_window_unmap(m, w);
w = v->by_fd_next;