[ Bottom of Page | Previous Page | Next Page | Contents | Index | Library Home | Legal | Search ]

General Programming Concepts:
Writing and Debugging Programs

Kernel Programming

Kernel programming is thoroughly explained in AIX 5L Version 5.2 Kernel Extensions and Device Support Programming Concepts. This section only highlights the major changes required for multiprocessor systems.

Serialization is often required when accessing certain critical resources. Locking services can be used to serialize thread access in the process environment, but they will not protect against an access occurring in the interrupt environment. Previously, a kernel service disabled interrupts using the i_disable kernel service to serialize interrupt level access. However, this strategy does not work in a multiprocessor environment. Therefore, new or ported code should use the disable_lock and unlock_enable kernel services, which use simple locks in addition to interrupt control. These kernel services can also be used for uniprocessor systems, on which they simply use interrupt services without locking. See Locking Kernel Services in AIX 5L Version 5.2 Kernel Extensions and Device Support Programming Concepts for detailed information.

Device drivers by default run in a logical uniprocessor environment, in what is called funnelled mode. Most well-written drivers for uniprocessor systems will work without modification in this mode, but must be carefully examined and modified to benefit from multiprocessing. Finally, kernel services for timers now have return values because they will not always succeed in a multiprocessor environment. Therefore, new or ported code must check these return values. See Using Multiprocessor-Safe Timer Services in AIX 5L Version 5.2 Kernel Extensions and Device Support Programming Concepts for more information.

32-bit and 64-bit Addressability

In AIX, applications are either 32-bit applications or 64-bit applications.

A 32-bit application is an application that executes in an environment where addresses are 32 bits long and can represent 4 gigabytes of addressability (virtual address space).

A 64-bit application is an application that executes in an environment where addresses are 64 bits long and can represent much larger addressability (over a billion gigabytes).

When creating an application, a decision must be made whether to create a 32-bit application or a 64-bit application. 32-bit applications can be run on any RS/6000 system. 64-bit applications can only be run on 64-bit RS/6000 systems. Both 32-bit and 64-bit applications (and libraries) can be compiled and linked on both 32-bit and 64-bit systems.

Performance

If the same source code is used to create both a 32-bit and a 64-bit application, the 64-bit application will be the same size or larger than the 32-bit application and will generally run no faster (and often slower) than the 32-bit application, unless it makes use of the larger 64-bit addressability to improve its performance. Therefore, the correct choice should generally be to create a 32-bit application unless 64-bit addressability is required by the application or can be used to dramatically improve its performance. For this reason, the default mode for development tools is to create 32-bit objects and applications.

The 64-bit address space can be used to dramatically improve the performance of applications that manipulate large amounts of data. This data can either be created within the application or obtained from files. Generally the performance gain comes from the fact that the 64-bit application can contain the data in its address space (either created in data structures or mapped into memory), where the data would not fit into a 32-bit address space. The data would need to be multiple gigabytes in size or larger to show this benefit.

There are two reasons for this performance improvement. First, the system call overhead of reading and writing files can be avoided by mapping the files into memory. Second, 64-bit systems can support physical memories that are larger than the addressability of 32-bit applications, so 64-bit applications are needed to make full use of the physical memory available.

64-bit objects and archive file types

64-bit libraries and applications can only be created from 64-bit objects. A 64-bit object is an object type (64-bit XCOFF format) created by compilation or assembly in 64-bit mode. (This does not mean that the compiler or assembler executes in a 64-bit execution environment, just that the compiler or assembler has been requested to create 64-bit objects rather than 32-bit objects.) 32-bit XCOFF format was the only object type in releases of AIX before AIX 4.3.

There is no way to create an object or application using both 32-bit and 64-bit object files. A system provided library contains both 32-bit and 64-bit object files. The linker selects the appropriate objects from the library based on the type of linking that is requested (32-bit or 64-bit) and creates an object or application of that type.

There are two archive file types. The first does not recognize 64-bit object files and cannot be larger than 2 gigabytes. This was the only archive file type in releases of AIX before AIX 4.3. The second archive file type recognizes both 32-bit and 64-bit object files and will work with files larger than 2 gigabytes.

Differences between 32-bit and 64-bit execution environments

In addition to the differences in addressability, there are the following differences between the 32-bit and 64-bit execution environments (or modes):

All C fundamental types other than "long" and pointer types will be the same size in 32-bit and 64-bit compilation modes.

Tools support for 64-bit development

AIX provides support in all the standard tools for building, examining, and debugging 64-bit applications.

yacc, lex, and lint work with source code destined for both 32-bit and 64-bit compilation.

The C and Fortran compilers and the assembler allow the creation of both 32-bit and 64-bit objects. The linker allows the creation of both 32-bit and 64-bit objects and applications.

make, ar, strip, dump, nm, prof, gprof, lorder, ranlib, size, strings, and sum work with both 32-bit and 64-bit objects and applications.

dbx and xldb allow the debugging of both 32-bit and 64-bit applications.

Porting source code from 32-bit to 64-bit execution environments

The following issues must be examined and dealt with when porting source code for 32-bit applications to be compiled in 64-bit mode to create 64-bit applications:

The -t flag to lint can be used to find issues when porting source code from 32-bit to 64-bit compilation mode.

64-bit application development

The APIs (Application Programming Interfaces) provided to 32-bit applications are also generally provided to 64-bit applications. Some libraries that have been superseded or deprecated for 32-bit applications are not being provided to 64-bit applications, so their APIs will be missing in 64-bit execution mode.

The names of types, global variables, preprocessor macros, and predefined constants are the same in 32-bit and 64-bit compilation mode. The sizes (and layouts in the case of structures) and values for these are often different in 32-bit and 64-bit compilation mode, to account for the different sizes of the address spaces and fundamental types involved.

The names of API functions, the types of parameters passed, and the return types are the same in 32-bit and 64-bit compilation modes. The sizes (and layouts in the case of structures) of the parameters and return values are often different in 32-bit and 64-bit compilation modes to account for the different size of the address spaces involved.

64-bit library development

Libraries should provide the same functionality to 64-bit applications that they provide to 32-bit applications. This is to minimize the amount of porting that needs to be done when changing the execution mode of an application from 32-bit to 64-bit. To ease porting, the names of functions provided, their parameter types and return types should be the same for 32-bit and 64-bit applications.

The choice of the types of integral parameters and return values should be made based upon what a parameter or return value is representing. If it represents the size of an object in the address space, its type should be based upon a C "long" type. Otherwise, the type should be made one of the C types "char", "short", "int", or "long long", depending on what the maximum possible value is. (These types are the same size in 32-bit and 64-bit compilation mode.)

Libraries should contain both the 32-bit and 64-bit objects files for the API they support. This will minimize the porting effort for makefiles for applications that are being ported from 32-bit to 64-bit execution mode. System libraries provide object files for using both 32-bit and 64-bit applications in the same library archive file.

Only 32-bit objects can be loaded by a 32-bit application. Only 64-bit objects can be loaded by 64-bit applications. If an API is provided by loading objects, a separate 32-bit and 64-bit version of the object must be provided with a different pathname.

64-bit kernel extension development

AIX kernel extensions run in 32-bit mode on the 32-bit kernel and in 64-bit mode on the 64-bit kernel, regardless of the mode of the application for which they might be processing requests.

Kernel extensions that have not been designed to work with 64-bit applications only support 32-bit applications. A 64-bit application will fail to link attempts to make use of a system call from a kernel extention that has not been modified to support 64-bit applications. A kernel extension can indicate that it supports 64-bit applications by setting the SYS_64BIT flag when it is loaded using the sysconfig routine.

Kernel extension support for 64-bit applications has two aspects.

The first aspect is the use of new kernel services for working with the 64-bit user address space. The new 64-bit services for examining and manipulating the 64-bit address space are as_att64, as_det64, as_geth64, as_puth64, as_seth64, and as_getsrval64.

The new services for copying data to or from 64-bit address spaces are copyin64, copyout64, copyinstr64, fubyte64, fuword64, subyte64, and suword64.

The new service for doing cross-memory attaches to memory in a 64-bit address space is xmattach64.

The new services for creating real memory mappings are rmmap_create64 and rmmap_remove64.

The major difference between all these services and their 32-bit counterparts is that they use 64-bit user addresses rather than 32-bit user addresses.

The service for determining whether a process (and its address space) is 32-bit or 64-bit is IS64U.

[ Top of Page | Previous Page | Next Page | Contents | Index | Library Home | Legal | Search ]