Thread data

Has the notion of thread data been discussed in this forum? Just a void * in the TCB with set/get functions would do it. Richard, any chance of you including this in tasks.c?

Thread data

Hi Glen, This would be simple enough to add.  What would you foresee it being used for (thinking about mutual exclusion issues in particular if for talking between threads)?  There is already the void* parameter passed into each task. Regards.

Thread data

Generally, this would allow threads to have thread specific data that is accessible from service functions that are called from multiple threads. One use would be to make the task pvParameters usable by functions called by the task. When a task starts up, it it could set that pvParameters as it’s task data pointer. In fact, that might be an interesting ‘default’ value for the task data pointer rather than NULL. In my specific case, I have an C++ object oriented layer above FreeRTOS. There is an object for each thread/task. I would set the task data pointer to locate the object. That way, member functions of the ‘thread object’ could be called from service functions that otherwise would have no way to find the thread object from the task handle. Originally I maintained a lookup table that associated task handles with thread objects. A bit complex and costly to access the object. Later I bacame braver and modified the context save/restore routines to push/pop the thread object pointer from/to a global variable. I pass the thread object pointer in to the task as pvParameters, and initialize the global variable with it. Then, from within service functions I get at the thread object via the global. This works well, but I think it is a bit heavy to burden each context switch with this cost when most ‘runs of a thread’ (context switch in to context switch out) will not even use the global. In fact, timewise it may be more costly than the table lookup! Hence my request. This is not an original idea. It is a feature of other RTOS’s I have seen, although I couldn’t name one off the top of my head. I don’t think there is a mutex problem because only the thread itself will access the pointer and its referenced data structure. In fact, I would ask that this restriction be enforced (i.e., the accessor functions not take a task handle parameter). However, I was concerned about things like this and that is why I raised the issue in the forum rather than just do it myself. I thought your (and others) experience might save me from myself. So I think it is trivial, but I am not sure… add (but using the Hungarian naming convention):    void * taskData; to the TCB with accessor functions void setTaskData(void * ptr) {    ‘set tcb to locate the current TCB’    tcb->taskData = ptr; } void * getTaskData(void) {    ‘set tcb to locate the current TCB’    return tcb->taskData; }

Thread data

An interesting idea.  I’m not there would be enough call for the feature to include it in the standard TCB structure.  There is actually a member of the TCB that is not used directly by the scheduler already – the uxTCBNumber member.  This is only used to hold a number to facilitate debugging when printing out the task states.  A bit ugly perhaps, but maybe this could have a dual purpose? Regards.

Thread data

Yes, I had noticed uxTCBNumber and thought of using it when I was considering just implementing it myself. But really, I don’t think 4 bytes per TCB is all that much. Do you see this as safe enough go ahead and do? Maybe I should just write the accessor functions and try it out, using uxTCBNumber. I could let you know how it works out, and if OK you could decide whether or not you want to include it. I assume that after you set uxTCBNumber you never change it. Correct?

Thread data

I cannot see any (obvious) problem.  uxTCBNumber never gets changed. Regards.

Thread data

Here are the thread data accessor functions I added to tasks.c. Seems to work fine. This requires that ‘unsigned portBASE_TYPE’ be safely convertible back and forth to ‘void *’ in the particular FreeRTOS port you are using. It is probably safer to at a new ‘void *’ field to the TCB structure. void SetTaskData(void * ptr) {     tskTCB *    tcb = xTaskGetCurrentTaskHandle();     tcb->uxTCBNumber = (unsigned portBASE_TYPE)ptr; } void * GetTaskData(void) {     tskTCB *    tcb = xTaskGetCurrentTaskHandle();     return (void *)(tcb->uxTCBNumber); } I have previously done something else in tasks.c that maybe I could get some feedback on. I’ll put it into a new thread.

Thread data

I agree that there’s no reason to change anything in FreeRTOS, and I would not like to increase overhead for the feature. There are many possibilities already. I don’t think ‘unsigned portBASE_TYPE’ would easily cast to pointer in many small systems. I guess it could be a global array of pointers, using this value to index to this task. Better Idea: The pvParameters could pass an environment allocated for a particular task if it needs to already exist. Of course that is not saved in the TCB, so I could save the pointer at ‘*pxStack’ because that would not be written until the stack is full (if portSTACK_GROWTH < 0). Now thinking more, I wouldn’t need point to it. I’d just have the data space be the region unused by stack. Increasing ‘usStackDepth’ gives me more space for the task data block. I think this would allow for any target to work, especially if Richard will write something into the docs to guarantee what we can expect in a portable way.