QOS ADMISSION

STARTING THE QOS ADMISSION THREAD:

QoS admission is the result of the negotiation process performed by the SRMS service's QoS negotiator, also known as the QoS admission thread. Once a task is registered, it is ready to request QoS admission into the system. The task has the option of calling either a blocking or non-blocking function, and the SRMS API supports both methods with the functions request_QoS_admission() and await_QoS_admission() respectively. Depending on the call, these functions will send either a WM_Request_QoS_AdmissionMsg or WM_Await_Qos_AdmissionMsg along with the task's thread id in a message to the SRMS service's message queue. Upon receiving that message, the service's message handler calls the SRMS internal functions process_request_QoS_admission()or process_await_QoS_admission() respectively to handle the request. These functions use the task's thread id that is sent with the message to locate the task's entry in the registered task list. After removing the entry from that list, the function adds it to the end of the request_queue or the await_queue. Both queues are FIFO queues that contain a doubly-linked list of task_struct entries. The need for two queues becomes more apparent with the explanation of the QoS admission thread later in this section.

Finally, the last job remaining for the process functions is to create the QoS admission thread if it is not already active. The createQosAdmissionThread() function handles the small task of creating the QoS admission thread and setting its priority. The function creates a child thread and directs it to start its work with the QosAdmissionThreadProc() function.  It also assigns the QoS admission thread to run at the same priority as the message handler thread, which is at a level lower than the SRMS scheduler and real-time task set.  By operating at that level, the thread should not steal any CPU cycles away from the SRMS scheduler or the task set.  This basically means that the QoS admission thread only gets a control of the processor when the SRMS scheduler is idle and the tasks have no real-time work to do. 

QOS ADMISSION THREAD OVERVIEW:

The primary goal of the QoS admission thread is to determine if the system can meet the requested quality of service of a particular task. The system must process all non-blocking requests first so that a task waiting for a response from a non-blocking call is delayed as little as possible. SRMS facilitates the non-blocking request via the request_queue. Ideally, the QoS admission thread could be processed by a second processor that speeds up the time to calculate a quality of service estimate, so a request queue to handle relatively fast calculations seems unnecessary. However, a uni-processor implementation as seen here can rely heavily on a request queue. Since QoS calculations grow exponentially with the number of phases between two consecutive, rate-monotonically ordered tasks, a task set with large differences between consecutive periods can cripple a processor with lengthy calculations. This, coupled with the fact that the lower priority QoS admission thread is frequently preempted by the SRMS scheduler and task set, can lead to unpredictable QoS calculation times. Uncertainty and unpredictability such as this contributed to the creation of a request queue.

Therefore, the goal of the QoS admission thread is to satisfy all requests from the reqeust_queue on a first come, first serve basis. If the system can meet the task's requested QoS, then the task is admitted. Regardless of the result, the system sends the task its estimated QoS value and removes it from the request_queue. Once the request_queue is empty, the QoS admission thread tries to satisfy requests from the blocking call, which are waiting in the await_queue. This queue is also serviced in a FIFO manner, but if a request cannot be met, then the thread leaves the task in the await_queue and terminates itself. That queue will be serviced later when the thread gets recreated due to a change in the active task set, either by a new task entering or an old task leaving the system. Instead, if a task from the await_queue can be guaranteed its requested quality of service, then the task is added to the system and notified, removed from the queue, and the QoS admission thread continues to service the next task waiting in the queue until it is empty.

The QoS admission thread can also play a secondary role depending on the value of the data that is passed to from createQosAdmissionThread() when it is first created. Notice that the function QosAdmissionThreadProc() takes a parameter called lpQosThreadParam as input. If the value that it points to is equal to SRMS_RECOMPUTE_SYSTEM, then the first job of the thread is to recompute the allowance and expected QoS values for the entire SRMS system after an active task has left the system. Upon completion, it services the request and await queues as described above.

INSIDE THE QOS ADMISSION THREAD:

As described above, there are three main responsibilities of the QoS admission thread. First, if an active task leaves the system, then it must recompute the QoS and allowance values for the new task system. Then it services all tasks in the request queue and finally services as many tasks as possible from the await queue until either it is empty or a task's QoS cannot be satisfied. The function QosAdmissionThreadProc() contains three sections with these goals in mind.

Note that the QoS admission thread does not place a lock on the SRMS system's task_list or qos_list while processing QoS and allowance calculations. Doing so would cause very unpredictable timing results since both the SRMS scheduler and QoS admission threads would be competing for access to a shared list. Instead, all computations are performed on a copy of the qos_list, and the only time a list is locked by the QoS admission thread is during the reading and writing of that list.

PART 1 - RECOMPUTING THE SYSTEM:

The thread only recomputes the system if the parameter lpQosThreadParam equals SRMS_RECOMPUTE_SYSTEM. In this case, a registered task must have unregistered, so the unregister_task() function calls createQosAdmissionThread() with a parameter signaling it to recompute the system. The first thing that the QoS admission thread does is it makes a copy of the qos_list using the CopyQosList() function. CopyQosList() waits to obtain a lock on the qos_list, and when it finally does, it returns a pointer to an exact replica of the list. This copy is then passed to SpecifySystem() which either returns true if the new system met all of its tasks' QoS requirements or false if it failed any of them. In this section, the return value will always be true since an exiting task will only free up system resources, not take an away. Next, it checks the dirty bit of all entries in the qos_list to see if any changes had been made to the system task_list since the copy was made. If a dirty bit is set, then a new copy of the qos_list needs to be made and the calculations redone. Otherwise, the QoS admission thread can proceed to confirm the new values in the system's task_list.

PART 2 - SATISFYING NON-BLOCKING REQUESTS:

The next section of the QoS admission thread handles all non-blocking admission requests found in the request_list. With a call to CopyQosInfoFromTask(), the thread makes a copy of all pertinent QoS information from the task entry at the head of the request_list and returns that information in a qos_task_info_struct pointed to by myQosInfo. After making a copy of the qos_list, the thread inserts the myQosInfo structure into the copy using the InsertQosInfoIntoList() function. When this function finishes, the qos_list_copy points to a new rate monotonically ordered task set that includes the task being tested. This new task set is given to SpecifySystem() and it returns either true or false depending on whether the new system is supportable or not. If the new system passes, then the task can be admitted into the system. In that case, all new QoS and allowance values need to be confirmed in the system's task_list and qos_list. Before making any changes, however, the thread first verifies that no dirty bits are set in the qos_list and then it copies all new information from the qos_list_copy to the qos_list. If any entry is missing or has its dirty bit set, then that means that the active task set has changed since the copy was made and all calculations need to be redone. Once all values are updated in the system lists, then the QoS admission thread sends the SRMS scheduler thread a WM_AdmitNewRTtask message and waits for it to process that message and set the hNewTaskAdmittedEvent handle. (See the section on admitting a new task). While the QoS admission thread is waiting, the SRMS scheduler removes the task from the request_list, adds it to the task_list, and notifies the task that it has been admitted into the system. Finally, once the QoS admission thread wakes from its wait state, its last job is to add the myQosInfo structure into the qos_list, which makes all changes final and the addition of the new task complete. However, if the new system generated with this new task returns a false value from the SpecifySystem() function, then task being tested is sent a WM_QoS_Admission_FailedMsg and the task is removed from the request_queue. This process is repeated for all tasks in the queue until it is empty.

PART 3 - SATISFYING BLOCKING REQUESTS:

Finally, once the QoS admission thread finishes servicing the request_queue, it moves on to the final section servicing as many of the requests as it can satisfy in the await_queue. The procedure is exactly the same as described above for the non-blocking requests except that the QoS admission thread terminates itself when a a false value is returned from the SpecifySystem() function. QoS admission ceases until an active system task unregisters and frees up resources. When this happens, the QoS admission thread is restarted and the task that failed admittance at the head of the await_queue will be tested again under different conditions.   Eventually, once enough tasks unregister, tasks that fail admittance can finally gain admittance into the SRMS system.

< Back to the SRMS Service Home Page >