You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
4.0 KiB
C

#ifndef H_ktypes
#define H_ktypes
// define the nullpointer
#define NULL ((void*) 0)
// types with explicit bit-widths
typedef unsigned int uint32;
typedef unsigned long long uint64;
typedef unsigned char byte;
/*
* Error codes
*/
enum error_code {
ENOCODE = 1, // invalid syscall code
EINVAL = 2, // invalid argument value
ENOMEM = 3, // not enough memory
ENOBUFS = 4, // no space left in buffer
ESRCH = 5, // no such process
ETIMEOUT= 6 // timeout while waiting
};
/*
* Scheduling types
*/
enum process_status {
PROC_DEAD = 0,
PROC_RDY = 1,
PROC_WAIT_PROC = 2,
PROC_WAIT_SLEEP = 3,
};
// forward define structs for recursive references
struct process_control_block;
struct loaded_binary;
struct process_control_block {
int pid;
// state information
int pc;
int regs[31];
int exit_code;
// scheduling information
enum process_status status;
struct process_control_block* waiting_for_process;
unsigned long long int asleep_until;
// hierarchical information
struct loaded_binary* binary;
struct process_control_block* parent;
// memory management information
void* stack_top;
};
enum pcb_struct_registers {
REG_RA = 0,
REG_SP = 1,
REG_GP = 2,
REG_TP = 3,
REG_T0 = 4,
REG_T1 = 5,
REG_t2 = 6,
REG_FP = 7,
REG_S0 = 7,
REG_S1 = 8,
REG_A0 = 9,
REG_S2 = 17,
REG_T3 = 27
};
/* This struct holds information about binaries which are currently loaded into
* memory. Currently the kernel is not able to load binaries into memory, as
* no file system layer is implemented. When the memory image is built, the
* list of loaded binaries is populated aswell.
*/
typedef struct loaded_binary {
int binid;
int entrypoint;
void* bounds[2];
} loaded_binary;
/*
* Optionals
*
* in this kernel, an optional can hold a value or an error, but we can't use
* unions here because we need to be able to distinguish errors from results.
* this is a little space inefficient, but we'll have to deal with this, or else
* we get global errno variables.
*/
#define CreateOptionalOfType(type) \
typedef struct Optional ## type { \
enum error_code error; \
type value; \
} optional_ ## type
// has_value and has_error are not dependent on the value type
// therefore we can define them as macros
#define has_value(optional) (optional.error == 0)
#define has_error(optional) (!has_value(optional))
// define some type aliases that only contain ascii character
// they are used in the name of the struct optional_<name>
typedef void* voidptr;
typedef struct process_control_block* pcbptr;
// size_t is another standard type
typedef unsigned int size_t;
// create optionals for required types
CreateOptionalOfType(int);
CreateOptionalOfType(size_t);
CreateOptionalOfType(pcbptr);
CreateOptionalOfType(voidptr);
/*
* Stacks
*
* stacks allow pushing and popping elements off it.
*/
// we currently only need a voidptr stack, if we need more we can either move them to a separate file
// or just type cast the pointers afterwards
struct voidptr_stack {
void** data;
int pos;
int size;
};
inline void* voidptr_stack_pop(struct voidptr_stack* stack) __attribute__((always_inline));
inline int voidptr_stack_push(struct voidptr_stack* stack, void* ptr) __attribute__((always_inline));
inline void voidptr_stack_new(struct voidptr_stack* stack, void** data, int size) __attribute__((always_inline));
inline void* voidptr_stack_pop(struct voidptr_stack* stack)
{
if (stack->pos == -1)
return NULL;
return stack->data[stack->pos--];
}
inline int voidptr_stack_push(struct voidptr_stack* stack, void* ptr)
{
if (stack->pos + 1 > stack->size)
return 0;
stack->pos += 1;
stack->data[stack->pos] = ptr;
return 1;
}
inline void voidptr_stack_new(struct voidptr_stack* stack, void** data, int size)
{
stack->pos = -1;
stack->size = size;
stack->data = data;
}
#endif