Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ OBJS = \
$K/kalloc.o \
$K/spinlock.o \
$K/string.o \
$K/elog.o \
$K/alert.o \
$K/main.o \
$K/vm.o \
$K/proc.o \
Expand Down Expand Up @@ -142,6 +144,8 @@ UPROGS=\
$U/_grind\
$U/_wc\
$U/_zombie\
$U/_sustainlog\
$U/_alertsys\
$U/_logstress\
$U/_forphan\
$U/_dorphan\
Expand Down
125 changes: 125 additions & 0 deletions kernel/alert.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// kernel/alert.c
#include "types.h"
#include "riscv.h"
#include "spinlock.h"
#include "defs.h"
#include "alert.h"
#include "elog.h"

extern uint ticks;
extern struct spinlock tickslock;

struct {
struct spinlock lock;
struct alert_threshold thresholds[MAX_SENSORS];
struct alert_entry buf[ALERT_BUF_SIZE];
int next_index;
int count;
} alertsys;

static int
getticksafe(void)
{
int t;
acquire(&tickslock);
t = ticks;
release(&tickslock);
return t;
}

void
alertinit(void)
{
initlock(&alertsys.lock, "alert");
alertsys.next_index = 0;
alertsys.count = 0;
for(int i = 0; i < MAX_SENSORS; i++){
alertsys.thresholds[i].active = 0;
}
}

int
alertsetthreshold(int sensor_id, int min_val, int max_val)
{
if(sensor_id < 1 || sensor_id > MAX_SENSORS)
return -1;
if(min_val > max_val)
return -1;

acquire(&alertsys.lock);

struct alert_threshold *t = &alertsys.thresholds[sensor_id - 1];
t->sensor_id = sensor_id;
t->min_val = min_val;
t->max_val = max_val;
t->active = 1;

release(&alertsys.lock);
return 0;
}

void
alertcheck(int sensor_id, int value)
{
int exceeded = 0;
int thresh_val = 0;

if(sensor_id < 1 || sensor_id > MAX_SENSORS)
return;

acquire(&alertsys.lock);

struct alert_threshold *t = &alertsys.thresholds[sensor_id - 1];
if(t->active){
if(value > t->max_val){
exceeded = 1;
thresh_val = t->max_val;
} else if(value < t->min_val){
exceeded = 1;
thresh_val = t->min_val;
}

if(exceeded){
struct alert_entry *e = &alertsys.buf[alertsys.next_index];
e->timestamp = getticksafe();
e->sensor_id = sensor_id;
e->value = value;
e->threshold = thresh_val;
e->alert_type = ALERT_WARNING;

alertsys.next_index = (alertsys.next_index + 1) % ALERT_BUF_SIZE;
if(alertsys.count < ALERT_BUF_SIZE)
alertsys.count++;
}
}

release(&alertsys.lock);

// Log threshold breach into elog system (after releasing alert lock)
if(exceeded)
elogadd(EVENT_THRESHOLD_EXCEEDED, sensor_id, value);
}

int
alertgetpending(struct alert_entry *dst, int max)
{
int i, n, start;

if(dst == 0 || max <= 0)
return 0;

acquire(&alertsys.lock);

n = alertsys.count;
if(max < n)
n = max;

start = (alertsys.next_index - alertsys.count + ALERT_BUF_SIZE) % ALERT_BUF_SIZE;

for(i = 0; i < n; i++){
dst[i] = alertsys.buf[(start + i) % ALERT_BUF_SIZE];
}

release(&alertsys.lock);
return n;
}
30 changes: 30 additions & 0 deletions kernel/alert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef _ALERT_H_
#define _ALERT_H_

#define MAX_SENSORS 5
#define ALERT_BUF_SIZE 32

#define ALERT_WARNING 1
#define ALERT_CRITICAL 2

struct alert_threshold {
int sensor_id;
int min_val;
int max_val;
int active;
};

struct alert_entry {
int timestamp;
int sensor_id;
int value;
int threshold;
int alert_type;
};

void alertinit(void);
void alertcheck(int sensor_id, int value);
int alertsetthreshold(int sensor_id, int min_val, int max_val);
int alertgetpending(struct alert_entry *dst, int max);

#endif
78 changes: 78 additions & 0 deletions kernel/elog.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// kernel/elog.c
#include "types.h"
#include "riscv.h"
#include "spinlock.h"
#include "defs.h"
#include "elog.h"

extern uint ticks;
extern struct spinlock tickslock;

struct {
struct spinlock lock;
struct elog_entry buf[ELOG_SIZE];
int next_index; // next position to write
int count; // number of valid entries
} elogsys;

static int
getticksafe(void)
{
int t;
acquire(&tickslock);
t = ticks;
release(&tickslock);
return t;
}

void
eloginit(void)
{
initlock(&elogsys.lock, "elog");
elogsys.next_index = 0;
elogsys.count = 0;
}

void
elogadd(int event_type, int sensor_id, int value)
{
acquire(&elogsys.lock);

struct elog_entry *e = &elogsys.buf[elogsys.next_index];
e->timestamp = getticksafe();
e->event_type = event_type;
e->sensor_id = sensor_id;
e->value = value;

elogsys.next_index = (elogsys.next_index + 1) % ELOG_SIZE;
if(elogsys.count < ELOG_SIZE)
elogsys.count++;

release(&elogsys.lock);
}

// Copies logs from oldest -> newest into dst.
// Returns number of entries copied.
int
elogread(struct elog_entry *dst, int max)
{
int i, n, start;

if(dst == 0 || max <= 0)
return 0;

acquire(&elogsys.lock);

n = elogsys.count;
if(max < n)
n = max;

start = (elogsys.next_index - elogsys.count + ELOG_SIZE) % ELOG_SIZE;

for(i = 0; i < n; i++){
dst[i] = elogsys.buf[(start + i) % ELOG_SIZE];
}

release(&elogsys.lock);
return n;
}
28 changes: 28 additions & 0 deletions kernel/elog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef _ELOG_H_
#define _ELOG_H_

#define ELOG_SIZE 64

#define SENSOR_TEMPERATURE 1
#define SENSOR_AIR_QUALITY 2
#define SENSOR_HUMIDITY 3
#define SENSOR_ENERGY_USAGE 4
#define SENSOR_WATER_USAGE 5

#define EVENT_SENSOR_UPDATE 1
#define EVENT_THRESHOLD_EXCEEDED 2
#define EVENT_BACK_TO_NORMAL 3
#define EVENT_INVALID_READING 4

struct elog_entry {
int timestamp;
int event_type;
int sensor_id;
int value;
};

void eloginit(void);
void elogadd(int event_type, int sensor_id, int value);
int elogread(struct elog_entry *dst, int max);

#endif
8 changes: 6 additions & 2 deletions kernel/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "memlayout.h"
#include "riscv.h"
#include "defs.h"
#include "elog.h"
#include "alert.h"

volatile static int started = 0;

Expand All @@ -28,6 +30,8 @@ main()
iinit(); // inode table
fileinit(); // file table
virtio_disk_init(); // emulated hard disk
eloginit(); // initialize logging system
alertinit(); // initialize alert system
userinit(); // first user process
__sync_synchronize();
started = 1;
Expand All @@ -41,5 +45,5 @@ main()
plicinithart(); // ask PLIC for device interrupts
}

scheduler();
}
scheduler();
}
8 changes: 8 additions & 0 deletions kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ extern uint64 sys_unlink(void);
extern uint64 sys_link(void);
extern uint64 sys_mkdir(void);
extern uint64 sys_close(void);
extern uint64 sys_logevent(void);
extern uint64 sys_getlogs(void);
extern uint64 sys_setalert(void);
extern uint64 sys_getalerts(void);

// An array mapping syscall numbers from syscall.h
// to the function that handles the system call.
Expand All @@ -126,6 +130,10 @@ static uint64 (*syscalls[])(void) = {
[SYS_link] sys_link,
[SYS_mkdir] sys_mkdir,
[SYS_close] sys_close,
[SYS_logevent] sys_logevent,
[SYS_getlogs] sys_getlogs,
[SYS_setalert] sys_setalert,
[SYS_getalerts] sys_getalerts,
};

void
Expand Down
8 changes: 6 additions & 2 deletions kernel/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,9 @@
#define SYS_mknod 17
#define SYS_unlink 18
#define SYS_link 19
#define SYS_mkdir 20
#define SYS_close 21
#define SYS_mkdir 20
#define SYS_close 21
#define SYS_logevent 22
#define SYS_getlogs 23
#define SYS_setalert 24
#define SYS_getalerts 25
Loading