Commit 8c39cffc authored by Charlie Jacobsen's avatar Charlie Jacobsen

static-cptr-cache: Adds lock to cptr cache, fixes race conditions in tests.

All looks OK now.

Few other misc things:

   - config.h header goes with install
   - Some debug code in cap.c.
   - Wasn't handling return value of make cnode table in cap.c.

For now, until we (possibly) move stuff around, I'm including the
internal header in the public header so that I have access to
the cap mutex type. I'm considering re-working things so that this
won't be necessary in the future. Temporary hack for now.
parent fc4c8ed8
Pipeline #392 failed with stage
......@@ -5,7 +5,7 @@ AC_PREREQ([2.69])
AC_INIT([libcap], [0.1])
AC_CONFIG_SRCDIR([src/common/cptr_cache.c])
AC_CONFIG_AUX_DIR(autoconf)
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_HEADERS([include/config.h])
LT_INIT
AC_CONFIG_MACRO_DIR([m4])
......
......@@ -2,4 +2,4 @@ noinst_HEADERS = \
libcap_internal.h libcap_internal_kernel.h libcap_internal_user.h list.h
include_HEADERS = \
libcap.h libcap_kernel.h libcap_types.h libcap_user.h
libcap.h libcap_kernel.h libcap_types.h libcap_user.h config.h
......@@ -79,6 +79,9 @@ extern int cap_debug_level;
/* CPTRs -------------------------------------------------- */
#include "libcap_internal.h" /* temporary hack */
/**
* __cptr -- Construct a cptr from an unsigned long
* @cptr: the unsigned long to use
......@@ -186,6 +189,25 @@ static inline int cptr_is_null(cptr_t c)
/* CPTR CACHEs -------------------------------------------------- */
#if (CAP_CSPACE_DEPTH == 4)
struct cptr_cache {
/* 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))];
};
#else
#error "You need to adjust the cptr cache def."
#endif
/**
* cptr_init -- Initalize the cptr cache subsystem
*/
......
......@@ -104,24 +104,5 @@ typedef struct {
#define CAP_CPTR_NULL ((cptr_t){0})
/* CPTR CACHE -------------------------------------------------- */
#if (CAP_CSPACE_DEPTH == 4)
struct cptr_cache {
/* 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))];
};
#else
#error "You need to adjust the cptr cache def."
#endif
#endif /* __LIBCAP_TYPES_H__ */
......@@ -257,6 +257,7 @@ static int update_cnode_table(struct cspace *cspace,
bool alloc, struct cnode_table **new)
{
unsigned long index;
int ret;
/*
* The first half of the slots contain caps, the second half table
* pointers. Skip over cap slots by adding half the number of slots
......@@ -278,7 +279,11 @@ static int update_cnode_table(struct cspace *cspace,
*
* Allocate and init a new cnode table
*/
make_empty_cnode_table(cspace, old->table_level + 1, new);
ret = make_empty_cnode_table(cspace, old->table_level + 1, new);
if (ret) {
CAP_ERR("Error making empty cnode table\n");
return ret;
}
/*
* Set up cnode that points to it
*/
......@@ -290,6 +295,11 @@ static int update_cnode_table(struct cspace *cspace,
/*
* cnode free, invalid, etc.
*/
CAP_DEBUG(CAP_DEBUG_ERR,
"Error in cspace traversal: cnode contains%s, and we are%s trying to alloc\n",
old->cnode[level_id].type == CAP_TYPE_CNODE ?
" a pointer to the next level" : " has unexpected type (not a pointer to a cnode in the next level)",
alloc ? "" : " not");
return -EINVAL; /* signal error in look up */
}
}
......@@ -324,7 +334,7 @@ static int find_cnode(struct cspace *cspace, struct cnode_table *old,
/*
* invalid indexing, etc.
*/
CAP_DEBUG(1,
CAP_DEBUG(CAP_DEBUG_ERR,
"Error in lookup: cnode is %s, and we are%s trying to alloc\n",
old->cnode[level_id].type == CAP_TYPE_FREE ?
"free" : "occupied",
......@@ -386,8 +396,10 @@ static int __cap_cnode_lookup(struct cspace *cspace, cptr_t c, bool alloc,
/*
* If cptr is null, fail
*/
if (cptr_is_null(c))
if (cptr_is_null(c)) {
CAP_DEBUG(CAP_DEBUG_MSG, "cptr is null, lookup aborted\n");
return -EINVAL;
}
/*
* Initialize to root cnode table
......@@ -434,7 +446,8 @@ static int __cap_cnode_get(struct cspace *cspace, cptr_t c,
}
ret = __cap_cnode_lookup(cspace, c, alloc, cnode);
if (ret) {
ret = -ENOMEM;
CAP_DEBUG(CAP_DEBUG_MSG,
"cnode lookup failed with ret = %d\n", ret)
goto fail2;
}
......
......@@ -67,6 +67,10 @@ int cptr_cache_init(struct cptr_cache *cache)
{
int i;
unsigned long *bmap;
/*
* Init lock
*/
cap_mutex_init(&cache->lock);
/*
* Zero out the bitmaps. (The caller may not have
* necessarily used zalloc.)
......@@ -119,7 +123,13 @@ int cptr_alloc(struct cptr_cache *cptr_cache, cptr_t *free_cptr)
unsigned long idx;
int size;
cptr_t result;
/*
* Lock cache ********************
*/
cap_mutex_lock(&cptr_cache->lock);
/*
* Search
*/
depth = 0;
do {
bmap = cap_cptr_cache_bmap_for_level(cptr_cache, depth);
......@@ -134,7 +144,7 @@ int cptr_alloc(struct cptr_cache *cptr_cache, cptr_t *free_cptr)
*/
CAP_ERR("out of cptrs");
ret = -ENOMEM;
goto fail1;
goto unlock;
}
/*
* Found one; dec depth back to what it was, and encode
......@@ -145,9 +155,14 @@ int cptr_alloc(struct cptr_cache *cptr_cache, cptr_t *free_cptr)
cap_cptr_set_level(&result, depth);
*free_cptr = result;
return 0;
ret = 0;
goto unlock;
fail1:
unlock:
/*
* Unlock cache ********************
*/
cap_mutex_unlock(&cptr_cache->lock);
return ret;
}
......@@ -157,6 +172,10 @@ void cptr_free(struct cptr_cache *cptr_cache, cptr_t c)
unsigned long bmap_idx;
unsigned long level;
unsigned long mask;
/*
* Lock cache ********************
*/
cap_mutex_lock(&cptr_cache->lock);
/*
* Get the correct level bitmap
*/
......@@ -175,6 +194,10 @@ void cptr_free(struct cptr_cache *cptr_cache, cptr_t c)
* Clear the bit in the bitmap
*/
cap_clear_bit(bmap_idx, bmap);
/*
* Unlock cache ********************
*/
cap_mutex_unlock(&cptr_cache->lock);
return;
}
#include "libcap.h"
int cap_debug_level = 1;
int cap_debug_level = 5;
......@@ -64,6 +64,7 @@ static struct cptr_cache *scache;
static struct cptr_cache *dcache;
static cptr_t sslot_arr[SLOTS];
static cptr_t dslot_arr[SLOTS];
static int revoke_signal[SLOTS];
static int track = 0;
static pthread_t threads[THREAD_COUNT];
static cap_mutex_t global_user_lock;
......@@ -84,7 +85,8 @@ int insert(struct cspace *csp, cptr_t slot)
perror("malloc\n");
return 1;
}
snprintf(p, 32, "stringobj%d", global_stringobj_counter);
/* using global could lead to race */
snprintf(p, 32, "stringobj%d", next);
ret = cap_insert(csp, slot, p, stringobj_type);
if (ret < 0) {
......@@ -151,12 +153,10 @@ void *thread_revoke(void* arg)
printf("Thread Revoke : slot %d 0x%lx\n",
i, cptr_val(sslot_arr[i]));
/* Wait for both insert and grant before revoke */
if (cptr_is_null(sslot_arr[i])
|| cptr_is_null(dslot_arr[i])) {
printf("Thread Revoke : null cptr slot %i (0x%lx,0x%lx), stalling...\n",
i,cptr_val(sslot_arr[i]),cptr_val(dslot_arr[i]));
while (cptr_is_null(sslot_arr[i])
|| cptr_is_null(dslot_arr[i])) {
if (!revoke_signal[i]) {
printf("Thread Revoke : get on %i not done yet, stalling...\n",
i);
while (!revoke_signal[i]) {
STALL();
}
printf("Thread Revoke : unstalled cptr slot %i (0x%lx,0x%lx)\n",
......@@ -234,6 +234,7 @@ void *thread_get(void * arg) {
CAP_ERR("Destination CSPACE Lookup failed\n");
else
printf("Lookup PASS\n");
revoke_signal[i] = 1;
i++;
}
}
......
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