Add cmake option to enable/disable cache and alloc tracing.

This commit is contained in:
Enrico Fraccaroli (Galfurian)
2022-07-08 14:36:01 -04:00
parent 4e07800428
commit cef88432a1
5 changed files with 139 additions and 115 deletions
+17
View File
@@ -17,6 +17,11 @@ set(BUDDY_SYSTEM_FILE ${PROJECT_SOURCE_DIR}/src/mem/libbuddysystem.a)
# Add the memory option.
option(USE_BUDDY_SYSTEM "Build using the buddysystem written by the user." OFF)
# Enables cache tracing.
option(ENABLE_CACHE_TRACE "Enables cache tracing." OFF)
# Enables memory allocation tracing.
option(ENABLE_ALLOC_TRACE "Enables memory allocation tracing." OFF)
# =============================================================================
# ASSEMBLY
@@ -197,6 +202,18 @@ target_compile_definitions(
__KERNEL__
)
# =============================================================================
# Enables cache tracing.
if(ENABLE_CACHE_TRACE)
target_compile_definitions(${KERNEL_NAME} PUBLIC ENABLE_CACHE_TRACE)
endif(ENABLE_CACHE_TRACE)
# =============================================================================
# Enables memory allocation tracing.
if(ENABLE_ALLOC_TRACE)
target_compile_definitions(${KERNEL_NAME} PUBLIC ENABLE_ALLOC_TRACE)
endif(ENABLE_ALLOC_TRACE)
# =============================================================================
# Set the list of valid scheduling options.
set(SCHEDULER_TYPES SCHEDULER_RR SCHEDULER_PRIORITY SCHEDULER_CFS SCHEDULER_EDF SCHEDULER_RM)
+4 -15
View File
@@ -9,9 +9,6 @@
#include "stddef.h"
#include "mem/gfp.h"
//#define ENABLE_CACHE_TRACE
//#define ENABLE_ALLOC_TRACE
/// @brief Type for slab flags.
typedef unsigned int slab_flags_t;
@@ -88,10 +85,6 @@ void kmem_cache_destroy(kmem_cache_t *cachep);
#ifdef ENABLE_CACHE_TRACE
#ifndef __FILENAME__
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
#endif
/// @brief Allocs a new object using the provided cache.
/// @param file File where the object is allocated.
/// @param fun Function where the object is allocated.
@@ -109,10 +102,10 @@ void *pr_kmem_cache_alloc(const char *file, const char *fun, int line, kmem_cach
void pr_kmem_cache_free(const char *file, const char *fun, int line, void *addr);
/// Wrapper that provides the filename, the function and line where the alloc is happening.
#define kmem_cache_alloc(...) pr_kmem_cache_alloc(__FILENAME__, __func__, __LINE__, __VA_ARGS__)
#define kmem_cache_alloc(...) pr_kmem_cache_alloc(__FILE__, __func__, __LINE__, __VA_ARGS__)
/// Wrapper that provides the filename, the function and line where the free is happening.
#define kmem_cache_free(...) pr_kmem_cache_free(__FILENAME__, __func__, __LINE__, __VA_ARGS__)
#define kmem_cache_free(...) pr_kmem_cache_free(__FILE__, __func__, __LINE__, __VA_ARGS__)
#else
/// @brief Allocs a new object using the provided cache.
@@ -129,10 +122,6 @@ void kmem_cache_free(void *addr);
#ifdef ENABLE_ALLOC_TRACE
#ifndef __FILENAME__
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
#endif
/// @brief Provides dynamically allocated memory in kernel space.
/// @param file File where the object is allocated.
/// @param fun Function where the object is allocated.
@@ -149,10 +138,10 @@ void *pr_kmalloc(const char *file, const char *fun, int line, unsigned int size)
void pr_kfree(const char *file, const char *fun, int line, void *addr);
/// Wrapper that provides the filename, the function and line where the alloc is happening.
#define kmalloc(...) pr_kmalloc(__FILENAME__, __func__, __LINE__, __VA_ARGS__)
#define kmalloc(...) pr_kmalloc(__FILE__, __func__, __LINE__, __VA_ARGS__)
/// Wrapper that provides the filename, the function and line where the free is happening.
#define kfree(...) pr_kfree(__FILENAME__, __func__, __LINE__, __VA_ARGS__)
#define kfree(...) pr_kfree(__FILE__, __func__, __LINE__, __VA_ARGS__)
#else
+106 -88
View File
@@ -158,11 +158,10 @@ void dynamic_timers_install()
tvec_base_t *base = &cpu_base;
base->timer_ticks = 0;
for(int i = 0; i < TVR_SIZE; ++i)
for (int i = 0; i < TVR_SIZE; ++i)
list_head_init(base->tv1.vec + i);
for(int i = 0; i < TVN_SIZE; ++i) {
for (int i = 0; i < TVN_SIZE; ++i) {
list_head_init(base->tv2.vec + i);
list_head_init(base->tv3.vec + i);
list_head_init(base->tv4.vec + i);
@@ -175,8 +174,8 @@ void dynamic_timers_install()
}
/// Prints used slots of timer vector
static void __print_tvec_slots(tvec_base_t *base, int tv_index) {
static void __print_tvec_slots(tvec_base_t *base, int tv_index)
{
if (tv_index < 0 || tv_index > 5)
return;
@@ -184,51 +183,57 @@ static void __print_tvec_slots(tvec_base_t *base, int tv_index) {
char result[TVN_SIZE + 1];
result[TVN_SIZE] = '\0';
struct timer_vec* tv = NULL;
switch(tv_index) {
// Root
case 1: {
pr_debug("base->tv1.vec:");
for(int i = 0; i < TVR_SIZE; ++i) {
struct timer_vec *tv = NULL;
switch (tv_index) {
// Root
case 1: {
pr_debug("base->tv1.vec:");
for (int i = 0; i < TVR_SIZE; ++i) {
// New line in order to not clutter the screen
int index = i % TVN_SIZE;
if (i != 0 && index == 0)
pr_debug("\n\t%s", result);
// New line in order to not clutter the screen
int index = i % TVN_SIZE;
if (i != 0 && index == 0)
pr_debug("\n\t%s", result);
if (!list_head_empty(base->tv1.vec + i))
result[index] = '1';
else
result[index] = '0';
}
if (!list_head_empty(base->tv1.vec + i))
result[index] = '1';
else
result[index] = '0';
}
// The last line
pr_debug("\n\t%s\n", result);
return;
// The last line
pr_debug("\n\t%s\n", result);
return;
} break;
} break;
// Normal
case 2: tv = &base->tv2; break;
case 3: tv = &base->tv3; break;
case 4: tv = &base->tv4; break;
case 5: tv = &base->tv5; break;
// Normal
case 2:
tv = &base->tv2;
break;
case 3:
tv = &base->tv3;
break;
case 4:
tv = &base->tv4;
break;
case 5:
tv = &base->tv5;
break;
}
for(int i = 0; i < TVN_SIZE; ++i) {
for (int i = 0; i < TVN_SIZE; ++i) {
if (list_head_empty(tv->vec + i))
result[i] = '0';
else
result[i] = '1';
}
pr_debug("base->tv%d.vec:\n\t%s\n", tv_index, result);
}
/// Dump all timer vector in base
static inline void __dump_all_tvec_slots(tvec_base_t *base) {
static inline void __dump_all_tvec_slots(tvec_base_t *base)
{
__print_tvec_slots(base, 1);
__print_tvec_slots(base, 2);
__print_tvec_slots(base, 3);
@@ -238,13 +243,13 @@ static inline void __dump_all_tvec_slots(tvec_base_t *base) {
/// Select correct timer vector and position inside of it for the input timer
/// index contains the position inside of the tv_index timer vector
static void __find_tvec(tvec_base_t *base, struct timer_list *timer, int* index, int* tv_index)
static void __find_tvec(tvec_base_t *base, struct timer_list *timer, int *index, int *tv_index)
{
assert(index && "index is NULL");
assert(tv_index && "tv_index is NULL");
unsigned long expires = timer->expires;
unsigned long ticks = expires - base->timer_ticks;
unsigned long ticks = expires - base->timer_ticks;
unsigned long tv1_ticks = TIMER_TICKS(0);
unsigned long tv2_ticks = TIMER_TICKS(1);
@@ -253,49 +258,59 @@ static void __find_tvec(tvec_base_t *base, struct timer_list *timer, int* index,
// Can happen if you add a timer with expires == ticks, or in the past
if ((signed long)ticks < 0) {
*index = base->timer_ticks & TVR_MASK;
*index = base->timer_ticks & TVR_MASK;
*tv_index = 1;
}
// tv1
else if (ticks < tv1_ticks) {
*index = expires & TVR_MASK;
*index = expires & TVR_MASK;
*tv_index = 1;
}
// tv2
else if (ticks < tv2_ticks) {
*index = (expires >> TIMER_TICKS_BITS(0)) & TVN_MASK;
*index = (expires >> TIMER_TICKS_BITS(0)) & TVN_MASK;
*tv_index = 2;
}
// tv3
else if (ticks < tv3_ticks) {
*index = (expires >> TIMER_TICKS_BITS(1)) & TVN_MASK;
*index = (expires >> TIMER_TICKS_BITS(1)) & TVN_MASK;
*tv_index = 3;
}
// tv4
else if (ticks < tv4_ticks) {
*index = (expires >> TIMER_TICKS_BITS(2)) & TVN_MASK;
*index = (expires >> TIMER_TICKS_BITS(2)) & TVN_MASK;
*tv_index = 4;
}
// tv5
else {
*index = (expires >> TIMER_TICKS_BITS(3)) & TVN_MASK;
*index = (expires >> TIMER_TICKS_BITS(3)) & TVN_MASK;
*tv_index = 5;
}
}
/// Add timers into different lists based on their expire time
static void __add_timer_tvec_base(tvec_base_t *base, struct timer_list *timer) {
static void __add_timer_tvec_base(tvec_base_t *base, struct timer_list *timer)
{
int index = 0, tv_index = 0;
__find_tvec(base, timer, &index, &tv_index);
struct list_head* vec;
switch(tv_index) {
case 1: vec = base->tv1.vec + index; break;
case 2: vec = base->tv2.vec + index; break;
case 3: vec = base->tv3.vec + index; break;
case 4: vec = base->tv4.vec + index; break;
case 5: vec = base->tv5.vec + index; break;
struct list_head *vec;
switch (tv_index) {
case 1:
vec = base->tv1.vec + index;
break;
case 2:
vec = base->tv2.vec + index;
break;
case 3:
vec = base->tv3.vec + index;
break;
case 4:
vec = base->tv4.vec + index;
break;
case 5:
vec = base->tv5.vec + index;
break;
}
pr_debug("Adding timer at time_index: %d in tv%d\n", index, tv_index);
@@ -304,22 +319,31 @@ static void __add_timer_tvec_base(tvec_base_t *base, struct timer_list *timer) {
#ifdef ENABLE_REAL_TIMER_SYSTEM_DUMP
__dump_all_tvec_slots(base);
#endif
}
/// Remove timer from tvec_base
static void __rem_timer_tvec_base(tvec_base_t *base, struct timer_list *timer) {
static void __rem_timer_tvec_base(tvec_base_t *base, struct timer_list *timer)
{
int index = 0, tv_index = 0;
__find_tvec(base, timer, &index, &tv_index);
struct list_head* vec;
switch(tv_index) {
case 1: vec = base->tv1.vec + index; break;
case 2: vec = base->tv2.vec + index; break;
case 3: vec = base->tv3.vec + index; break;
case 4: vec = base->tv4.vec + index; break;
case 5: vec = base->tv5.vec + index; break;
struct list_head *vec;
switch (tv_index) {
case 1:
vec = base->tv1.vec + index;
break;
case 2:
vec = base->tv2.vec + index;
break;
case 3:
vec = base->tv3.vec + index;
break;
case 4:
vec = base->tv4.vec + index;
break;
case 5:
vec = base->tv5.vec + index;
break;
}
pr_debug("Removing timer at time_index: %d in tv%d\n", index, tv_index);
@@ -327,13 +351,12 @@ static void __rem_timer_tvec_base(tvec_base_t *base, struct timer_list *timer) {
#ifdef ENABLE_REAL_TIMER_SYSTEM_DUMP
__dump_all_tvec_slots(base);
#endif
#endif
}
/// Move all timers from tv up one level
static int cascate(tvec_base_t* base, timer_vec* tv, int time_index, int tv_index) {
static int cascate(tvec_base_t *base, timer_vec *tv, int time_index, int tv_index)
{
if (!list_head_empty(tv->vec + time_index)) {
pr_debug("Relocating timers in tv%d.vec[%d]\n", tv_index, time_index);
@@ -345,7 +368,6 @@ static int cascate(tvec_base_t* base, timer_vec* tv, int time_index, int tv_inde
__add_timer_tvec_base(base, timer);
}
}
return time_index;
}
@@ -360,17 +382,15 @@ void run_timer_softirq()
// While we are not up to date with current ticks
unsigned long current_ticks = timer_get_ticks();
while (base->timer_ticks <= current_ticks) {
// Index of the current timer to execute
int current_time_index = base->timer_ticks & TVR_MASK;
// If the index is zero then all lists in base->tv1 have been checked, so they are empty
if (!current_time_index) {
// Consider the first invocation of the cascade() function: it receives as arguments
// Consider the first invocation of the cascade() function: it receives as arguments
// the address in base, the address of base->tv2, and the index of the list
// in base->tv2 including the timers that will decay in the next 256 ticks. This
// index is determined by looking at the proper bits of the base->timer_ticks value.
// index is determined by looking at the proper bits of the base->timer_ticks value.
// cascade() moves all dynamic timers in the base->tv2 list into the
// proper lists of base->tv1; then, it returns a positive value, unless all base->tv2
// lists are now empty. If so, cascade() is invoked once more to replenish
@@ -381,16 +401,17 @@ void run_timer_softirq()
int tv4_index = (base->timer_ticks >> TIMER_TICKS_BITS(2)) & TVN_MASK;
int tv5_index = (base->timer_ticks >> TIMER_TICKS_BITS(3)) & TVN_MASK;
if (!cascate(base, &base->tv2, tv2_index, 2) &&
!cascate(base, &base->tv3, tv3_index, 3) &&
!cascate(base, &base->tv4, tv4_index, 4) &&
!cascate(base, &base->tv5, tv5_index, 5));
if (!cascate(base, &base->tv2, tv2_index, 2) &&
!cascate(base, &base->tv3, tv3_index, 3) &&
!cascate(base, &base->tv4, tv4_index, 4) &&
!cascate(base, &base->tv5, tv5_index, 5))
;
}
// If there are timers to execute in this instant
if (!list_head_empty(&base->tv1.vec[current_time_index])) {
pr_notice("Executing dynamic timers at %d ticks from start inside of tv1.vec[%d]\n",
base->timer_ticks, current_time_index);
pr_debug("Executing dynamic timers at %d ticks from start inside of tv1.vec[%d]\n",
base->timer_ticks, current_time_index);
// Trigger all timers
struct list_head *it, *tmp;
@@ -399,7 +420,7 @@ void run_timer_softirq()
// Executes timer function
spinlock_unlock(&base->lock);
pr_notice("Executing dynamic timer function...\n");
pr_debug("Executing dynamic timer function...\n");
timer->function(timer->data);
spinlock_lock(&base->lock);
@@ -426,12 +447,12 @@ void run_timer_softirq()
// Executes timer function
spinlock_unlock(&base->lock);
pr_notice("Executing dynamic timer function...\n");
pr_debug("Executing dynamic timer function...\n");
timer->function(timer->data);
spinlock_lock(&base->lock);
// Removes timer from list
pr_notice("Removing dynamic timer...\n");
pr_debug("Removing dynamic timer...\n");
list_head_del(it);
kfree(timer);
}
@@ -453,27 +474,25 @@ void init_timer(struct timer_list *timer)
void add_timer(struct timer_list *timer)
{
tvec_base_t *base = &cpu_base;
timer->base = base;
timer->base = base;
#ifdef ENABLE_REAL_TIMER_SYSTEM
__add_timer_tvec_base(base, timer);
#else
list_head_add_tail(&timer->entry, &base->list);
#endif
}
void del_timer(struct timer_list *timer)
{
tvec_base_t *base = &cpu_base;
timer->base = NULL;
timer->base = NULL;
#ifdef ENABLE_REAL_TIMER_SYSTEM
__rem_timer_tvec_base(base, timer);
#else
list_head_del(&timer->entry);
#endif
}
//======================================================================================
@@ -483,8 +502,7 @@ void del_timer(struct timer_list *timer)
/// @param data The data.
static inline void debug_timeout(unsigned long data)
{
pr_notice("Il timer è stato attivato con successo: %d, ticks: %d, seconds: %d\n",
data, timer_ticks, timer_get_seconds());
pr_debug("The timer has been successfully deactivated: %d, ticks: %d, seconds: %d\n", data, timer_ticks, timer_get_seconds());
}
/// @brief Contains the entry of a wait queue and timespec which keeps trakc of
@@ -497,7 +515,7 @@ typedef struct sleep_data_t {
} sleep_data_t;
/// @brief Callback for when a sleep timer expires
/// @param data Custom data stored in the timer
/// @param data Custom data stored in the timer
void sleep_timeout(unsigned long data)
{
// NOTE: We could modify the sleep_on and make it return the wait_queue_entry_t
@@ -550,7 +568,7 @@ int sys_nanosleep(const timespec *req, timespec *rem)
}
/// @brief Function executed when the real_timer of a process expires, sends SIGALRM to process.
/// @param pid PID of the process whos associated timer has expired
/// @param pid PID of the process whos associated timer has expired
void alarm_timeout(unsigned long pid)
{
sys_kill(pid, SIGALRM);
+4 -4
View File
@@ -263,7 +263,7 @@ void *kmem_cache_alloc(kmem_cache_t *cachep, gfp_t flags)
list_head_add(slab_full_elem, &cachep->slabs_full);
}
#ifdef ENABLE_CACHE_TRACE
pr_notice("kmem_cache_alloc : (%-16s:%3d)[%-16s] : 0x%p\n", file, line, cachep->name, ptr);
pr_notice("CHACE-ALLOC 0x%p in %-20s at %s:%d\n", ptr, cachep->name, file, line);
#endif
return ptr;
}
@@ -284,7 +284,7 @@ void kmem_cache_free(void *ptr)
kmem_cache_t *cachep = slab_page->container.slab_cache;
#ifdef ENABLE_CACHE_TRACE
pr_notice("kmem_cache_free : (%-16s:%3d)[%-16s] : 0x%p\n", file, line, cachep->name, ptr);
pr_notice("CHACE-FREE 0x%p in %-20s at %s:%d\n", ptr, cachep->name, file, line);
#endif
if (cachep->dtor)
cachep->dtor(ptr);
@@ -332,7 +332,7 @@ void *kmalloc(unsigned int size)
ptr = kmem_cache_alloc(malloc_blocks[order], GFP_KERNEL);
}
#ifdef ENABLE_ALLOC_TRACE
pr_notice("kmalloc : (%-16s:%3d) : 0x%p\n", file, line, ptr);
pr_notice("KMALLOC 0x%p at %s:%d\n", ptr, file, line);
#endif
return ptr;
}
@@ -344,7 +344,7 @@ void kfree(void *ptr)
#endif
{
#ifdef ENABLE_ALLOC_TRACE
pr_notice("kfree : (%-16s:%3d) : 0x%p\n", file, line, ptr);
pr_notice("KFREE 0x%p at %s:%d\n", ptr, file, line);
#endif
page_t *page = get_lowmem_page_from_address((uint32_t)ptr);
+8 -8
View File
@@ -360,7 +360,7 @@ static void __do_signal_stop(struct task_struct *current, struct pt_regs *f, int
// the SA_NOCLDSTOP flag of SIGCHLD.
if (!(SA_NOCLDSTOP & current->parent->sighand.action[SIGCHLD - 1].sa_flags))
if (__notify_parent(current, SIGCHLD) != 0)
pr_debug("Failed to notify parent with signal: %d", signr);
pr_warning("Failed to notify parent with signal: %d", signr);
// The state is now TASK_UNINTERRUPTABLE
sleep_on(&stopped_queue);
@@ -410,7 +410,7 @@ int do_signal(struct pt_regs *f)
// If its value is 0, it means that all pending signals have been
// handled and do_signal( ) can finish.
if (signr == 0) {
pr_notice("There are no more signals to handle.\n");
pr_debug("There are no more signals to handle.\n");
__unlock_task_sighand(current);
return 0;
}
@@ -633,7 +633,7 @@ int sys_kill(pid_t pid, int sig)
sighandler_t sys_signal(int signum, sighandler_t handler)
{
pr_notice("sys_signal(%d, %p)\n", signum, handler);
pr_debug("sys_signal(%d, %p)\n", signum, handler);
// Check the signal that we want to send.
if ((signum < 0) || (signum >= NSIG)) {
pr_err("sys_signal(%d, %p): Wrong signal number!\n", signum, handler);
@@ -645,7 +645,7 @@ sighandler_t sys_signal(int signum, sighandler_t handler)
assert(current && "There is no running process.");
// Skip the `init` process, always.
if (current->pid == 1) {
pr_err("sys_signal(%d, %p): Cannot signal number!\n", signum, handler);
pr_err("sys_signal(%d, %p): Cannot signal init!\n", signum, handler);
return SIG_ERR;
}
// Create a new signal action.
@@ -677,7 +677,7 @@ int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
pr_debug("sys_sigaction(%d, %p, %p)\n", signum, act, oldact);
// Check the signal that we want to send.
if ((signum < 0) || (signum >= NSIG)) {
pr_debug("sys_sigaction(%d, %p, %p): Wrong signal number!\n", signum, act, oldact);
pr_err("sys_sigaction(%d, %p, %p): Wrong signal number!\n", signum, act, oldact);
return -EINVAL;
}
// The do_signal() function is usually only invoked when the CPU is going
@@ -686,7 +686,7 @@ int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
assert(current && "There is no running process.");
// Skip the `init` process, always.
if (current->pid == 1) {
pr_debug("sys_sigaction(%d, %p, %p): Cannot set signal for init!\n", signum, act, oldact);
pr_err("sys_sigaction(%d, %p, %p): Cannot set signal for init!\n", signum, act, oldact);
return -EINVAL;
}
// Lock the signal handling for the given task.
@@ -708,7 +708,7 @@ int sys_sigaction(int signum, const sigaction_t *act, sigaction_t *oldact)
int sys_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
{
pr_notice("sys_sigprocmask(%d, %p, %p)\n", how, set, oldset);
pr_debug("sys_sigprocmask(%d, %p, %p)\n", how, set, oldset);
if (!set && !oldset) {
return -EFAULT;
}
@@ -721,7 +721,7 @@ int sys_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
assert(current && "There is no running process.");
// Skip the `init` process, always.
if (current->pid == 1) {
pr_notice("sys_sigprocmask(%d, %p, %p): Cannot set signal for init!\n", how, set, oldset);
pr_warning("sys_sigprocmask(%d, %p, %p): Cannot set signal for init!\n", how, set, oldset);
return -EINVAL;
}
// If `oldset` is not, return the old set.