HelenOS sources
This source file includes following definitions.
- region_instance
- region_create
- region_destroy
- get_regions
- pio_trace_log
- pio_trace_enable
- pio_trace_disable
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <adt/list.h>
#include <fibril_synch.h>
#include <ddi.h>
#include <str.h>
typedef struct {
link_t link;
volatile void *base;
size_t size;
void *data;
trace_fnc log;
} region_t;
static inline region_t *region_instance(link_t *l)
{
return list_get_instance(l, region_t, link);
}
static inline region_t *region_create(volatile void *base, size_t size,
trace_fnc log, void *data)
{
region_t *new_reg = malloc(sizeof(region_t));
if (new_reg) {
link_initialize(&new_reg->link);
new_reg->base = base;
new_reg->data = data;
new_reg->size = size;
new_reg->log = log;
}
return new_reg;
}
static inline void region_destroy(region_t *r)
{
free(r);
}
typedef struct {
list_t list;
fibril_rwlock_t guard;
} pio_regions_t;
static pio_regions_t *get_regions(void)
{
static pio_regions_t regions = {
.list = LIST_INITIALIZER(regions.list),
.guard = FIBRIL_RWLOCK_INITIALIZER(regions.guard),
};
return ®ions;
}
void pio_trace_log(const volatile void *r, uint64_t val, bool write)
{
pio_regions_t *regions = get_regions();
fibril_rwlock_read_lock(®ions->guard);
list_foreach(regions->list, link, region_t, reg) {
if ((r >= reg->base) && (r < reg->base + reg->size)) {
if (reg->log)
reg->log(r, val, reg->base,
reg->size, reg->data, write);
break;
}
}
fibril_rwlock_read_unlock(®ions->guard);
}
errno_t pio_trace_enable(void *base, size_t size, trace_fnc log, void *data)
{
pio_regions_t *regions = get_regions();
assert(regions);
region_t *region = region_create(base, size, log, data);
if (!region)
return ENOMEM;
fibril_rwlock_write_lock(®ions->guard);
list_append(®ion->link, ®ions->list);
fibril_rwlock_write_unlock(®ions->guard);
return EOK;
}
void pio_trace_disable(void *r)
{
pio_regions_t *regions = get_regions();
assert(regions);
fibril_rwlock_write_lock(®ions->guard);
list_foreach_safe(regions->list, it, next) {
region_t *reg = region_instance(it);
if (r >= reg->base && (r < reg->base + reg->size)) {
list_remove(®->link);
region_destroy(reg);
}
}
fibril_rwlock_write_unlock(®ions->guard);
}
HelenOS homepage, sources at GitHub