Yield the CPU VP

To preserve the availability of the CPU VP, a well-behaved C UDR must ensure that it regularly yields the CPU VP to other threads. A C UDR might yield when it calls a DataBlade® API function because DataBlade API functions automatically yield the VP when appropriate.

For example, the UDR thread might migrate to the AIO VP to perform any of the following kinds of I/O:
  • Smart-large-object I/O with a DataBlade API function such as mi_lo_open(), mi_lo_read(), or mi_lo_write()
  • External-file I/O with a DataBlade API file-access function such as mi_file_open(), mi_file_read(), or mi_file_write()

Therefore, you can assume that thread migration might occur during execution of any DataBlade API function.

However, if your C UDR performs any of the following types of resource-intensive tasks (which do not involve calls to DataBlade API functions), your UDR does not automatically yield the VP:
  • A task that is CPU- or I/O-bound
  • A task that causes other threads to wait for an undue length of time (usually longer than 0.1 seconds)

For such a C UDR to be well-behaved, it must explicitly yield the CPU VP with the DataBlade API function mi_yield(). The mi_yield() function causes the thread that is executing the UDR to voluntarily yield the CPU VP so that other threads get a chance to execute in the VP. When the original thread is ready to continue execution, execution resumes at the point immediately after the call to the mi_yield() function.

Write your C UDR so that it yields the VP at strategic points in its processing. Possible points include the beginning or end of lengthy loops and before and/or after expensive computations. Judicious use of mi_yield() generally leads to an improved response time overall.

If you cannot code the C UDR to explicitly yield during resource-intensive passages of code, the UDR is considered an ill-behaved routine and must not execute in the CPU VP. To isolate a resource-intensive UDR from the CPU VP, you can assign the routine to a user-defined VP class. To determine which kind of user-defined VP to define, you must also consider whether you need to preserve availability of the user-defined VP. Keep in mind that all VPs of a class share a thread queue. If there are multiple users of your UDR, multiple threads can accumulate in the same thread queue. If your UDR does not yield, it blocks other UDRs that execute in the same VP class. Therefore, the VP might not effectively share between users. One user might have to wait while the UDR in the query of some other user completes.

You can use a user-defined VP to execute a resource-intensive routine:
  • To preserve availability of a user-defined VP, execute the routine in a yielding user-defined VP.

    Within your UDR, you can use the mi_yield() function to yield the user-defined VP to other threads that execute in the same VP class. To increase availability, you can define multiple instances of the yielding user-defined VP.

  • If you cannot rewrite the routine to yield, add more user-defined VPs.

    A nonyielding user-defined VP is used for code that must maintain ownership of the process until it completes. A nonyielding VP might modify a global variable or use a command resource that cannot be shared.