Return the private parameters of a created task

Hello,

so we use FreeRTOS with an self-written C+±abstraction layer.
Today I made some thoughts about a Watchdog-handling. Since the abstraction is mainly based on a single-responsibility about all OS-entities for every OS-using entity, we won’t pass any handles of mutexes, eventgroups, tasks and so on to other tasks. our components are decoupled via own-written communication interfaces and mechanisms. Tasks shall not do any unneccessary extra-handling, which can differ from task to task but should in general behave unified to prevent any confusion for the developer.

So to get this work, every C+±Object-Task has it’s own run-loop, which is called by a static defined C+±member-function of a task class, this is passed as a private parameter when the task get’s created, looking like this:

xTaskCreate(run, name, static_cast<uint16_t>(stackSize_), reinterpret_cast<void*>(owner), prio, &handle_);

So the owner is the c+±object. this works fine, later one, like this:

    static void run(void* taskHandle)
    {
        reinterpret_cast<Task*>(taskHandle)->runTask();
    }

So if a task now calls a mutex, which is also abstracted, everything will work because of FreeRTOS knowing which task is currently active.

A Watchdog-implementation-design at our side would now be to back-point to the C+±Task-Object and set it “ASLEEP”, so a checking watchdog-task can tell what state the task is in.

I thought that I may use the function xTaskGetCurrentTaskHandle() and with the task-handle get the previous passed private parameter when creating the task, which is in fact the c+±Task-object.

But the private parameter is not part of the TCB in FreeRTOS, it is port-defined where the private parameter is passed, as I noticed.
We can also generate a map to map the freeRTOS task-handles to our handles but that seems a bit bloated and unneccessaray runtime-intensive since the handle is already directly known to the FreeRTOS-task at creation-time.

Is there a “general” way to receive back the private parameter without fiddling it out of the port-implementation?

Use case would simply be like that:
C++ Mutex-object:

    /**
     * @brief gets the mutex
     */
    void get()
    {
        // use like this:
        reinterpret_cast<Task*>(xTaskGetCurrentTaskHandle()->prvParam)->setState(ASLEEP);
        if (xSemaphoreTake(handle_, portMAX_DELAY) != pdTRUE)
        {
            // error happened
        }
    }

I hope you get the intention. With the current FreeRTOS-implementation there won’t seem to be an “easy” approach as I understand.

Or am I missing something?

regards
Felix

Can’t you just explicitly give a task object reference/pointer to the watchdog object on creation or via a setter or init member function ?

That would be done anyway, because the Watchdog needs to check the state of the task. There would be a small list with registered C+±Task-Objects (which themselves contain their own states). This list would then be checked in an interval and the watchdog will be kicked/cleared if everything is fine.
But the c+±task-object itself must be set to a state. this state can only be known, when - in this example - a mutex-call sets the state of the calling task. But to know the calling task I would need to pass it additionally via the get-function of the Mutex. But it is already known by FreeRTOS. For the user it would be an unneccessary action and additional code which is not really needed, since the information is already present. Or if the user itself does the setting manually, then some may just forget it. To not encapsulate this behaviour and instead make explicit calls is a bit error prone in our design.
The other option would be the mentioned map. But all the time checking the FreeRTOS-Task-handle with the C+±Task-Object or running through a list with the FreeRTOS-Task-handles and a mapped state is unneccessary time consumption and extra code. Simplest would be to just call a function via the pointer.

Or did I get your assumption wrong?

Ok - it surely depends on your overall design which way suits best.
Using prvParam is also a good approach given you always follow your rule that it really is the this pointer of Task objects. But that can be ensured by your C++ wrapper.

It sounds like your issue is some things just know the FreeRTOS handle, and you want to know your task wrapper object for that task.

IF that is the case, you could use the vTaskSetApplicationTaskTag and vTaskGetApplicationTaskTag to save and fetch that pointer. You will need a cast on both ends to the tag, since it uses a function pointer to store the value, but for most system, an object pointer can be cast to a function pointer and back successfully.

This means you will just get back a NULL pointer if you try to get the pointer for a system task that doesn’t have a wrapper.

this looks a bit hacky but taking a look into the task.c-implementation of this function it would probably do the job. I will give it a try.

Another option would be to assign one of the “Thread Local Pointer” to be the Wrapper object pointer.

The key is you need to use something in the TCB to point to your objects, or you need a dictionary of handles to objects and search.

So the tag worked fine.
Thank you!

Thank you for reporting back.