Skip to main content

skip to main content

developerWorks  >  Linux  >

Guide to porting from Solaris to Linux on POWER

developerWorks
Document options

Document options requiring JavaScript are not displayed

Discuss


Rate this page

Help us improve this content


Level: Introductory

Chakarat Skawratananond (chakarat@us.ibm.com), Linux on POWER Technical Consultant, IBM 
Matt Davis (mattdavis@us.ibm.com), Linux on POWER Technical Consultant, IBM 

15 Feb 2005

Accelerate your porting efforts by following this six-step guide. Learn the differences between Solaris and Linux™ on POWER™ that you commonly encounter during a port. Get an introduction to the development environment for Linux running on IBM® POWER processor-based systems, and see how SUN's compiler/linker switches compare with those of GNU GCC and the IBM native compiler. Finally, learn about tools for performance analysis and software packaging for Linux on POWER.

Introduction

Generally, porting Solaris-based applications to Linux is a simple task since both Solaris and Linux are based on UNIX®. Porting often requires only a recompile with minor changes in some compiler and linker switches. Only when applications depend on system-specific implementations do they require major modifications. While both Solaris and Linux are designed to follow standards, differences in their implementations sometimes occur. This guide highlights these differences and recommends possible solutions, if an equivalent on the Linux side is not available.

This paper is organized as follows:

  • Proposed steps for migration
  • Endianness and 32- and 64-bit porting issues
  • Development environment for Linux on POWER
  • Differences between Solaris and Linux
  • Performance tuning and software packaging tools available for Linux on POWER



Back to top


About this guide

This guide focuses on migration from Solaris running on 32-bit or 64-bit SPARC, Intel, or AMD x86 architectures to Linux running on POWER architecture. On the Solaris side, we base our discussion on the version 9 and later. On the Linux side, we focus on the distributions available on IBM POWER processor-based servers: SUSE LINUX Enterprise Server 9 and Red Hat Enterprise Linux AS V3 update 4.



Back to top


Porting roadmap

The following steps provide a roadmap for successful migration:

Step 1: Prepare

Research to understand the differences between the source and target platforms. For example, you need to know if the endianness on the source platform is different from the endianness on the target platform. If your source platform is Solaris/x86, then endianness should be under your consideration since Linux on POWER is big-endian, while Solaris/x86 is little-endian.

Determine, also, if all the required third party packages (such as databases and class libraries) are available on the target platform. For 32-bit applications, consider if it is necessary to migrate to 64-bit. The next section, General Porting Notes, provides more information about endianness and 32- to 64-bit issues.

Also, decide which compiler to use on the target platform. If your application is performance sensitive, consider using the native compiler. The section Development Environment for Linux on POWER provides more information about the available compilers for Linux on POWER.

Step 2: Configure

This step involves setting up the development environment, setting environment variables, making changes to makefiles, and so on. At the end of this stage, you should be ready to start building your application.

Step 3: Build

This step involves fixing compiler errors, linker errors, and more. It is not unusual for code to go through several iterations of Steps 2 and 3 before a clean build is produced.

Step 4: Run-time test and debug

After the application is successfully built, test it for runtime errors.

Step 5: Performance tuning

Now the ported code is running on the target platform. Monitor performance to ensure the ported code performs as expected. If not, performance tuning must be completed. The Performance Tuning section of this document provides more information about the performance tuning tools available for Linux on POWER.

Step 6: Packaging

Will you have to distribute the resulting code to others? If so, what packaging method will you want to use? Linux provides several ways to package your application such as a tarball, self-installing shell script, or RPM. The section Software Packaging provides more information about software packaging for Linux.



Back to top


General porting notes

This section provides information about when to migrate applications from 32-bit to 64-bit, as well as considerations for applications crossing an endianness barrier. Applications migrating from Solaris on x86 platforms will cross an endian barrier. Developers familiar with 32-bit to 64-bit migration and byte ordering may wish to skip to the next section, Development Environment for Linux on POWER.

32-bit to 64-bit

Once you decide to port to Linux on POWER, you may also consider porting the application to 64-bit, if it is currently 32-bit. However, 32-bit applications that do not require 64-bit capabilities should remain 32-bit. Any porting effort involving a migration to 64-bit should be taken in two steps: First, migrate to the target platform as 32-bit, and only then proceed to 64-bit. Otherwise, issues arising from the platform migration can be easily confused with issues arising from the migration to 64-bits. That said, an application should be ported to 64-bit, if it can:

  • benefit from more than 4 GB of virtual address space
  • benefit from more physical memory (greater than 4 GB), and if its users are likely to deploy it on a system with more than 4GB of physical memory
  • benefit from 64-bit size integers
  • benefit from full 64-bit registers to do efficient 64-bit arithmetic
  • use files larger than 2 GB

The application can remain 32-bit and still run on the 64-bit Linux on POWER kernel without requiring any code changes. IBM Linux on POWER processor-based servers support both 32-bit and 64-bit applications running simultaneously on the 64-bit architecture without any performance degradation between modes.

When converting 32-bit applications to 64-bit applications, two basic issues are likely to arise: Data type inconsistency and interoperation between applications using different data models.

The 64-bit environment uses a different data type model than the 32-bit environment. For Linux on POWER, the ILP32 model is used in the 32-bit environment, while the LP64 is used in the 64-bit environment. The differences between these two models are the sizes of long and pointer. Therefore, when an application is converted from ILP32 to LP64, fundamental changes in data type occur. Longs and integers are no longer the same size. Pointers and integers are no longer the same size. Also, the size of objects like structs and unions is bigger in the 64-bit environment if they include pointer or long data types. Other issues commonly spawned by these differences are:

  • Data truncation
  • Pointer assignment
  • Data alignment
  • Data sharing

The topic of migrating applications from 32-bit to 64-bit environments has been covered extensively in other publications. We, therefore, will not go into detail about how to deal with these porting issues in this article. Refer to Chapter 3 of the "AIX 5L Porting Guide," an IBM Redbook, for detailed information about porting from 32-bit to 64-bit.

Byte ordering (endianness)

Since both SPARC and POWER architectures are big-endian, there will be no endianness issues when porting applications between these platforms. However, if you are porting Solaris on x86 applications to Linux on POWER, you may need to deal with endianness portability issues since x86 is a little-endian architecture.

Endianness issues are often encountered during the process of migrating applications from one type of architecture to another. Endianness is the ordering of a data element and its individual bytes as they are stored and addressed in memory. There are two types of endianness: big-endian and little-endian.

For big-endian processors, such as POWER, PowerPC™, and SPARC, when a word is placed in memory, starting from the lowest address, the most significant byte will be placed first. On the other hand, for little-endian processors, such as Intel and Alpha processors, the least significant byte will be placed first.

The following diagram shows how big-endian and little-endian processors place a hexadecimal value, like 0x89ABCDEF, in its memory:


Figure 1. Byte ordering (endianness)

One source of endianness problems is non-uniform data reference. It is often featured by data type mismatches resulting from either data element casting, use of a union data structure, or the use and manipulation of bit fields.

The following source code illustrates the endianness issue due to the non-uniform data reference using a pointer:


Listing 1. Non-uniform data reference
                
int main() {
        int value;
       char *p;
       p = (char*) &value;
      value = 0x89ABCDEF;
      printf(“%X.%X.%X.%X\n" p[0], p[1], p[2], p[3]);
return 0;
}



Back to top


Development environment for Linux on POWER

This section describes the elements of a Linux on POWER development environment with which you should be familiar.

Linux distributions

Linux for POWER is offered in enterprise form by two leading Linux vendors: SUSE LINUX and Red Hat. While both are highly respected by the Linux community, their offerings do differ. For most vendors, however, there is no problem deploying software from the same code base across either offering. Developers familiar with the specific levels of the development environment in SLES9, RHEL3, and Solaris 10 may wish to skip to the next section, Differences Between Solaris and Linux on POWER.

SLES9
SUSE LINUX Enterprise Server, version 9 (SLES9) is based on the Linux 2.6 kernel and supports all enterprise features of Linux on POWER hardware. The development environment provides GCC 3.3.3, glibc 2.3.3, and the GNU binutils 2.15.90. This is in contrast to GCC 3.3.2 and glibc 2.2.3 available on Solaris 10. The IBM JDK 1.4.2 is also provided with SLES9. Many other open source development libraries, such as perl, python, and gtk are also packaged with SLES9. Thus, environments for 32-and 64-bit development are available for C, C++, and Java™ technology.
RHEL3
Red Hat Enterprise Linux, version 3, update 4 is based on the Linux 2.4.21 kernel, and, thanks to extensive backporting from the Linux 2.6 kernel, RHEL3 offers 2.6 kernel features, such as simultaneous multi-threading (SMT) and Native POSIX Thread Library (NPTL). The RHEL3 development environment, as with SLES9, provides tools for both 32- and 64-bit development of C, C++, and Java technology, as well as common open source libraries. This is accomplished with GCC 3.2.3, glibc 2.3.2, the GNU binutils 2.14.90, and the IBM JDK 1.4.2.

Compilers

Linux on POWER, like Solaris, offers a high performance compiler set in addition to the GNU Compiler Collection -- the IBM XL C/C++ compiler set. Details about its licensing are available at the XL C/C++ Advanced Edition for Linux Web site. (See Resources.)

Here is a brief overview of each compiler set and their advantages:

GCC
For projects developed across multiple platforms where a GCC compiler is the original compiler, the GCC compiler is often used to deploy applications for Linux on POWER. This is especially true for applications where performance is not critical; small utilities, for example. GCC also allows some code prototypes that are only understood by GCC, such as GCC specific macros. However, many of these “GCC-isms" are incorporated in the IBM XL C/C++ compilers.

XL C/C++
XL C/C++ V7.0 is the follow-on release to VisualAge V6.0 for Linux. XL C/C++ compilers offer a high performance alternative to GCC, as well as a number of additional features. Fortunately, the XL C/C++ compilers produce 32- and 64-bit GNU elf objects, which are fully compatible with the objects GCC compilers produce because the XL C/C++ compilers employ the same GNU libraries, linker, assembler, and binutils as GCC. In fact, functionality formerly exclusively offered by GCC compilers has been ported to XL C/C++ to facilitate source compatibility; some GCC macros and inline functions, for example. But aside from compatibility, XL C/C++ offers unparalleled performance.

Sophisticated XL C/C++ optimization routines have been developed for and tailored to the POWER architecture, and it shows. High performance computing applications, especially those heavily reliant on floating point operations, often benefit significantly from a simple recompile with XL C/C++.

In addition to algorithmic optimization routines, XL C/C++ provides some architecture specific support not yet available in GCC -- specifically, support for VMX vector instructions featured in the IBM eServer® BladeCenter™ JS20 product. These instructions are supported by GCC 3.3 (SLES9, but not RHEL3 version of GCC), but only XL C/C++ version 7 offers automatic vectorization of unvectorized code and optimizes it for POWER VMX instructions.

While XL C/C++ for Linux on POWER is not free, it is available to developers at a reduced rate and as a free trial. Details are available at the XL C/C++ Advanced Edition for Linux Web site. (See Resources.)

Binutils
On Solaris 10, you have the option of using the native build utilities or the utilities provided with GNU . With Linux on POWER, the GNU binutils are used to generate objects with both the XL C/C++ compiler set and GCC. They are reviewed in significant detail at the GNU Binutils site. (See Resources.) In addition to the standard binutils, developers should be aware of modified versions of elflint, nm, readelf, size, and strip; these are the elfutils tools packaged on RHEL3. These tools have been rewritten for Linux-specific functionality, but the regular GNU binutils versions of these programs are still available as well.

Java technology

Java technology allows developers to deploy across multiple platforms without recompiling code, provided that the Java Runtime Environment is compatible with the Java Developer Kit (JDK) for the platform on which the software was developed. Linux on POWER Java development is supported on both RHEL3 and SLES9 by the IBM Developer Kit for Linux, Java Technology Edition version 1.4.2. (See Resources.) This developer kit is available in both 32- and 64-bit versions at no cost from IBM . The IBM developer kit is also packaged with both RHEL3 and SLES9 media, and updates are supported by the distributions maintenance packages.

64-bit Java and NPTL
Threaded 32- and 64-bit development on RHEL3 can be done with NPTL or the older Linux Threads libraries. However, only the NPTL 64-bit threading libraries are supported for Java. LinuxThreads is not supported with the 64-bit version of the IBM JDK 1.4.2 for Linux on POWER.


Back to top


Differences between Solaris and Linux on POWER

In this section, learn about the differences between Solaris and Linux on POWER, including system calls, signals, data types, makefiles, compiler and linker options, and threading libraries.

System calls and library functions

System calls are interfaces used by user programs to have the kernel perform a specific function on behalf of the calling thread or process. To execute a system call, a context switch to the privileged kernel mode is required. Library functions are normal C functions. They do not have any context switching overhead since they are part of the address space for each process that uses them. Some Solaris system calls and library functions may not be available on Linux. When this happens, a wrapper-call may have to be implemented on the Linux side.

Linux on POWER currently provides 256 different system calls. A list of system calls can be found in /usr/include/asm-ppc/unistd.h or /usr/include/asm-ppc64/unistd.h.

Here are a few examples of incompatibilities between Solaris and Linux:

  • regexp() and regcmp(): The routines regexp() and regcmp() on Solaris need to be replaced by regexp() and regcmp() on Linux.
  • Dirent structure on Solaris is different from that on Linux:


    Listing 2. Dirent structure on Linux
                                
    struct dirent
           {
    #ifndef __USE_FILE_OFFSET64
           __ino_t d_ino;
           __off_t d_off;
    #else
          __ino64_t d_ino;
          __off64_t d_off;
    #endif
           unsigned short int d_reclen;
           unsigned char d_type;
           char d_name[256];
    };
    



    Listing 3. Dirent structure on Solaris
                                
    
    typedef struct dirent {
             ino_t d_ino; /* "inode number" of entry */
             off_t d_off; /* offset of disk directory entry */
             unsigned short d_reclen; /* length of this record */
             char d_name[1]; /* name of file */
    } dirent_t;
    


  • File system interface routines: Solaris file system routines employ vfstab structures and contain vfs in the function name, such as getvfsent. Linux provides equivalent interfaces, but the routines use fstab structures and contain fs in the routine name, such as getfsent. The vfstab structure on Solaris is defined in /usr/include/sys/vfstab.h. The definition of fstab on Linux is in /usr/include/fstab.h.
  • Device Information Library Functions (libdevinfo): The libdevinfo library contains a set of interfaces for accessing device configuration data, such as major and minor numbers. The standard Linux installation does not support this.
  • CPU Affinity: By default, a process in a multiprocessor system bounces among several CPUs. By explicitly binding a process to certain CPUs (assigning CPU affinity) may yield performance gain in some cases. System calls for CPU affinity on Solaris are different from those on Linux. The Linux 2.6 kernel provides sched_setaffinity() and sched_getaffinity() for CPU affinity. Please consult the Linux man pages for more information.

The following table lists the Solaris system calls that either use a different name, signature, or are not available on Linux:

Table 1. Solaris system calls

Solaris Linux Notes
acl, facl N/Aget or set a files’s Access Control List (ACL)
adjtime N/Acorrect the time to allow synchronization of the system clock
audit N/Awrite a record to the audit log
auditon N/Amanipulate auditing
auditsvc N/A write audit log to specified file descriptor
getacct, putacct, wracct N/Aget, put, or write extended accounting data
getaudit, setaudit, getaudit_addr, setaudit_addr N/A get and set process audit information
getauid, setauid N/Aget and set user audit identity
getdents getdents**read directory entries and put in a file system independent format. Dirent structure on Linux and Solaris are different.
getmsg, getpmsg N/Aget next message off a stream
getpflags, setpflags N/Aget or set process flags
getppriv, setppriv N/Aget or set a privilege set
getustack, setustack N/Aretrieve or change the address of per-LWP stack boundary information
issetugid N/Adetermine if current executable is running setuid or setgid
llseek _llseek move extended read/write file pointer
_lwp_cond_signal, _lwp_cond_broadcastN/A signal a condition variable
_lwp_cond_wait, _lwp_cond_timedwait, _lwp_cond_reltimedwaidN/A wait on a condition variable
_lwp_info N/A return the time-accounting information of a single LWP
_lwp_kill N/Asend a signal to a LWP
_lwp_mutex_lock, _lwp_mutex_unlock, _lwp_mutex_trylockN/A mutual exclusion
_lwp_self N/A get LWP identifier
_lwp_sema_wait, _lwp_sema_trywait, _lwp_sema_init, _lwp_sema_postN/A semaphore operations
_lwp_suspend, _lwp_continueN/A continue or suspend LWP execution
memcntl N/A memory management control
meminfoN/A provide information about memory
mountmount* mount a file system. The signatures of this system call on Solaris and Linux are different.
msgids N/A discover all message queue identifiers
msgrcv msgrcv* message receive operation. Linux uses struct msgbuf type in one of its argument.
msgsnapN/A message queue snapshot operation
msgsnd msgsnd*message send operation. Linux uses struct msgbuf type in one of its argument.
ntp_adjtime N/A adjust local clock parameters
ntp_gettime N/A get local clock values
open, openat open* open a file. openat() is not available in Linux.
pcsample N/A program execution time profile
p_online N/A return or change processor operational status
priocntl N/A process scheduler control
priocntlset N/A generalized process scheduler control
processor_bind sched_setaffinity bind LWPs to a processor
processor_info N/A determine type and status of a processor
pset_bind N/A bind LWPs to a set of processors
pset_create, pset_destroy, pset_assignN/A manage sets of processors
pset_info N/A get information about a processor set
pset_list N/A get list of processor sets
pset_setattr, pset_getattr N/A set or get processor set attributes
putmsg, putpmsg N/A send a message on a stream
rename, renameat rename* change the name of a file. Linux does not have renameat().
resolvepath N/A resolve all symbolic links of a path name
semids N/A discover all semaphore identifiers
setrctl, getrctl N/A set or get resource control values
settaskid, gettaskid, getprojid N/A set or get task or project IDs
shmids N/A discover all shared memory identifiers
sigsend, sigsendset N/A send a signal to a process or a group of processes
__sparc_utrap_install N/A install a SPARC V9 user trap handler
fstatat N/A get file status
swapctl N/A manage swap space
uadmin N/A administrative control
unlink, unlinkat unlink* remove directory entry. Linux does not have unlinkat().
futimesat N/A set file access and modification times. It resolves the path relative to the fildes argument.
waitid N/A wait for child process to change state
yield sched_yield yield execution to another lightweight process

Signals

Signals are used to notify a process or thread of a particular event. Linux supports both POSIX standard signals and POSIX real-time signals. Every signal has a unique name and a corresponding signal number. Several signal numbers are architecture dependent. For example, the signal number of SIGSTOP for Solaris is 23, but it is 19 for Linux on POWER. The definition of signal numbers on Linux can be found at /usr/include/bits/signum.

For all possible signals, the system defines a default action to take when a signal occurs:

Terminate:
Default action is to terminate the process.
Ignore:
Default action is to ignore the signal.
Core:
Default action is to terminate the process and dump core.
Stop:
Default action is to stop the process.

For a full list of Linux signals, including a short description of each and the default behavior when the signal is delivered, consult the signal man page in Section 7 by invoking the following command:

# man 7 signal

Note that for Linux:

  • SIGABRT and SIGIOT are identical
  • SIGCLD and SIGCHLD are identical
  • SIGPOLL and SIGIO are identical
  • Default action for SIGPWR for Linux is to terminate the process, but ignore on Solaris.

The following signals are supported by Solaris, but not by Linux on POWER:

Table 2. Signals supported by Solaris

Name Default action Description
SIGEMT core Emulation trap
SIGWAITING ignoreConcurrency signal used by threads library
SIGLWP ignore Inter-LWP signal used by threads library
SIGFREEZEignoreCheckpoint suspend
SIGTHAWignoreCheckpoint resume
SIGCANCELignoreCancellation signal used by threads library
SIGLOSTignoreResource lost (but supported in Linux running on Sparc)
SIGXRES ignoreResource control exceeded

sigset_t is defined differently on Solaris and Linux.

On Linux, it is defined in /usr/include/bits/sigset.h as:

# define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long
int)))
typedef struct
   {
       unsigned long int __val[_SIGSET_NWORDS];
   } __sigset_t;
#endif


On Solaris, it is defined in /usr/include/sys/signal.h as:

typedef struct  {                                     /* signal set type */
             unsigned int       __sigbits[4];
} sigset_t;

Base data type and alignment

There are two different classes of data types available on a system: base data types and derived data types.

Base data types are all data types defined by the C and C++ language specification. The following table compares base data types for Linux on POWER and Solaris:

Table 3. Base data types

  Linux on POWER Solaris
Base type ILP32 LP64 ILP32LP64
char8888
short16161616
init32323232
float32323232
long32643264
pointer32643264
long long64646464
double64646464
long double64/128*64/128*128128

*The default size for long double in Linux on POWER is 64 bits. They can be increased to 128 bits if the compiler option –qlongdouble in XL C/C++ compiler is used.

When porting applications between platforms or between 32-bit and 64-bit modes, you need to take into account the differences between alignment settings available in the different environments to avoid possible degradation in performance and data corruption. For IBM XL C/C++ compiler, each data type within aggregates (C/C++ structures/unions and C++ classes) will be aligned along byte boundaries according to the either linuxppc or bit-packed rules, where linuxppc is the default. linuxppc is compatible with the default GCC alignment rules.

The following table shows the alignment values in byte for linuxppc and bit-packed:

Table 4. Alignment values

Data type linuxppc bit-packed
bool11
char11
wchar_t (32-bit)21
wchar_t (64-bit)41
intl41
short21
long (32-bit)41
long (64-bit)81
long long81
float41
double81
long double81

System derived data types

A derived data type is a derivative or structure of existing base types or other derived types. System derived data types can have different byte sizes depending on the employed data model (32-bit or 64-bit) and the hardware platforms. The following table shows some of the derived data types on Linux that are different from those on Solaris:

Table 5. Derived data types

OS gid_t mode_t pid_t uid_t wint_t
Solaris ILP32 llongunsigned longlonglonglong
Solaris LP64intunsigned intintintint
Linux ILP32 unsigned intunsigned intintunsigned intunsigned int
Linux ILP64 unsigned intunsigned intintunsigned intunsigned int

GNU Make versus Solaris Make

If you use Solaris Make in the source platform, you need to modify your makefile in order to use GNU Make on Linux.

To obtain detailed information about the difference between Solaris Make and GNU Make, please consult Chapter 6 of the "AIX 5L Porting Guide."

Compiler and linker options

As mentioned earlier, there are two compilers available for Linux on POWER: GNU GCC and IBM XL C/C++ V7.0. Here is a list of widely used compiler options for SUN Studio C/C++ compiler and the equivalent options for the GNU GCC and IBM’s XL C/C++ compilers:

Table 6. Compiler options

SUN Studio option GNU GCC option XL C/C++ option Description
-# -v-vInstructs the compiler to report information on the progress of the compilation.
-###-###-#Traces the compilation without invoking anything.
-Bstatic -static-qstaticlinkCauses the link editor to look only for files named libx.a.
-Bdynamic(Default)(Default)Instructs the link editor to look for files name libx.so and then libx.a when given the –lx option.
-G -shared -qmkshrobj Produce a shared object rather than a dynamically linked executable.
-xmemalign -malign-natural,
-malign-power
-qalign Specifies the maximum assumed memory alignment and the behavior of misaligned data accesses.
-xO1, -xO2, -xO3, -xO4,-xO5-O, -O2, -O3 -O,-O2,-O3,-O4,-O5 Optimizes code at a choice of levels during compilation.
-KPIC-fPIC-qpic=largeGenerates position-independent code for use in shared libraries (large model).
-Kpic-fpic-qpic=smallGenerates position-independent code for use in shared libraries (small model).
-mt-pthread Use _r invocation modeCompile and link for multithreaded code.
-R dirlist-Wl, -rpath, dirlist-Wl, -rpath, dirlistBuilds dynamic library search path into the executable file.
-xarch-mcpu, -march-qarch, -qtuneSpecifies the target architecture instruction set.

Solaris thread and NPTL

This section addresses issues that developers face when migrating multithreaded applications from Solaris to Linux.

Solaris supports two threading implementations: Solaris threads and POSIX threads (pthreads). There are a few functions implemented by the Solaris threads API that are not implemented by the pthreads API, and vice versa. For those functions that do match, the associated arguments might not. The following features are exclusively supported by the Solaris threads API:

  • The ability to create daemon threads. Daemon threads do not affect the process exit status. A process can exit either by calling exit(), or by having every non-daemon thread in the process call thr_exit().
  • The ability to suspend or continue the execution of the thread using thr_suspend() and thr_continue(). Note that thr_suspend() suspends the target thread with no regard to the locks that the thread might be holding. If the suspending thread calls a function that requires a lock held by the suspended target thread, deadlock occurs.
  • The ability to allow a thread to wait for any undetached thread in the process to terminate. This is achieved when the first argument of thr_join() is set to 0. If you set the first argument of pthread_join() to 0, the program will be terminated with a segmentation fault.

The following table compares the key Solaris threads functions with the pthreads functions. For other Solaris threads functions, please consult the "Multithreaded Porting Guide" from SUN. (See Resources.)

Table 7. Threads and pthreads functions

Solaris threads API Linux POSIX threads API Description
thr_create()pthread_create()Creates a new thread of control.
thr_exit()pthread_exit()Terminates the execution of the calling thread.
thr_join()pthread_join()Suspends the calling thread until the target thread completes.
thr_kill()pthread_kill()Sends a signal to another thread.
thr_self()pthread_self()Returns the thread ID of the calling process.
thr_yield()sched_yield()Makes the current thread yield to another thread.
thr_getprio()pthread_getschedparam()Retrieves a thread's priority parameters.
thr_setprio()pthread_setschedparam()Modifies a thread's priority parameters.
thr_getspecific() pthread_getspecific() Binds a new thread-specific value to the key.
thr_setspecific()pthread_setspecific() Binds a new thread-specific value to the key.
thr_getconcurrency()pthread_getconcurrency() Gets thread concurrency level.
thr_setconcurrency() pthread_setconcurrency()Sets thread concurrency level.
thr_sigsetmask()pthread_sigmask()Changes or examines the calling thread's signal mask.
thr_keycreate()pthread_key_create()Creates a key that locates data specific to a thread.
N/A pthread_key_delete()Deletes a key that locates data specific to a thread
thr_suspend()N/A Suspends the execution of the specified thread.
thr_continue()N/A Resumes the execution of a suspended thread.
fork1()fork()Regular fork
forkall()N/AReplicate all fork

The behavior of fork() in Solaris 9 and earlier releases is different from the behavior of fork() in POSIX threads. In POSIX threads, fork() creates a new process, duplicating the complete address space in the child. However, it duplicates only the calling thread in the child process. Solaris threads API also provides the replicate all fork semantics, forkall(). This function duplicates the address space and all the threads in the child. This feature is not supported by POSIX thread standard.

There are some POSIX thread routines implemented in Solaris, but not in Linux, and vice versa. The following table lists those routines:

Table 8. POSIX thread routines

Routine Solaris Linux
pthread_cond_reltimedwait_npyn
pthread_mutexattr_getprioceilingyn
pthread_mutexattr_getprotocolyn
pthread_mutexattr_getrobust_npyn
pthread_mutexattr_setprioceilingyn
pthread_mutexattr_setprotocolyn
pthread_mutexattr_setrobust_npyn
pthread_mutex_consistent_npyn
pthread_mutex_getprioceilingyn
pthread_mutex_reltimedlock_npyn
pthread_mutex_setprioceilingyn
pthread_rwlock_reltimedrdlock_npyn
pthread_rwlock_reltimedwrlock_npyn
pthread_setschedprioyn
pthread_attr_getaffinity_npny
pthread_attr_setaffinity_npny
pthread_cleanup_pop_restore_npny
pthread_cleanup_push_defer_npny
pthread_getattr_npny
pthread_kill_other_threads_npny
pthread_rwlockattr_getkind_npny
pthread_rwlockattr_setkind_npny
pthread_timedjoin_npny
pthread_tryjoin_npny

The Linux threading library in all the released versions of Linux prior to 2.6 is known as LinuxThreads. This library has been supported by GNU C library since glibc 2.0 and is largely POSIX-compliant. Starting in the 2.6 kernel, a new and improved threading library known as the Native POSIX Threading Library (NPTL) is introduced. This implementation provides a significant performance improvement over LinuxThreads. NPTL is also far more compliant with the POSIX specification than the LinuxThreads package was. However, simply using the 2.6 kernel does not mean that the NPTL is being used. Issue the following command to see which POSIX implementation you are using:

$ getconf GNU_LIBPTHREAD_VERSION

NPTL implements the one-on-one threading model where there is a one-to-one relationship between user threads and kernel threads. NPTL also implements the inter-process POSIX synchronization primitives. Specifically, the thread option

PTHREAD_PROCESS_SHARED is now supported. By default, each thread is created with the detachstate attribute set to PTHREAD_CREATE_JOINABLE, scheduling policy set to SCHED_OTHER, and no user-provided stack.

If your Solaris application uses POSIX threads API, then porting them to Linux will be straightforward. Note that even when using GCC, Solaris does not support NPTL. The following table shows the default values of attributes for POSIX threads on Linux:

Table 9. Default values of POSIX threads attributes on Linux

Attribute Default Values
scope PTHREAD_SCOPE_SYSTEM
detachstate PTHREAD_CREATE_JOINABLE
schedparam 0
inhiritsched PTHREAD_EXPLICIT_SCHED
schedpolicy SCHED_OTHER

Though many applications will migrate from the 2.4 kernel to the 2.6 without recompilation, the addition of NPTL may require minor modifications in multithreaded applications. Instructions for migrating applications by using LinuxThreads to NPTL is beyond the scope of this article. Additional information can be found in the LinuxDevices.com article "Migrating to Linux kernel 2.6." (See Resources.)



Back to top


Performance tuning

Once the code has been ported and successfully executed on Linux, complete performance monitoring and tuning to ensure that the ported code performs well on the target platform. This section provides you with a list of tools available for Linux on POWER to help accomplish that.

Performance Inspector

This suite of tools can be used to identify performance problems in your application (C/C++/Java) and shows how your application interacts with the Linux kernel. It consists of seven tools:

  • TProf is a timer profiler that identifies what code is running on the CPU during a user-specified time interval. It is used to report hot-spots in applications as well as the kernel. Basically, it records which code is running at each system-clock interrupt (100 times per second per CPU).
  • PTT collects per-thread statistics, such as number of CPU cycles, number of interrupts, and number of times that the thread was dispatched.
  • AI displays CPU utilization statistics during a user-specified interval.
  • JLM provides statistics on locks based in the Java 2 technology.
  • JProf is a shared library that interfaces with Java jvmpi interface.
  • POST generates reports based on outputs from other tools.
  • A2N is used by POST to map code execution to the application that was being traced.

At the time of this writing, Performance Inspector supports SUSE LINUX Enterprise Server 9 (2.6.5-7.97) and Red Hat Enterprise Linux V3.0 Update 2.

The article "Five easy-to-use performance tools for Linux on PowerPC" (developerWorks, June 2004) provides information about installing and utilizing Performance Inspector.

To download Performance Inspector and get more information, please visit the Performance Inspector home page. (See Resources.)

Post-Link optimization

This tool optimizes the executable image of a program by collecting information on the behavior of the program while the program is used for some typical workload. It then re-analyzes the program (together with the collected profile), applies global optimizations (including program restructuring), and creates a new version of the program that is optimized for that workload. The new program generated by the optimizer typically runs faster and uses less real memory than the original program.

At the time of this writing, Post-Link Optimization tool is supported on the following Linux distributions: SUSE LINUX Enterprise Server 8 and above, Red Hat Enterprise Linux 3.

To download and get more information, please visit the alphaWorks Post-Link Optimization for Linux on POWER site. (See Resources.)

Oprofile

Oprofile provides profiles of code based on hardware-related events such as cache misses or CPU cycles. For example, Oprofile can help you determine which of the source routines causes the most cache misses. Oprofile utilizes hardware performance counters provided in many CPUs including IBM POWER4™, POWER5™ and PowerPC™ 970. Please visit the Oprofile Web site for more information. (See Resources.)

Oprofile for Linux on POWER is also available in the SUSE LINUX SDK 9. (See Resources.)

Quick reference of Oprofile on an installed system can be found at /usr/share/doc/packages/oprofile.



Back to top


Software packaging

Application software is delivered to end users in a unit called a package. A package is a collection of related files (binaries, libraries, documentation, and source code) and metadata. Metadata is used by the package management system to coordinate all of the pieces in the package. Solaris uses pkgadmin as its package manager. RPM is the package management system widely used on Linux. For further information about RPM, please visit www.rpm.org. (See Resources.)

Note that the format of the package specification template files used by pkgadmin in Solaris is different from the spec file used by RPM, and translating packaging information from template file into spec files requires a substantial effort.



Back to top


Summary

The porting effort from Solaris to Linux on POWER in most cases involves just a recompile or minor changes in compiler/linker switches. However, the design of Solaris and Linux is fundamentally different. Solaris is focused on performance, scalability, and reliability, while sacrificing portability. On the other hand, Linux is designed with portability in mind, and it is supported on almost all hardware platforms available today. The Linux 2.6 kernel, however, has significantly improved performance, scalability and reliability from the 2.4 kernel. As a result, there are some system-specific features available on Solaris that are not available on Linux.



Resources



About the authors

Chakarat Skawratananond is currently a technical consultant in the IBM eServer Solutions Enablement organization, where he assists ISVs in enabling their applications for Linux on POWER architecture. He has published a number of articles for IBM developerWorks in the area of Linux migration. He can be contacted at chakarat@us.ibm.com.


Matt Davis is a Linux on POWER consultant in Austin, Texas. He came to IBM in May, 2000 while still studying at the University of Texas at Austin, from which he earned two degrees with academic honors. He has been engaged with the Linux on POWER development community for nearly 5 years, and is the author of roughly two dozen papers and articles regarding Linux on Intel and POWER architectures. In addition to involvement in the Open Source Community, Matt spends his spare time researching life sciences at the University of Texas.




Rate this page


Please take a moment to complete this form to help us better serve you.



YesNoDon't know
 


 


12345
Not
useful
Extremely
useful
 


Back to top


This is a trademark statement. This is another trademark statement. Other company, product, or service names may be trademarks or service marks of others.