Helping ordinary people create extraordinary websites!
GET OUR NEWSLETTER
Your Email:
 

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 example
Main 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, &param);

// Perform time critical task
...
...

// set the priority back to normal

param.sched_priority = 0;
policy = 0; // for normal threads
pthread_setschedparam(thread_id, policy, &param);
....
....

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


 | Bookmark
Related Tutorials:
» How to Install PHP 5 on Linux
» How to Install Apache 2 on Linux
» How to Install MySQL 5.0 on Linux
» SMB Caching
» Mound --Bind
» Tar Wild Card Interpretation

Advertise with Us!


Tutorials Scripts Web Hosting Developer Manuals
Resources