Job Queues would be a great addition to ChibiOS, allowing threads to "delegate" scheduled jobs to other threads in a buffered way. This would reduce the need for some types of overly-simple dedicated threads, and has potential to become a common ChibiOS "Design Pattern".
Hi All,
I've noticed a number of new features being added to ChibiOS. I noticed the Delegate Threads in particular seem simplify a small family of issues that can make concurrency difficult. I would like to describe, propose and discuss a similar feature which would greatly simplify a number of similar, though broader set of problems that Delegate threads seem to get "close" to solving.
Job Queues, (or jobqs for short) are found in a number of other RTOSs, and even general purpose OSs. They typically allow one thread to delegate function calls to a pool of worker threads via a queue. This is particularly helpful when handling a large number of asynchronous, low priority events with possibility for periodic work.
This approach is perhaps unneccessary in many ChibiOS applications, where it is likely more desirable to minimize the number of threads in the application.
An alternative method to function call delegation I've seen done is the method I would love to see added to ChibiOS.
In this method, a thread can be allocated an associated job-queue, which can have job-queue "jobs" added to by any thread - including the associated thread.
The thread simply runs a job from the jobq if the dedicated jobq event bit is raised. This allows the thread to handle other, unrelated events - unrelated to whatever gets placed on it's job queue.
Where this becomes more interesting, and very useful, is in the calling thread's API, which is able to add jobs to a job queue at a specified target time, so you can set up one-shot, and periodic jobs for another thread to handle. The API could look something like this:
Code: Select all
chJobq_t my_jobq;
chJobfn_t my_job_fn;
uint32_t param = 3;
void * param_p = (void*)¶m;
// Use PERIOD_MS = 0 to add to job queue once
chJob_t my_job = { my_job_fn, PERIOD_MS };
chJobq_init( &my_jobq );
// This is a non-blocking alternative to Delegate Threads
// The job is added to the target thread's job queue now,
// and the job raises the thread's job queue event bit when the target time arrives
chJobq_addJob( &my_jobq, DELAY_MS, &my_job, param_p );
// Removes the job from the job queue if it is present
// This can cancel a previously scheuled job, or stop of periodic job
chJobq_removeJob( &my_jobq, &my_job );
// Called from the target thread's event handler
// It's probably best if the thread only runs 1 job from the job queue per invocation
// After running the job, this function can check for more jobs in the queue
// If there are more ready to run, this function can send the job queue event flag to this thread again
if( events & JOBQ_EVENT_BIT )
chJobq_runJob( my_jobq );
Further thought about this feature reveals that it is a non-blocking superset of the Delegate thread feature (which I believe blocks the calling thread until execution is completed).
This feature would be very powerful to have, allowing a single thread to delegate jobs to other threads, but also when to do so, and in a queued manner - preventing lost jobs.
Image starting a simple LED blinking feature with this method. We may see a reduced occurrance of "blinker threads", dedicated to a overly-simple task that doesn't typically have hard real-time deadlines to meet. It could added to a job queue to simplify the API, and reduce the memory used by yet another thread.
For another example, you could make simple, high priority input/output threads that handle jobs sent by ISRs. Similar to DSP-BIOS concept of "Software ISRS".
For example, making a basic button debouncer with this method could be as simple as adding delayed one-shot jobs to job queues from inside the EXTI ISR, allowing threads to wake up later to check on the bounce state of the GPIO. Since these jobs are all queued, one thread could handle many EXTI interrupts/bounces on different EXTI lines this way. This simplifies your applcation business logic by allowing the "software interrupt" to send debounced button events to the interested threads in the application.
I believe this could be done in ChibiOS, since a number of the needed mechanisms already exist.
It might be a combination of the timed events and mailboxes. After trying to do this with the VTs as they are written, the VT has to buffer the future events for ALL jobs on ALL job queues across the applcation - which is not very efficient for the kernel. Additionally, I have to define an interrupt-context function that wakes up the target thread for every job I define. It would be nice to have a kernel-level mechanism that allows a thread to track it's own scheduled jobs once the job queue is added to once.
Please discuss with feedback, and problems you might notice. I think this is a cool feature, but I think it needs to be implemented carefully.
TLDR:
Job Queues would be a great addition to ChibiOS, allowing threads to "delegate" scheduled jobs to other threads in a buffered way. This reduce the need for dedicated threads, and has potential to become a common ChibiOS "Design Pattern".
Thanks!