Create task without starting it?

I am migrating a code base over from eCos to FreeRTOS. In eCos, you can create a thread and then resume it at a later time, e.g., the thread creation does not automatically start running the thread. I would like to do something similar with FreeRTOS because we do some initialization and want all the threads to start after that initialization. Is this possible with FreeRTOS? I didn’t see a task creation function that would take a flag or anything to not start the thread.

Are you creating the threads before starting the scheduler? If so, you can create the thread and then suspend it - so when the scheduler starts it is already in the suspended state.

No, they may be created at any time, mostly after the scheduler is started.

If this feature doesn’t exist, would a PR with an implementation be allowed, or should I just implement locally?

In addition to Richard’s proposal you might simply implement your own task code wrapper with vTaskSuspend(NULL); as task code preamble (right before the real task code begins) along with a taskStart function just initially resuming this task.
This works regardless if the scheduler already runs or not.
I wouldn’t create a PR for this rather specific / eCos like use case.

If we can think of a backward compatible way of implementing this then we could add it as a new feature.

I can only think of an extended API like xTaskCreateSuspended putting it into the suspended instead of ready list… This would also avoid tailored (self-suspending) task code.

there are numerous ways of implementing this… for example, the task parameter could point to a structure one parameter of which is a (n initially owned) semaphore that must explicitly signalled to start the thread fn.

I agree that it could be a useful feature, but as Richard Barry says, the problem is backward compatibility. I think this really would need a new set of creating functions to do, and that starts to make things start to explode as we already have static and dynamic, and then we have create restricted (which can only be done as static).

As has been mentioned, you can do this sort of already in a couple of different ways.

One is wrapping the task function with a function that suspends/blocks itself and then calls the normal task function.

Another is to create it at a lower priority than you, then suspend it, then change its priority to what you want (if it would be equal or higher than yours).

You can also just define your task to start with the blocking/suspending unless there is a real reason that needs it to start suspended (my task wrapping class have that issue, you want to let the task class finish constructing before letting the task that will use that class fully start)

Except for that wrapping issue, I find little need to start a task suspended, as either I will be creating the task I will need some point in the future at startup time, or I really need it NOW, so don’t want to create it suspended.

There is also the concept that in most cases ‘suspending’ a task if rarely what you want to be doing, the task should be naturally blocking until it has something to do, at which point that work arriving causes it to unblock and run…

Thanks everyone for your suggestions. I’ll take a look at each one and decide which will work best for me. Thanks again!

Be aware that there is a drawback using the cheap self-suspend approach. There is a chance of a subtle race condition resuming the created task not yet self-suspended as this is part of the task code and the task needs a chance to run…
Resuming a non-suspended task does nothing, as mentioned task suspend/resume is a special tool. So you’d need to take some extra measures (e.g. boosted create prio, poll task state using eTaskGetState, …) to handle this.
Using a real sync object like a semaphore or something else as @RAc proposed would be safe.
Getting rid of the splitted create/start approach would avoid all of this :wink:

Thanks, Hartmut. I also agree with you that adapting this OS specific feature is probably not worth adding to the standard API set. I remember porting something from Kadak’s AMX (which had this feature) to FreeRTOS, and when I came across the same porting issue, I looked at the original code closer just to discover that it would have been much cleaner to restructure the code in the first place, so that’s what we did.

That said, I can think of a more generic approach where you could split a FreeRTOS task into an init phase followed by the infinite loop. The first part could be traversed as soon as the scheduler allows the task to run, whereas the second part would require explicit triggering. If the first part is empty, semantics are equivalent to eCOS and AMX’s start suspended.

But again, every such feature leaves the sour taste of “RTOS lock-in” on the tongue, because if it’s part of the OS, it’ll make it harder to port to another RTOS later on and thus discourage a migration. IMHO there should be a very good reason for any such addition which would be true added value. Like @richard-damon and @hs2 , I don’t see a true added value in this; it’s straightforward enough to implement custom tailored. Maybe add a sample to the plus tree?

Well you are free to define your task the way you want, so you can write that initial section that will run as soon as it can, then you can put an explicit block till you are ready to go to the second part.

It is only if you are using some ‘special sauce’ of the OS to make that explicit block be implicit that you get into trouble, and that is what creates the locking.

I would say also that Io would actually NEVER use ‘suspend’ for this operation, due to the race conditions, but a direct-to-task notification wait, as that gets rid of the race completely.

I want to update this topic because I ran into the exact same problem.

I do not understand that there is no “true added value”. In times where C++ is way more used and abstraction-layers are created which should enable to exchange the OS it is really dangerous to just start a task as soon as the C-function xTaskCreate is called. Because the constructor is not finished and if the run-function is hit and some abstraction-specific managment must be done related to the task itself inside the constructor you will experience data aborts because the Object never finished its construction and member variables or other entities are not available.
So NOT providing it is the real “RTOS lock-in” because you are bound to FreeRTOS now and probably need to rework your abstraction layer only for FreeRTOS.
The scenario also can be extended like in our case where we have multiple cores where each core has its own FreeRTOS-instance (SMT is not possible since we are bound to a vendor which provides the FreeRTOS implementation). There must be an init-task since interrupts for IPC are not activated before the scheduler is started.
So it works having the init-task at highest priority. But as soon as you create another task at highest priority (e.g. a watchdog-task) it could happen that it just starts to run right at calling xTaskCreate. So our workaround is to forbid having the highest priority but that also just erases one prio for the whole system. We tried using an active flag to decide how the task should behave (because some tasks should start running in parallel to the init-task, e.g. a watchdog task, which also needs to have the highest priority) and to suspend it inside the run-function if the flag is not set.
But when the Constructor is not finished, you could get a data abort as soon as the flag is checked or in the concrete case the state of the task for the Watchdog is set or if the back-pointer to the C+±object (which has not finished construction) is used. So this is also no reliable solution.

So I just can conclude that the “RTOS lock-in” is only present because we use FreeRTOS and we are locked in to it and need to do workarounds for it e.g. defining that the highest prio should never be used by any other task but the init-task.

Unless you can show that this is a feature commonly provided by other RTOSes, it is hardly a locking.

I will note that it only really becomes a problem if creating a Task while the scheduler is running with a priority Greater Than or Equal to the creating task (and equal is the nastier case, as it becomes intermittent).

My C++ wrappers currently handle the condition by changing the priority of the task to be created (if needed and possible) to be less than the priority of the creating task (and documenting the issue). The interface stub to the function then will set the priority to the desired priority before calling the provided task functon/member.

Some key points:
Most true embedded systems don’t need dynamically created tasks. I can normally create all my tasks before the scheduler is started, and thus it isn’t an issue.

If you do need to create a task dynamically, then you tend to have a built in race in constructing the C++ object and the task, either the task creation must be the last Thing the constructor does (and even with delayed starting, you need that start to be the last thing done), so it can’t be done as a base class unless you have otherwise dealt with the inherent race,

Priority is a very workable solution to this problem.

If you want the task to start “suspended:”, you just need to you C tampoline stub to begin with a suspend call before calling your provided C++ function. I will point out that your C++ function almost certainly doesn’t have the right signature to be directly used as the task function, so you will have a trampoline, where you can do this step before getting into the real function.