#include <mach/mach_types.h>
#include <mach/host_info.h>
#include <kern/locks.h>
#include <kern/ecc.h>
#include <kern/spl.h>
#include <pexpert/pexpert.h>
#include <libkern/OSAtomic.h>
#define ECC_EVENT_BUFFER_COUNT 5
struct ecc_event ecc_data[ECC_EVENT_BUFFER_COUNT];
static uint32_t ecc_data_next_read;
static uint32_t ecc_data_next_write;
static boolean_t ecc_data_empty = TRUE; static LCK_GRP_DECLARE(ecc_data_lock_group, "ecc-data");
static LCK_SPIN_DECLARE(ecc_data_lock, &ecc_data_lock_group);
static uint32_t ecc_correction_count;
uint32_t
ecc_log_get_correction_count()
{
return ecc_correction_count;
}
kern_return_t
ecc_log_record_event(const struct ecc_event *ev)
{
spl_t x;
if (ev->count > ECC_EVENT_INFO_DATA_ENTRIES) {
panic("Count of %u on ecc event is too large.", (unsigned)ev->count);
}
x = splhigh();
lck_spin_lock(&ecc_data_lock);
ecc_correction_count++;
if (ecc_data_next_read == ecc_data_next_write && !ecc_data_empty) {
lck_spin_unlock(&ecc_data_lock);
splx(x);
return KERN_FAILURE;
}
bcopy(ev, &ecc_data[ecc_data_next_write], sizeof(*ev));
ecc_data_next_write++;
ecc_data_next_write %= ECC_EVENT_BUFFER_COUNT;
ecc_data_empty = FALSE;
lck_spin_unlock(&ecc_data_lock);
splx(x);
return KERN_SUCCESS;
}
kern_return_t
ecc_log_get_next_event(struct ecc_event *ev)
{
spl_t x;
x = splhigh();
lck_spin_lock(&ecc_data_lock);
if (ecc_data_empty) {
assert(ecc_data_next_write == ecc_data_next_read);
lck_spin_unlock(&ecc_data_lock);
splx(x);
return KERN_FAILURE;
}
bcopy(&ecc_data[ecc_data_next_read], ev, sizeof(*ev));
ecc_data_next_read++;
ecc_data_next_read %= ECC_EVENT_BUFFER_COUNT;
if (ecc_data_next_read == ecc_data_next_write) {
ecc_data_empty = TRUE;
}
lck_spin_unlock(&ecc_data_lock);
splx(x);
return KERN_SUCCESS;
}