FreeRTOS - creating a task in place of another task? - freertos

I am using heap_1 memory allocation. There is an initialization task Task_ini, from which 2 tasks Task_1 and Task_2 are launched. Then I delete Task_ini. At some point in time from Task_1 I need to create a new task Task_3. How can I create Task_3 in the FreeRTOS heap in place of Task_ini which has already been deleted by that time, knowing only its TaskHandle_t?
int main(void){
xTaskCreate(Task_ini, "Task_ini", configMINIMAL_STACK_SIZE, NULL, 1, &htask_ini);
vTaskStartScheduler();
for(;;);
}
void Task_ini(void *pParams){
xTaskCreate(Task_function, "Task_1", configMINIMAL_STACK_SIZE, &param1, 1, &htask1);
xTaskCreate(Task_function, "Task_2", configMINIMAL_STACK_SIZE, &param2, 1, &htask2);
vTaskDelete(NULL);
}
void Task_function(void *pParams){
for(;;){
//task code
//...
//end task code
if(create == true){
create = false;
//Here I need to create a task at the address where the "Task_ini" task was.
//My code creates a task in a new heap section, and if there is no space it will cause a memory allocation error.
xTaskCreate(Task_function, "Task_3", configMINIMAL_STACK_SIZE, &param3, 1, &htask3);
}
}
}

The main idea of heap_1 is that you can't free memory. It is simply not capable of doing so. If you want to delete tasks, you need to use other heap_n methods. Even in that case, you should let the kernel to do its job: It's kernels job to manage memory for FreeRTOS objects, not yours.
Actually, deleting tasks isn't considered as a good practice in general. Unless you are really low on heap space, you can simply suspend the task. In this way, you can wake it up again without any cost in case its services are required again.
It's true that an init task will become useless after the system initialization. But there is a well known solution for your init task problem: It can evolve into another task after it completes the initialization sequence. For example, Task_ini can create only Task_2, and instead of creating a Task_1, it can do the Task_1's job itself.
Update:
It's kernels job to manage memory for FreeRTOS objects, not yours.
Actually, FreeRTOS allows you to manage the memory manually, if you prefer to do so. There are static versions of object creation functions, like xTaskCreateStatic(). When using these static versions, you pass two statically allocated buffers to the function for the task stack and the task control block (TCB). Then you will literally be able to place one task onto another (provided that it's deleted). To be able to use these functions, configSUPPORT_STATIC_ALLOCATION must be defined as 1.
But I suggest you to avoid manual memory management unless you have a specific reason to do so.

Related

Does async operation in iOS create a new thread internally, and allocate task to it?

Does async operation in iOS, internally create a new thread, and allocate task to it ?
An async operation is capable to internally create a new thread and allocate task to it. But in order for this to happen you need to run an async operation which creates a new thread and allocates task to it. Or in other words: There is no direct correlation.
I assume that by async you mean something like DispatchQueue.main.async { <#code here#> }. This does not create a new thread as main thread should already be present. How and why does this work can be (if oversimplified) explained with an array of operations and an endless loop which is basically what RunLoop is there for. Imagine the following:
Array<Operations> allOperations;
int main() {
bool continueRunning = true;
for(;continueRunning;) {
allOperations.forEach { $0.run(); }
allOperations.clear();
}
return 0;
}
And when you call something like DispatchQueue.main.async it basically creates a new operation and inserts it into allOperations. The same thread will eventually go into a new loop (within for-loop) and call your operation asynchronously. Again keep in mind that this is all over-simplified just to illustrate the idea behind all of it. You can from this also imagine how for instance timers work; the operation will evaluate if current time is greater then the one of next scheduled execution and if so it will trigger the operation on timer. That is also why timers can not be very precise since they depend on rest of execution and thread may be busy.
A new thread on the other hand may be spawned when you create a new queue DispatchQueue(label: "Will most likely run on a new thread"). When(if) exactly will a thread be made is not something that needs to be fixed. It may vary from implementations and systems being run on. The tool will only guarantee to perform what it is designed for but not how it will do it.
And then there is also Thread class which can generate a new thread. But the deal is same as for previous one; it might internally instantly create a new thread or it might do it later, lazily. All it guarantees is that it will work for it's public interface.
I am not saying that these things change over time, implementation or system they run on. I am only saying that they potentially could and they might have had.

Shuld be a delay in a FreeRTOS task main loop?

Is it necessary to add some delay into the infinite loop inside a FreeRTOS task (created by xTaskCreatePinnedToCore())? Also, in my case, since the function aws_iot_mqtt_yield already takes a timeout (100) I tend to think the extra task delay is unnecessary.
My task looks like:
...
while(1) {
error = aws_iot_mqtt_yield(&m_client, 100);
check error...
vTaskDelay(10 / portTICK_RATE_MS);
}
...
No. You shouldn't need to add a delay. In fact in my opinion it is bad practice as it means you could be suspended at two different points in the task which can lead to very confusing program flow and is hard to debug.

printing the stack of a task in FreeRTOS

I am working on a STM32F4-discovery board, i installed FreeRTOS on the board and was able to run two tasks created by main function.
Now i want task 1 to access the local variables of task 2 with any passing of variable by reference or by value.
I thought it would be good to print the stack content of task 2 and then locate the local variables and use that in task1
Can somebody guide me with this?
I tried to print the address of each variable and tried to use in task1, but my program did not compile and returned -1.
It is not clear to me what you are trying to achieve, or what you mean by the program returning -1 because it didn't compile, but it would not be normal for one task to access a stack variable of another task.
Each task has its own stack, and the stack is private to the task. There are lots of ways tasks can communicate with each other though, without the need to access each other's stack. The simplest way is just to make the variable global, although global variables are rarely a good thing. Other than that you could send the value from one task to another on a queue (http://www.freertos.org/Inter-Task-Communication.html), or even using a task notification as a mailbox (http://www.freertos.org/RTOS_Task_Notification_As_Mailbox.html).
First, a cautionary note: what you're trying to do -- access local variables of one task from another -- can be error-prone. Particularly if the local is declared in Task A and goes out of scope before Task B accesses it. Since stack memory can be reused for different variables in different functions, Task B might be accessing some other variable.
But I've actually used this pattern in practice -- specifically, to allow one task to stack-allocate a buffer for communication serviced by another task.
So I'll just assume that you know what you're doing. :-)
It's difficult to compute the address of a local variable ahead of time. If you derive it today, it's likely to change if you change the code or compiler version. What you probably want to do is to capture its address at runtime and somehow make it available to the other task. This can be be tricky, however: it's possible for the other task to try to use the local before your task starts up, and nothing prevents other tasks from getting to it.
A slightly cleaner approach would be to provide the address to the other task through a queue shard by the two tasks.
QueueHandle_t shared_queue;
void common_startup() {
// This code might go in main, or wherever you initialize things.
shared_queue = xQueueCreate(1, sizeof(unsigned *));
}
void task_a() {
// This task wants to share the address of 'local' with task_b.
unsigned local;
// Stuff the address of our local in the queue. We use a
// non-blocking send here because the queue will be empty (nobody
// else puts things in it). In real code you'd probably do some
// error checking!
unsigned * ptr = &local;
xQueueSend(shared_queue, &ptr, 0);
while (1) {
do_stuff();
}
}
void task_b() {
// This task wants to use task_a's 'local'.
// Real code would do error checking!
unsigned * ptr;
xQueueReceive(shared_queue, &ptr, portMAX_DELAY);
while (1) {
// Just increment the shared variable
(*ptr)++;
}
}

Resart a task in FreeRTOS

I have a specific task routine which performs some operations in a specific order, and these operations handle few volatile variables. There is a specific interrupt which updates these volatile variables asynchronously. Hence, the task routine should restart if such an interrupt occurs. Normally FreeRTOS will resume the task, but this will result in wrong derived values, hence the requirement for restarting the routine. I also cannot keep the task routine under critical section, because I should not be missing any interrupts.
Is there a way in FreeRTOS with which I can achieve this? Like a vtaskRestart API. I could have deleted the task and re-created it, but this adds a lot of memory management complications, which I would like to avoid. Currently my only option is to add checks in the routine on a flag to see if a context switch have occured and if yes, restart, else continue.
Googling did not fetch any clue on this. Seems like people never faced such a problem or may be its that this design is poor. In FreeRTOS forum, few who asked for a task-restart didn't seem to have this same problem. stackOverflow didn't have a result on freertos + task + restart. So, this could be the first post with this tag combination ;)
Can someone please tell me if this is directly possible in FreeRTOS?
You can use semaphore for this purpose. If you decide using semaphore, you should do the steps below.
Firstly, you should create a binary semaphore.
The semaphore must be given in the interrupt routine with
xSemaphoreGiveFromISR( Example_xSemaphore, &xHigherPriorityTaskWoken
);
And, you must check taking semaphore in the task.
void vExample_Task( void * pvParameters )
{
for( ;; )
{
if (xSemaphoreTake( Example_xSemaphore, Example_PROCESS_TIME)==pdTRUE)
{
}
}
}
For this purpose you should use a queue and use the queue peek function to yield at your volatile data.
I'm using it as I have a real time timer and this way I make the time available to all my task, without any blocking.
Here it how it goes:
Declare the queue:
xQueueHandle RTC_Time_Queue;
Create the queue of 1 element:
RTC_Time_Queue = xQueueCreate( 1, sizeof(your volatile struct) );
Overwrite the queue everytime your interrupt occurs:
xQueueOverwriteFromISR(RTC_Time_Queue, (void*) &time);
And from other task peek the queue:
xQueuePeek(RTC_GetReadQueue(), (void*) &TheTime, 0);
The 0 at the end of xQueuePeek means you don't want to wait if the queue is empty. The queue peek won't delete the value in the queue so it will be present every time you peek and the code will never stop.
Also you should avoid having variable being accessed from ISR and the RTOS code as you may get unexpected corruption.

pthread_create and EAGAIN

I got an EAGAIN when trying to spawn a thread using pthread_create. However, from what I've checked, the threads seem to have been terminated properly.
What determines the OS to give EAGAIN when trying to create a thread using pthread_create? Would it be possible that unclosed sockets/file handles play a part in causing this EAGAIN (i.e they share the same resource space)?
And lastly, is there any tool to check resource usage, or any functions that can be used to see how many pthread objects are active at the time?
Okay, found the answer. Even if pthread_exit or pthread_cancel is called, the parent process still need to call pthread_join to release the pthread ID, which will then become recyclable.
Putting a pthread_join(tid, NULL) in the end did the trick.
edit (was not waitpid, but rather pthread_join)
As a practical matter EAGAIN is almost always related to running out of memory for the process. Often this has to do with the stack size allocated for the thread which you can adjust with pthread_attr_setstacksize(). But there are process limits to how many threads you can run. You can query the hard and soft limits with getrlimit() using RLIMIT_NPROC as the first parameter.
There are quite a few questions here dedicated to keeping track of threads, their number, whether they are dead or alive, etc. Simply put, the easiest way to keep track of them is to do it yourself through some mechanism you code, which can be as simple as incrementing and decrementing a global counter (protected by a mutex) or something more elaborate.
Open sockets or other file descriptors shouldn't cause pthread_create() to fail. If you reached the maximum for descriptors you would have already failed before creating the new thread and the new thread would have already have had to be successfully created to open more of them and thus could not have failed with EAGAIN.
As per my observation if one of the parent process calls pthread_join(), and chilled processes are trying to release the thread by calling pthread_exit() or pthread_cancel() then system is not able to release that thread properly. In that case, if pthread_detach() is call immediately after successful call of pthread_create() then this problem has been solved. A snapshot is here -
err = pthread_create(&(receiveThread), NULL, &receiver, temp);
if (err != 0)
{
MyPrintf("\nCan't create thread Reason : %s\n ",(err==EAGAIN)?"EAGAUIN":(err==EINVAL)?"EINVAL":(err==EPERM)?"EPERM":"UNKNOWN");
free(temp);
}
else
{
threadnumber++;
MyPrintf("Count: %d Thread ID: %u\n",threadnumber,receiveThread);
pthread_detach(receiveThread);
}
Another potential cause: I was getting this problem (EAGAIN on pthread_create) because I had forgotten to call pthread_attr_init on the pthread_attr_t I was trying to initialize my thread with.

Resources