Commit 40077300 authored by Charlie Jacobsen's avatar Charlie Jacobsen

Updates cptr cache defs and build so that cspace config can truly vary.

Before, I just had some CPP checks that would stop the build
if the cspace depth wasn't 4, etc. So it required some manual
changes. Now it should be fully automated.

There are three awk scripts that generate some C code / do some
calculations, and the results are plugged into some headers (that
are now templates and generated by configure). I did it this way
because the CPP doesn't seem powerful enough to generate variable
length definitions like this (without some serious CPP hacking).
Easier to use awk and then AC_SUBST the results in.

If we want to make the code even faster, we could precompute some
other stuff like this as well.

I tested the user build, and ran multi_thrd_cap with a cspace
depth of 8, and cnode table size of 8. Looked ok.
parent 8e2fb16b
Pipeline #411 passed with stage
......@@ -248,8 +248,8 @@ AC_CHECK_SIZEOF([unsigned long])
# Sanity check cspace depth and cnode table size, now that we
# have the size of an unsigned long.
AC_MSG_CHECKING([that cspace config is sane])
cptr_size=`$AWK "BEGIN { print (2 ** $CAP_CSPACE_DEPTH_BITS) * ($CAP_CSPACE_CNODE_TABLE_BITS - 1) + $CAP_CSPACE_DEPTH_BITS }"`
long_size=`$AWK "BEGIN { print $ac_cv_sizeof_unsigned_long * 8 }"`
cptr_size=`$AWK -v cap_cspace_depth_bits=$CAP_CSPACE_DEPTH_BITS -v cap_cspace_cnode_table_bits=$CAP_CSPACE_CNODE_TABLE_BITS -f $srcdir/scripts/cptr_size.awk`
long_size=`$AWK -v bytes_in_an_unsigned_long=$ac_cv_sizeof_unsigned_long -f $srcdir/scripts/ulong_size.awk`
AS_IF([test "$cptr_size" -gt "$long_size"],
[
AC_MSG_RESULT([no])
......@@ -282,6 +282,33 @@ AC_C_INLINE
AC_FUNC_MALLOC
AC_CHECK_FUNCS([memset strdup])
# --------------------------------------------------
# Set up cptr cache definitions and accessors
# --------------------------------------------------
# These are computed with awk scripts instead of the CPP
# since the CPP is limited with respect to loops/recursion,
# exponentiation, and so on. Awk seems like it will be available on most build
# systems (no? including Windows? I'm guessing yes if they have
# support to do autoconf crap, installed gnu autotools or something).
CAP_CPTR_CACHE_BMAP_DEFS=`$AWK -v cap_cspace_depth_bits=$CAP_CSPACE_DEPTH_BITS -v cap_cspace_cnode_table_bits=$CAP_CSPACE_CNODE_TABLE_BITS -f $srcdir/scripts/cptr_cache_bmap_defs.awk`
CAP_CPTR_CACHE_BMAP_FOR_LEVEL=`$AWK -v cap_cspace_depth_bits=$CAP_CSPACE_DEPTH_BITS -f $srcdir/scripts/cptr_cache_bmap_for_level.awk`
AC_SUBST(CAP_CPTR_CACHE_BMAP_DEFS)
AC_SUBST(CAP_CPTR_CACHE_BMAP_FOR_LEVEL)
# Don't subst these in makefile's, or else the makefiles will break
AM_SUBST_NOTMAKE(CAP_CPTR_CACHE_BMAP_DEFS)
AM_SUBST_NOTMAKE(CAP_CPTR_CACHE_BMAP_FOR_LEVEL)
# --------------------------------------------------
# Misc
# --------------------------------------------------
# I can't remember if there is a standard way to do this
CAP_AUTOCONF_NOTICE="This file was autogenerated by configure."
AC_SUBST(CAP_AUTOCONF_NOTICE)
# --------------------------------------------------
# Config files
# --------------------------------------------------
......@@ -294,6 +321,8 @@ AC_CONFIG_FILES(
src/include/Makefile
src/include/libcap_config.h
src/include/libcap_types.h
src/include/libcap.h
src/platform/Makefile
src/platform/kernel/Makefile
......
#
# Generate the bitmap defs for the cptr_cache type.
#
# Invocation example:
#
# awk -v cap_cspace_depth_bits=2 -v cap_cspace_cnode_table_bits=6 \
# -f cptr_cache_bmap_defs.awk
#
BEGIN {
out = "";
depth = 2 ** cap_cspace_depth_bits;
slots_per_table = 2 ** cap_cspace_cnode_table_bits;
for (i = 0; i < depth; i++) {
# Only half of the slots store capabilities in a cnode table. The
# other half store pointers to nodes further down in the radix
# tree.
slots_in_lvl = (slots_per_table / 2) ** (i + 1);
out = out "\tunsigned long bmap" i "[CAP_BITS_TO_LONGS(" \
slots_in_lvl ")];\n";
}
print out;
}
#
# Generate the switch statement in the body of
# cap_cptr_cache_bmap_for_level.
#
# Invocation example:
#
# awk -v cap_cspace_depth_bits=2 -f cptr_cache_bmap_for_level.awk
#
BEGIN {
out = "\tswitch (lvl) {\n";
for (i = 0; i < (2 ** cap_cspace_depth_bits); i++) {
out = out "\t\tcase " i ":\n";
out = out "\t\t\treturn c->bmap" i ";\n";
}
out = out "\t\tdefault:\n";
out = out "\t\t\tCAP_BUG();\n";
out = out "\t}";
print out;
}
#
# Calculates total number of slots in a cspace, given the depth and
# cnode table size.
#
# Invocation example:
#
# awk -v cap_cspace_depth_bits=2 -v cap_cspace_cnode_table_bits=6 \
# -f cptr_cache_bmap_size.awk
#
BEGIN {
depth = 2 ** cap_cspace_depth_bits;
tsize = 2 ** cap_cspace_cnode_table_bits;
total = ( (tsize/2) - ((tsize/2)**(depth + 1)) ) / ( 1 - (tsize/2) );
print total;
}
#
# Calculates number of bits needed to store a cptr. Awk is used because
# the CPP cannot do exponentiation, and many systems have awk (no?).
# Moreover, the shell's arithmetic ops (at least non-bash) are limited.
#
# Invocation example:
#
# awk -v cap_cspace_depth_bits=2 -v cap_cspace_cnode_table_bits=6 \
# -f cptr_size.awk
#
BEGIN {
print ((2 ** cap_cspace_depth_bits) * \
(cap_cspace_cnode_table_bits - 1) + cap_cspace_depth_bits)
}
#
# Calculates size in bits of an unsigned long. This is pretty trivial
# and could probably be inlined in configure.ac, but for clarity I
# moved it out here.
#
# Invocation example:
#
# awk -v bytes_in_an_unsigned_long=8 -f ulong_size.awk
#
BEGIN {
print bytes_in_an_unsigned_long * 8
}
......@@ -9,28 +9,6 @@
#include <libcap.h>
#include <libcap_internal.h>
#if (CAP_CSPACE_DEPTH == 4)
static inline unsigned long*
cap_cptr_cache_bmap_for_level(struct cptr_cache *c, int lvl)
{
switch (lvl) {
case 0:
return c->bmap0;
case 1:
return c->bmap1;
case 2:
return c->bmap2;
case 3:
return c->bmap3;
default:
CAP_BUG();
}
}
#else
#error "You need to adjust this function def."
#endif
int cptr_cache_alloc(struct cptr_cache **out)
{
struct cptr_cache *cache;
......
/*
* @CAP_AUTOCONF_NOTICE@
*
* libcap.h
*
* Main include for libcap library. This is the only file
......@@ -194,7 +196,21 @@ int cptr_alloc(struct cptr_cache *cptr_cache, cptr_t *free_cptr);
* Fails silently if the cptr is free already.
*/
void cptr_free(struct cptr_cache *cptr_cache, cptr_t c);
/**
* cap_cptr_cache_bmap_for_level -- Return pointer to the bitmap for lvl
* @c: the cptr cache
* @lvl: zero-indexed lvl value
*
* The body of this function is generated via an awk script (the CPP
* is too limited). Note that lvl may be a compile-time constant, but
* the CPP doesn't know that (so we can't use easy macro tricks, that I'm
* aware of).
*/
static inline unsigned long*
cap_cptr_cache_bmap_for_level(struct cptr_cache *c, int lvl)
{
@CAP_CPTR_CACHE_BMAP_FOR_LEVEL@
}
/* CSPACES -------------------------------------------------- */
......@@ -217,6 +233,10 @@ void cap_fini(void);
*
* Returns the total number of *capability* slots in all of the
* cnode tables at a given @lvl of the cspace radix tree.
*
* TODO: If we want to make things faster, we could replace the body
* of this with a switch statement and compute the values at compile time
* with some awk/autoconf magic.
*/
static inline int cap_cspace_slots_in_level(int lvl)
{
......
/*
* @CAP_AUTOCONF_NOTICE@
*
* libcap_config.h
*
* Copyright: University of Utah
......
/*
* types.h
* @CAP_AUTOCONF_NOTICE@
*
* Author: Charles Jacobsen <charlesj@cs.utah.edu>
* Copyright: University of Utah
* libcap_types.h
*
* Copyright: University of Utah
*/
#ifndef __LIBCAP_TYPES_H__
#define __LIBCAP_TYPES_H__
......@@ -17,28 +17,6 @@
#define CAP_DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define CAP_BITS_TO_LONGS(nr) CAP_DIV_ROUND_UP(nr, 8 * sizeof(long))
/* CONVENIENCE CALCULATIONS ---------------------------------------- */
/*
* To avoid serious CPP hacking, this is hard-coded for cspace depths. This
* is still pretty fugly anyway.
*
* lvl must be a compile-time constant.
*
* IMPORTANT: lvl should be zero-indexed (the first level is lvl = 0, ...).
* If you use a bad value, the error may not show up till link time.
*/
#if (CAP_CSPACE_DEPTH == 4)
#define CAP_EXP_0(a) (a)
#define CAP_EXP_1(a) ((a) * CAP_EXP_0(a))
#define CAP_EXP_2(a) ((a) * CAP_EXP_1(a))
#define CAP_EXP_3(a) ((a) * CAP_EXP_2(a))
#define CAP_CSPACE_SLOTS_IN_LEVEL(lvl) \
CAP_EXP_ ## lvl(CAP_CSPACE_CNODE_TABLE_SIZE/2)
#else
#error "cspace depth not 4, you need to update this"
#endif
/* CPTRs -------------------------------------------------- */
/**
......@@ -67,26 +45,20 @@ typedef struct {
* LCDs because the cptr cache needs to be available before the
* memory allocators are up and running.
*/
#if (CAP_CSPACE_DEPTH == 4)
struct cptr_cache {
/* lock */
/*
* lock
*/
cap_mutex_t lock;
/* level 0 bitmap */
unsigned long bmap0[CAP_BITS_TO_LONGS(CAP_CSPACE_SLOTS_IN_LEVEL(0))];
/* level 1 bitmap */
unsigned long bmap1[CAP_BITS_TO_LONGS(CAP_CSPACE_SLOTS_IN_LEVEL(1))];
/* level 2 bitmap */
unsigned long bmap2[CAP_BITS_TO_LONGS(CAP_CSPACE_SLOTS_IN_LEVEL(2))];
/* level 3 bitmap */
unsigned long bmap3[CAP_BITS_TO_LONGS(CAP_CSPACE_SLOTS_IN_LEVEL(3))];
/*
* bmaps
*
* (This part of the def is computed via an awk script; the
* CPP is limited and this would require serious CPP hacking to do.)
*/
@CAP_CPTR_CACHE_BMAP_DEFS@
};
#else
#error "You need to adjust the cptr cache def."
#endif
/* CSPACES -------------------------------------------------- */
/* For now, this def is not public, and hopefully never will be. */
......
# @CAP_AUTOCONF_NOTICE@
# Build libcap as static library. Unfortunately, the name of the
# library is hard-coded in the kernel build system to be lib.a. (We
# have an extra build step that cp's lib.a -> libcap.a.)
......
# @CAP_AUTOCONF_NOTICE@
# Build kernel module that includes libcap.a.
# Note: Kernel expects the files to be relative paths (it always prepends
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment