Port Windows IPC Apps to Linux, Part 1: Processes and Threads
By Srinivasan S. Muthuswamy, Kavitha Varadarajan
2005-06-16
Examples of processes and threads
To wrap up this installment, let's look at some examples of the following types of processes and threads:
- Normal or regular processes and threads
- Time-critical and real-time processes and threads
Normal or regular processes/threads
The Linux system call setpriority() is used to set or modify priority levels for normal processes and threads. The parameter scope is PRIO_PROCESS. Set id to 0 to change the current process (or thread) priority. Again, delta is the priority value -- this time in the range -20 to 20. Note also that in Linux, a lower delta value means a higher priority. So you set +20 for IDLETIME priority and 0 for REGULAR priority.
In Windows, the priority range is from 1 (lower priority) to 15 (higher priority) for the regular threads. But in Linux, the priority range for normal non-real-time processes is from -20 (higher) to +20 (lower priority). This has to be mapped before being used: int setpriority(int scope, int id, int delta);.
Time-critical and real-time processes and threads
You can use the Linux system call sched_setscheduler() to change the scheduling priority and policy of a running process: int sched_setscheduler(pit_t pid, int policy, const struct sched_param *param);.
The parameter policy is the scheduling policy. The possible values for policy are SCHED_OTHER (for regular non-real-time scheduling), SCHED_RR (real-time round-robin policy), and SCHED_FIFO (real-time FIFO policy).
Here, param is a pointer to a structure representing scheduling priority. It can range from 1 to 99 only for real-time policies. For others (normal non-real-time processes), it is zero.
In Linux, for a known scheduling policy, it is also possible to change only the process priority by using the system call sched_setparam: int sched_setparam(pit_t pid, const struct sched_param *param);.
The LinuxThreads library call pthread_setschedparam is the thread version of sched_setscheduler and is used to dynamically change the scheduling priority and policy for a running thread: int pthread_setschedparam(pthread_t target_thread, int policy, const struct sched_param *param);.
The parameter target_thread indicates the thread whose priority is to be changed; param indicates the priority.
The LinuxThreads library calls pthread_attr_setschedpolicy, and you can use pthread_attr_setschedparam to set the scheduling policy and the priority level to the thread attribute object before the thread is created:
int pthread_attr_setschedpolicy(pthread attr_t *threadAttr, int policy);
int pthread_attr_setschedparam(pthread attr_t *threadAttr, const struct sched_param *param);
|
In Windows, the priority range is from 16 (lower priority) to 31 (higher priority) for the real-time threads. In Linux, the priority range for real-time threads is from 99 (higher) to 1 (lower priority). This has to be mapped before being used.
Examples
The following listings illustrate the concepts in this section.
Listing 3. Windows thread exampleMain Thread
enum stackSize = 120 * 1024 ;
// create a thread normal and real time thread
DWORD normalTId, realTID;
HANDLE normalTHandle, realTHandle;
normalTHandle = CreateThread(
NULL, // default security attributes
stackSize, // 120K
NormalThread, // thread function
NULL, // argument to thread function
0, // use default creation flags
&normalTId); // returns the thread identifier
// Set the priority class as "High priority"
SetPriorityClass(pHandle, HIGH_PRIORITY_CLASS);
normalTHandle = CreateThread(
NULL, // default security attributes
stackSize, // 120K
NormalThread, // thread function
NULL, // argument to thread function
0, // use default creation flags
&normalTId); // returns the thread identifier
CloseHandle(threadHandle);
...
...
// Thread function
DWORD WINAPI NormalThread ( LPVOID lpParam )
{
HANDLE tHandle,pHandle;
pHandle = GetCurrentProcess();
tHandle = GetCurrentThread();
// Set the priority class as "High priority"
SetPriorityClass(pHandle, HIGH_PRIORITY_CLASS);
// increase the priority by 2 points above the priority class
SetThreadPriority(tHandle,THREAD_PRIORITY_HIGHEST);
// perform job at high priority
...
...
...
// Reset the priority class as "Normal"
SetPriorityClass(pHandle, NORMAL_PRIORITY_CLASS);
// set the priority back to normal
SetThreadPriority(tHandle,THREAD_PRIORITY_NORMAL);
// Exit thread
ExitThread(0);
}
// Thread function
DWORD WINAPI RealTimeThread ( LPVOID lpParam )
{
HANDLE tHandle, pHandle ;
pHandle = GetCurrentProcess();
tHandle = GetCurrentThread ();
// Set the priority class as "Real time"
SetPriorityClass(pHandle, REALTIME_PRIORITY_CLASS);
// increase the priority by 2 points above the priority class
SetThreadPriority(tHandle,THREAD_PRIORITY_HIGHEST);
// do time critical work
...
...
...
// Reset the priority class as "Normal"
SetPriorityClass(pHandle, NORMAL_PRIORITY_CLASS);
// Reset the priority back to normal
SetThreadPriority(tHandle,THREAD_PRIORITY_NORMAL);
ExitThread(0);
}
|
Listing 4. Equivalent thread code in Linux
static void * RegularThread (void *);
static void * CriticalThread (void *);
// Main Thread
pthread_t thread1, thread2; // thread identifiers
pthread_attr_t threadAttr;
struct sched_param param; // scheduling priority
// initialize the thread attribute
pthread_attr_init(&threadAttr);
// Set the stack size of the thread
pthread_attr_setstacksize(&threadAttr, 120*1024);
// Set thread to detached state. No need for pthread_join
pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
// Create the threads
pthread_create(&thread1, &threadAttr, RegularThread, NULL);
pthread_create(&thread2, &threadAttr, CriticalThread,NULL);
// Destroy the thread attributes
pthread_attr_destroy(&threadAttr);
...
...
// Regular non-realtime Thread function
static void * RegularThread (void *d) {
int priority = -18;
// Increase the priority
setpriority(PRIO_PROCESS, 0, priority);
// perform high priority job
...
...
// set the priority back to normal
setpriority(PRIO_PROCESS, 0, 0);
pthread_exit(NULL);
}
// Time Critical Realtime Thread function
static void * CriticalThread (void *d) {
// Increase the priority
struct sched_param param; // scheduling priority
int policy = SCHED_RR; // scheduling policy
// Get the current thread id
pthread_t thread_id = pthread_self();
// To set the scheduling priority of the thread
param.sched_priority = 90;
pthread_setschedparam(thread_id, policy, ¶m);
// Perform time critical task
...
...
// set the priority back to normal
param.sched_priority = 0;
policy = 0; // for normal threads
pthread_setschedparam(thread_id, policy, ¶m);
....
....
pthread_exit(NULL);
}
|
Tutorial Pages:
»
A mapping guide for complex, multithreaded, multiprocess applications
»
Processes
»
Creating a process
»
Terminating a process
»
Using wait functions
»
Exiting a process
»
Environment variables
»
Examples
»
Threads
» Examples of processes and threads
»
Next in the series
»
Resources
First published by IBM DeveloperWorks
|
