Thread End

Hi Everybody! I’ve just read FreeRTOS documentation, and there is one thing that surprised me. Thread is implemented as infinite loop (this of course is not surprisnig :) ), but when parent thread want to finish it, it calls vTaskDelete(). After reading documentation I understand, that it immediately finishes loop execution (by removing thread from scheduler), and idle thread will free memory allocated while thread creation. But some memory leaks will occur if thread dinamicaly allocate memory. Shouldn’t be finishing thread done by singnalig thread to leave infinite loop, dealocate all resources and leave thread execution routine?

Thread End

This functionality is not easy to implement without increasing the complexity and code size of the kernel.  This is because the task could be in any state when it is deleted.  For example, if the task is blocked on a queue then when it unblocks it has to know was this because it timed out, because something arrived on the queue, or because it was deleted.  Checking for a delete signal every time the task executes generates a large overhead. There is however an easy to implement alternative.  Each task can have an AboutToDelete function  like a callback.  When the idle task deletes the task it first calls the AboutToDelete function for the task.  This would do nothing but free up any resources the task had dynamically allocated itself (resources allocated by the kernel are automatically de-allocated).  A pointer to such a function could be stored within the TCB. Regards.

Thread End

OK. But I think that nobody can say: ‘Let’s kill this thread now!’, because it may be just after activity A and after A it has to perform activity B (it doesn’t mean that it should be done in critical section). What if after A parent call vTaskDelete()? OK. You can register AboutToDelete callback, but You have to check at what stage thread has been interrupted. This exaple is quite simple, but it may be more complex in real system. I think the best sollution for finishing threads is signaling by parent-thread to child-thread to self-finish: static void threadFn(void *pParam) {    message msg;    while(1)    {         queueReceive(queue, &msg)         switch(msg){         case LEAVE_THREAD:              dealocate_memory;              free_resources;               return;          case PERFORM_ACTION_A_AND_B:               do_action_A();               do_action_B();               break;           default:                break;           }    } } void parentTaskFn(void *pParam) {    message msg;    thread hThread;    hThread = createThread(threadFn, …);    ….    ….    msg = LEAVE_THREAD;    queueSend(queue, msg);    waitThread(hThread);  //wait for thread termination    //when thread returns its routine it is removing from scheduler by kernel } Am I wrong? Regards.

Thread End

Unfortunately no tabulatros :(

Thread End

If your tasks can all take this form then this is fine.  It places a lot of limitations on the task implementation, there is not always a parent thread for example. In a small embedded system dynamic memory allocation is likely to be less of an issue than, for example, a task being deleted while it has a peripheral locked for access.  The application design must of coarse take into account any actions necessary.

Thread End

Is more like Windoze style thread than RTOS task.

Thread End

>>Is more like Windoze style thread than RTOS task Do You think about WinAPI TerminateThread()? Do not ever use it to terminate thread if You want your application to run for a long time :) !!! It breaks thread at the current point of execution and removes it from scheduler freeing thread stack. It’s lieke vTaskDelete in FreeRTOS. Richard: of course. You have right if You are talking about small complexity systems. In most cases in embeded systems there are not thread termination at all! >>there is not always a parent thread for example – NO! There is always parent thread :) It may be Root thread (main function is called from its context). Someone creates thread of course – so it is parent. Of course thread can be signaled to terminate by different thread than parent. If your design is very complex you will be not able to control all of resources disposing or memory freeing if You will manage it from different contexts. I think the best sollution is to free resource by this one who allocated it. Of course this scheme of thread termination will work, but i think it is very unsafe (more unsafe if system is more complex). >>If your tasks can all take this form then this is fine Which another form could them take? Of course there may be not massage queue and signaling to terminate could look like this: static volatiole boolean bTerminate = false; static void threadFn(void *pParam) { while(1) { if(bTerminate == true) break; do_action_A(); do_action_B(); } } } May I have a question? What kind of embeded systems are You designing? PS. My name is Kamil -> I think i should register soon to be visible at forum not as Nobody :)

Thread End

> >>Is more like Windoze style thread than RTOS task > > Do You think about WinAPI TerminateThread()? > Do not ever use it to terminate thread if You want your application to run for > a long time :) !!! It breaks thread at the current point of execution and removes > it from scheduler freeing thread stack. It’s lieke vTaskDelete in FreeRTOS. > Sorry cant comment on WinAPI  as its out of my realm. > Richard: of course. You have right if You are talking about small complexity > systems. In most cases in embeded systems there are not thread termination at > all! > >>there is not always a parent thread for example – NO! There is always parent > thread :) It may be Root thread (main function is called from its context). Ok, a question of semantics I suppose. There are of coarse occasions when one task may create another.  There are also those tasks that are created before the kernel has started.  These are effectively started from main()  and once the kernel has started the context of main() effectively does not exist.  It never runs again unless the vPortEndScheduler() is called.  I have only vPortEndScheduler() for the ports that run over DOS, because in other cases there is nothing to return to. > Someone creates thread of course – so it is parent. > Of course thread can be signaled to terminate by different thread than parent. There is no super process running in the middle of the kernel that has knowledge of all the message queues.  It is up to the application design to say which tasks have knowledge of which threads  and how to talk to which threads.  There is no automatic way of communicating with a thread unless the threads generates a queue/semaphore/ and gives the rest of the system knowledge of it. > > >>If your tasks can all take this form then this is fine > Which another form could them take? A task may never block (like the idle task) but just run continuously in the background. A task may block on a semaphore.  A task may block on a queue.  A task may run periodically (very common). Most of these forms of execution do not require a central messaging system.  Of coarse you could create a queue which is checked for signals without blocking every iteration  but this will take up a lot of resources and severely limit the amount of tasks that can be created (remember the FreeRTOS is running on 8bit systems with as little as 1.5KBytes of RAM). > Of course there may be not massage queue and signaling to terminate could look > like this: > > static volatiole boolean bTerminate = false; > static void threadFn(void *pParam) > { > while(1) > { > if(bTerminate == true) > break; > do_action_A(); > do_action_B(); > } > } > } > > May I have a question? Of coarse :-) > What kind of embeded systems are You designing? How long have you got?  Industrial automation, consumer electronics, motor control, hobby projects, automotive, .  a  rather general answer I know. > > PS. My name is Kamil -> I think i should register soon to be visible at forum > not as Nobody :) > Thanks for your interesting comments. Best regards.

Thread End

OK! But I think that my approach gives better control over what is going on in our system. Code is more compact and therfore more portable to other systems. (Some parts of code may be used in other systems, employing other OSs) And this is my second question: What will happen if I finish thread by exiting its routine? (under FreeRTOS of course) Would it be hard to implement to finish thread as I described in my 2nd post? (After quick review of source code I think it wouldn’t be very hard). Kamil

Thread End

O! And one another question. A lot of RTOS implements both ways of thread termination. One – soft – which I proposed to normal thread termination, and another one – hard – like implemented in FreeRTOS(it is sometimes called "thread kill" and can be used to kill threads that don’t answer). Maybe it will be good to implement it in FreeRTOS?

Thread End

> What will happen if I finish thread by exiting its routine? (under FreeRTOS > of course) Would it be hard to implement to finish thread as I described in > my 2nd post? If the thread leaves it’s routine a return from subroutine instruction will be called.  Where this jumps to depends on how the initial task stack was created (when the task was created in the port.c file). If this is required functionality then I would suggest an approach such as: void vATask( void * pvParameters ) {     for(;;)     {         // perform operation here.         if( WhatToDie() )         {             break;         }     }     // delete any resources we have used here.     // Left the normal operation – make sure     // we leave the kernel in a clean state.     vTaskDelete( NULL );     // Will never get here! }

Thread End

> O! And one another question. A lot of RTOS implements both ways of thread > termination. One – soft – which I proposed to normal thread termination, and > another one – hard – like implemented in FreeRTOS(it is sometimes called "thread > kill" and can be used to kill threads that don’t answer). > Maybe it will be good to implement it in FreeRTOS? It is the stated goal of FreeRTOS to be a minimal implementation – which is (hopefully) easy to understand and therefore extend to fit your requirements. There are a lot of features that could be added, but would only be suitable for a small proportion of applications.  The functionality will grow over time, but this comes at the cost of complexity.  To keep the code size down it will also require greater use of conditional compilation which I have always tried to keep to a minimum to ease code readability.  Linux and eCOS provide open source alternatives if your application requires a more heavy weight OS.

Thread End

:) Let’s consider: portSHORT sTaskCreate( pdTASK_CODE pvTaskCode, const signed portCHAR * const pcName, unsigned portSHORT usStackDepth, void *pvParameters, unsigned portCHAR ucPriority, xTaskHandle *pxCreatedTask ) function Enter condition: usCurrentNumberOfTasks > 1 cSchedulerRunning == TRUE pxCreatedTask == NULL pxCurrentTCB->ucPriority < ucPriority So preemption (taskYIELD() ) is not performed. WHY? It all depends of argument passed pxCreatedTask but if it is NULL it means that I don’t need just created thread handle but if its priority is higher than actual there should be context switching performed. Kamil

Thread End

Not sure about that one…I will have to look back through the older versions to see if it is always thus.  Maybe the YIELD choice should be outside the if().

Thread End

I have changed this for V2.5.5.