I am rather new to vxworks(I am using version 6.7), and I find that when I spawn a child task, the parent seems to block till the child task completes. Perhaps, my understanding is not correct, and there is some parameter to be set in taskSpawn(), telling it not to block till the code task had completed.
Is there such a parameter or is there some other mechanism to bit make the parent task wait for completion of the child?
You should check priorities for your tasks. The default VxWorks scheduler is priority-based preemptive scheduling.
Related
Consider the following situation:-
Assume that we need to do heavy tasks in a lot of files in our app,
and we create a coroutine for each task,
if we run the app, then the app process will exit before those coroutines finish their work.
someone would suggest to use job.join() for every coroutine,
But this solution will block the parent threads that we created the coroutines in,which will cause problems for me because I'm already executing some other work in these parent threads.
Knowing that if we put those heavy tasks in new threads instead of coroutines then the app process will not exit until all the threads finish their work.
How to make the app process doesn't exit until all the coroutines finish their work, without blocking their parent threads via using job.join()?
In other words how to make the app process wait for the coroutines like how it waits for the threads?
Also I don't want to use async-await because it will also will block the parent thread.
Can you explain the difference between sc_spawn and another process (SC_METHOD, SC_THREAD, SC_CTHREAD )?
Thanks all.
Hook
To understand this, you have to get an idea of the phases of elaboration and simulation of SystemC first. The phases of elaboration and simulation shall run in the following sequence (from IEEE Std 1666-2011:
Elaboration—Construction of the module hierarchy
Elaboration—Callbacks to function before_end_of_elaboration
Elaboration—Callbacks to function end_of_elaboration
Simulation—Callbacks to function start_of_simulation
Simulation—Initialization phase
Simulation—Evaluation, update, delta notification, and timed notification phases (repeated)
Simulation—Callbacks to function end_of_simulation
Simulation—Destruction of the module hierarchy
Processes are objects derived from sc_object and are created by calling SC_METHOD, SC_THREAD, SC_CTHREAD, or the sc_spawn function.
If a process is created created during elaboration (1.) or the before_end_of_elaboration (2.) it is a static process. If it is created during the the end_of_elaboration (3.) callback or during simulation, it is a dynamic process.
A process instance created by the SC_METHOD, SC_THREAD, or SC_CTHREAD macro is an unspawned process instances and is typically a static process. Spawned process instances are processes created by calling sc_spawn. Typically, they are dynamic processes, but can be static if sc_spawn is called before the end_of_elaboration phase.
This means, to wrap this up in simple words, that sc_spawn enables you to dynamically add processes during simulation. For example: there can be cases where you only need a certain process, if a certain condition during your simulation becomes true.
Now let's take a look where the processes spawn during the simulation. The actual simulation of SystemC (6.) consists of these phases:
Initialization Phase—Execute all processes (except SC_CTHREADS) in an unspecified order.
Evaluation Phase—Select a process that is ready to run and resume its execution. This may cause immediate event notifications to occur, which may result in additional processes being made ready to run in this same phase. Repeat, as long as there are still processes ready to run.
Update Phase—Execute any pending calls to update() resulting from request_uptdate() calls made in step 1 or 2.
Delta notification phase—If there are pending delta notifications (result from calls to notify()), determine which processes are ready to run due to the delayed notifications and go to step 2.
Timed notification phase—If pending timed notifications or time-outs exist:
advance simulation time to the time of the earliest pending timed notification or time-out;
determine which process instances are sensitive to the events notified and time-outs lapsing at this precise time;
add all such process instances to the set of runnable processes;
If no pending timed notifications or time-outs exist → end of simulation. Otherwise, go to evaluation phase.
If sc_spawn is called to create a spawned process instance, the new process will be added to the set of runnable processes (except if dont_initialize is called). If sc_spawn is called during the evaluation phase, it shall be runnable in the current evaluation phase (2.). If it is called during the update phase (3.), it shall be runnable in the next evaluation phase.
If sc_spawn is called during elaboration, the spawned process will be a child of the module instance which calls sc_spawn. If it is called during simulation, it will be a child of the process that called the function sc_spawn. You may call sc_spawn from a method process (SC_METHOD), a thread process (SC_THREAD), or a clocked thread process (SC_CTHREAD).
This tutorial shows the difference between implementing processes through SC_METHOD and SC_THREAD, and sc_spawn.
After the Task 1 is completed, we need to spawn an optional task, based on a condition. The process completion does not depend on this optional task completion.
What is the correct way to design this model ?
the desired behaviour can be modeled like this:
After Task1 completes Task2 is triggered, if the optional Condition is true, the optional Task is triggered as well.
The Instance is terminated after Task2 is finished. If the optional Task was still active it will be terminated.
You should use conditional marker for the optional flow.
Exclusive gateway in your diagram will always execute mandatory Task 2, optional task will always be ignored even when the condition for its execution is true.
Parallel gateway can not be used as it will wait for the optional task to complete for successful merge.
Are conditional markers BPMN 2.0 ok? not even seen them before except they remind me good old UML.
I think this should be solved using a XOR gateway.
Using non-interrupting (message/signal/escalation) events will help your scenario.
Alternatively, using event subprocess in this process.
Let me know if you understand how to use it. Otherwise, I will draw an example for you
UPDATE
NOTE:
1. I am only using bpmn.io to draw example instead of Camunda. However, this is basic BPMN and I assume Camunda must have this type of model. I am only familiar with JBPM.
EXPLANATION:
Basically, you don't really have to use message event. It can be signal/escalation depending on what scenarios you have. Theoretically, message event is used if there is an incoming message to create other activities and this event is the most common among the others. Yet, one thing you must consider is whether the event is interrupting or not. In your case, it doesn't interrupt, therefore I put non-interrupt message event.
Interrupt message event will abort the Task 1 immediately as soon as the event is triggered while non-interrupting is only adding additional task/event without aborting Task 1.
Hope this example helps.
I know how waitpid(-1...) allows me to wait until all children have finished, such as waitpid(-1, &status). But how can I wait until all background processes are finished? Someone suggested that I can use the same waitpid (in a loop?) to achieve this but I don't see how.
To be clear, I'm implementing a shell, and need to add a new built-in command wait, which waits until all background jobs have terminated before returning to the prompt.
I read somewhere else on SO that "You will also want to call waitpid() with the WNOHANG option regularly - say, immediately before you display the shell prompt. This will allow you to detect when the background process has exited or stopped " But again, child != background. So even that I don't believe.
Edit:
I ended up just doing while(wait(NULL) > 0); and that's it, it worked. But what I'm still confused about is don't I WANT to make a distinction between foreground and background because the wait I'm implementing only waits for the background processes, and all children are equal in the eye of wait() or waitpid().
So again, the children I'm waiting for by using wait() or waitpid() aren't necessarily background processes. Am I wrong?
Since you ask in the context of implementing a shell, and evidently your shell supports enough job control to have a concept of background processes, it is reasonable to suppose that your implementation will have a table in which it tracks background jobs. That table can and should track the PID of the process associated with each job.
Having those PIDs in hand, you can waitpid() for specific background jobs until there are no more in the table, or you can waitpid(-1) to collect
any and every job, in a loop, until there are no more background jobs in the table.
If you want to implement background process (and job control) and catch their termination (at least) you must set a signal handler for SIGCHLD, and call wait(-1) inside it. This will let your shell receive asynchronous notifications of background processes termination. You may have a look at Catching SIGCHLD for example and discussion about this.
How can I make my thread sleep first before it runs? I know how to get sleep to work, however, whenever my program is run, the thread immediately runs. I want it to WAIT once it is first created to start running. (I am using handlers)
You cannot control when threads are scheduled. If you want it to go to sleep, have the first statement in the thread subroutine do a wait on a condition or something like that and when you are ready you can broadcast to that condition. In pseudo-code:
get-lock
if (we-are-still-supposed-to-sleep)
pthread_cond_wait()
release-lock
I suppose you could have the parent hold the lock while creating the children and then all they have to do is:
get-lock
release-lock
and avoid the condition thing.
What OS? Windoze allows you to create threads in a suspended state. When you have loaded up the thread fields in the ctor, you can resume the thread. Failing that, pass some synchro object in the thread start parameter for the new thread to wait on.
Rgds,
Martin.