Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Allow calling user provided hooks in system daemon #734

Draft
wants to merge 1 commit into
base: develop-pros-4
Choose a base branch
from
Draft
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
3 changes: 3 additions & 0 deletions include/pros/apix.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ extern "C" {

typedef void* queue_t;
typedef void* sem_t;
typedef void (*generic_fn_t)(void);

void add_daemon_hook(generic_fn_t hook);
Comment on lines +55 to +57
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doxygen, obviously.

Also, I'm unsold on the names of both generic_fn_t and add_daemon_hook.

Copy link
Contributor

@djava djava Dec 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably data_collection_hook_fn_t and add_data_processing_hook()?


/**
* Unblocks a task in the Blocked state (e.g. waiting for a delay, on a
Expand Down
18 changes: 18 additions & 0 deletions src/system/system_daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

#include "kapi.h"
#include "common/linkedlist.h"
#include "system/optimizers.h"
#include "system/user_functions.h"
#include "v5_api.h"
Expand All @@ -37,6 +38,9 @@ static void _competition_initialize_task(void* ign);
static void _initialize_task(void* ign);
static void _system_daemon_task(void* ign);

static linked_list_s_t* hook_list = NULL;
static mutex_t mut = 0;

enum state_task { E_OPCONTROL_TASK = 0, E_AUTON_TASK, E_DISABLED_TASK, E_COMP_INIT_TASK };

char task_names[4][32] = {"User Operator Control (PROS)", "User Autonomous (PROS)", "User Disabled (PROS)",
Expand All @@ -45,13 +49,27 @@ task_fn_t task_fns[4] = {_opcontrol_task, _autonomous_task, _disabled_task, _com

extern void ser_output_flush(void);

void add_daemon_hook(generic_fn_t hook) {
// TODO: make thread safe
if (unlikely(hook_list == NULL)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that it matters because this whole function is like, the coldest of paths, but is this even unlikely? It happens at least once per program that uses this function, and it seems at least semi-likely that most programs that use this would only have one.

Not that it matters, but you did add the unlikely so it seems worth questioning.

hook_list = linked_list_init();
}
linked_list_append_func(hook_list, hook);
}

static void call_hook(ll_node_s_t* node, void* data) {
(void) data;
node->payload.func();
}

// does the basic background operations that need to occur every 2ms
static inline void do_background_operations() {
port_mutex_take_all();
ser_output_flush();
rtos_suspend_all();
vexBackgroundProcessing();
rtos_resume_all();
linked_list_foreach(hook_list, &call_hook, NULL);
vdml_background_processing();
port_mutex_give_all();
}
Comment on lines 66 to 75
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sold on this order - I frankly don't know what vdml_background_processing is, but it sounds like something that should happen first.

Also, any user code should definitely not be called while all port mutexes are locked, because thats obviously going to deadlock, as every device API function requires locking a port mutex.

I think the linked_list_foreach should be at the end, after port_mutex_give_all().

Expand Down