Threads can be scheduled either as normal threads or as work. To decide which type is appropriate for a given thread, consider the following sections.
NOTE:Work is unique to the 4.x, 5.x, and 6.x OS. If your NLM is going to run on 3.x servers, you cannot schedule threads as work.
The following conditions serve as guidelines for when to schedule a routine as a thread:
If a routine is a long-term process, little benefit results from scheduling it as work because work that yields cannot be rescheduled as work. Instead, it is rescheduled on the Run Queue at the same priority as a normal thread.
All work is given a single stack size; but you can specify a stack size for threads. If you need to specify the stack size, you must schedule your routine as a thread.
If your routine is a polling process or one that does spin-waiting, you should schedule it as a thread.
In general, if your NLM already uses the NetWare 3.x process-scheduling scheme-which can still be carried out in the NetWare 4.x, 5.x, and 6.x kernel-and its routines are mostly long-term, continue to schedule the routines as threads. But if any of the routines are short-term, you can reschedule them as work.
NOTE:If your NLM is going to run in the NetWare 3.x environment as well as in the NetWare 4.x, 5.x, and 6.x environment, you cannot schedule any threads as work, since work does not exist in the NetWare 3.x environment. Schedule all threads then as normal threads.
Changing Thread Priority: It is possible to change the priority of a thread in one of ways described in the following sections.
(NetWare 4.x, 5.x, and 6.x) If a particular NLM does not yield often enough, the OS places a handicap in the NLM thread’s process control block (PCB), which prevents the thread from being rescheduled immediately. For example, it the OS places a handicap of 100 on a thread, 100 other pieces of work or threads run and yield before the handicapped thread is rescheduled in the RunList Queue.
A thread can also handicap itself by calling SetThreadHandicap.
(NetWare 3.x, 4.x, 5.x, and 6.x) If a thread needs a resource that will not be ready for a moment, but you do not want it to assume the overhead of sleeping on a semaphore or doing busy waiting, you can have the thread reschedule itself with a temporary handicap using ThreadSwitchWithDelay.
An example of busy waiting is the following:
while (!finished)
ThreadSwitchWithDelay();
Temporarily handicapped threads are not placed in the Run Queue until their handicap has expired. Upon expiration, they are rescheduled at the end of the Run Queue. Letting threads temporarily handicap themselves prevents needless rescheduling overhead caused by a busy-waiting condition.
Temporarily handicapping threads is an issue for NetWare 4.x, 5.x, adn 6.x OS since the Low-Priority Queue does not gain control of the CPU unless there is nothing else for the CPU to do. If a thread does "busy waiting", continually rescheduling itself on the Run Queue (by using ThreadSwitch), the Low-Priority Queue cannot gain control of the CPU.
(NetWare 4.x, 5.x, and 6.x) Low priority threads run when there is nothing to run except hardware polling routines and temporarily handicapped threads. Programs that might be candidates for low priority threads are file compression utilities, once-a-week backup, and cleanup utilities.
A thread can reschedule itself as a low priority thread by calling ThreadSwitchLowPriority.
To maintain a thread as low priority when you relinquish control, you must use ThreadSwitchLowPriority. If you use ThreadSwitch, the thread becomes a regular thread.
The following criteria can help determine when you should schedule a routine as work:
A database request routine needs to gain access to the processor quickly and does not need to yield before it is completed. The performance of the database would be enhanced by scheduling requests as work, so that the work is serviced quickly and the CPU is relinquished to the next thread.
Similarly, scheduling end-of-routine cleanup as work enhances the operation of all threads in the kernel. A task such as freeing up the stack needs to be executed immediately after a routine ends, and is quick.
Other candidates for work are service routines, which check and update an item regularly. A service routine that updates object information for network management, for example, could be scheduled as work.
In general, NLM applications benefit when lower-level services are scheduled as work. For example, repetitive services such as disk reads could be scheduled as work. NetWare typically does a lot of disk reading. The entire operation usually completes without yielding because the data is found in cache memory.