Porting from IRIX to Linux

Coding for portability to Linux: examples from the ACRT land vehicle port.
Software and Hardware Used

This section reflects what we did in March of 2000. See the Afterward section for more current information.

A) Red Hat 6.1

The KDE Workstation installation option provides most of the packages you need.

B) Metrolink Motif

We experimented with Lesstif. While it works well for Performer and lets us compile our other tools, it didn't handle updating some of our scrolling windows correctly. The developer's console (a tool for tracking messages) has a scrolling window that should update with message traffic even without mouse interaction. The Lesstif version didn't, but the Motif version did.

C) Mesa Graphics Library

We used the Mesa Graphics Library as an OpenGL look alike. Make sure that you follow their directions for making the widget set after you install Mesa.

D) Viper V770 Graphics Card.

We used the Diamond Viper V770 graphics card and the hardware accelerated Mesa drivers and libraries. At that time (January 2000) the GeForce 256 card was supported under Linux, but there were no hardware accelerated OpenGL drivers for it. More recently, XFree86 version 4.0 is out and while hardware-accelerated OpenGL is available for the GeForce card, setting it up can be tricky.

E) XFree86 Drivers for Hardware Acceleration

We used the XFree86 SVGA server and the XFree86-rivaGL-3.3.3.1-49riva drivers in January. OpenGL Linux drivers for the GeForce card are available from nVidia (see Resources).

F) SGI's Performer Package

Downloaded and installed per their instructions (see Resources web pages).

G) ACRT Version 1.06 (our simulator)

See Specifies for details about architecture and operation.

Tool “Equivalents”

SGIs generally offer a cushier environment than Linux. They're also working on porting more of IRIX's tools and features to Linux. For those accustomed to the SGI environment and new to Linux, here are some of the corresponding tools that we used when porting:

A) Xdiff -> Mgdiff

Do a Web search for this one. My recollection is that it requires Motif, and Lesstif won't work.

B) dbx -> gdb

Your basic command-line debugger.

C) cvd -> xxgdb

SGI Casevision debugger has a nice graphical interface to a whole suite of tools. While there is no Linux equivalent for Casevision, the xxgdb front end for dbx provides a similar debugging environment. There is also a tool called “DDD” (the data display debugger) available that we didn't use because we're already familiar with xxgdb.

D) gr_osview -> xosview

SGI's system monitoring and status tool, gr_osview, encompasses more than xosview, but xosview is similar in the ability to see processor and memory status, system load, etc.

E) editors, shells, etc.

Emacs, vi, edit, tcsh, bash and the like are all pretty much what you'd expect (I imagine there are some differences in the dark corners of the shells, but our system didn't use enough of them to run into the differences).

F) xwsh -> xterm

I can only say “equivalent” here with the proviso that the xwsh “-hold” option (which causes the window to persist even after the command running in it with “-e” has ended) is not available for xterm.

G) PCNFS -> SAMBA

The original system shared files over NFS (requiring an add-on package for NT). In this work we shared files between Linux and IRIX over NFS and used SAMBA to share with the NT systems.

H) Lint

The lint debugging tool is bundled as part of IRIX but is not bundled with Linux, though commercial versions of lint are available for Linux. There is also a package called LCLint that seemed like overkill for our work (porting legacy code). For our purposes, we used gcc and its options for better debugging and error detection:

gcc -ansi -Wall -Wstrict-prototypes
        -Wmissing-prototypes \
        -fsyntax_only -pedantic -O2

Larch C Lint is available for Linux and does have better debugging than this, if you want to go the extra mile (see Resources).

I) ICS' Builder Xcessory (BX PRO)

The C-code generated by the IRIX version 4 (and probably newer versions) of ICS's BX GUI builder compiles on Linux. Code generated by older versions needs to be tweaked. There is also a Linux version of BX available (see Resources).

J) Virtual Prototypes' VAPS

VAPS is a control panel building tool. There is no Linux version yet but VAPS does have an NT version. So my group ported IRIX VAPS panels to NT, but that is a separate story.

Specifics

A) Scripts and Shell Environment

It looks like Linux (or the tcsh shell) resets the processes limits when you “rsh” to another host. This kept me from getting core files. To get around this, I added a few lines to my .tcshrc file:

limit coredumpsize 1000000 kbytes <----
source ~/environment
setenv PATH ${PATH}:.

The environment file referenced here is a collection of environment variables for the simulator that is set at shell start up. [Due to the length of Listing 1 it could not be printed here, but is available for downloading at our FTP site: ftp.linuxjournal.com/pub/lj/listings/issue82.]

Using the results of uname, we can transparently point environment variables at the architecture-specific directories for binaries. Scripts, Makefiles and programs can then use those environment variables without each having to check the architecture type themselves. When we added Linux into the mix, we had to add some additional variables:

* $ARSI_SERIAL_PORT_ONE, $ARSI_SERIAL_PORT_TWO

The names of the serial port devices differ between IRIX and Linux. IRIX /dev/ttyd[N] roughly corresponds to Linux /dev/ttyS[N-1],

* $ARSI_CTDB_FILE_SUFFIX
the suffix of a binary data file that is different between big-endian (SGI MIPS) and little-endian (Intel X86) systems.

B)Makefiles

Makefiles are the part of the system that got beat up the most with this port. The IRIX Makefiles are moved from the directory with the source code to the IRIX64 subdirectory, and VPATH is added to point back up to them.

VPATH (“view path”) in a Makefile is like the -I directives that tell the compiler where to look for include files. VPATH tells make where to look for source files—in our case, up one level. Another consequence of moving the Makefiles is that you probably have to change directories before some of the regular shell commands in Makefile (cp, lint, etc.) that operate on the source files will work.

We recommend using SGI's smake for the IRIX Makefiles that need to use VPATH. We'd started using GNU Make hoping to integrate it with NT. However MS Studio uses Nmake instead, so that payoff never occurred. Smake understands VPATH and the common IRIX Makefile macros. The only anomaly we can report is one that occured with some of the clean options. If the make clean option is set up like this:

clean:
    -rm -f *.o $(TARGET) *.a *~*

and rm can't find anything to remove, smake will sometimes (incorrectly) exit with an error about “exit badly formed number”. We don't know why it does that, but adding an explicit “exit” statement fixes the problem:

clean:
    -rm -f *.o $(TARGET) *.a *~* ; exit 0
IRIX has a handy feature that lets you specify an alternate make program to run. The name of the program is put on the first line of the Makefile following a “#!” (much like the way script files name their interpreters). So making the first line of the IRIX Makefile:
#! smake
will cause the default make program to invoke smake to process the Makefile.

Dependencies are also tracked differently between IRIX Makefiles and GNU Makefiles. The IRIX Makefiles generate a single Make.depend file that lists all the dependencies for all the source files. In the version of GNU make that ships with Red Hat 6.1, dependencies are kept in separate files for each source file. For instance, if you have a file ground_motion.c, there will be a corresponding dependency file ground_motion.d. These can be automatically generated with a .d.c rule. (See the GNU Make documentation for details and how you can combine the .d extentions into a Make.depend file.)

Compiler options are also different between the IRIX and GNU compilers. Here's the changes we made:

For IRIX: Use GNU: Purpose: --------- -------- --------fullwarn -Wall -Extra warnings, error checks-MDupdate -MD -Update dependencies-xansi -ansi -Support ANSI C

Using the -g option with the compiler for debugging is serious now. The IRIX debugger was still able to give you information even if the -g option wasn't specified. For GNU, you really need to include the -g. On the Linux side, -D_BSD_SOURCE may be needed if you're doing something that uses BSD functions (like strncasecmp).

The permitted ordering of compiler options is different. IRIX seems to like the libraries to be last, gcc doesn't seem to care.

One of the handiest Makefile macros, $$(@F), is only partially available under GNU make. Make allows you to use $(@F) to extract the file name of a target. IRIX make and smake allow you to use $$(@F) on the dependency line of the Makefile. GNU make allows this only in the action clause, but it does allow you to use the pattern-matching macros to get the same effect (compare the IRIX and Linux Makefiles in Listings 2 and 3, which can be seen at ftp.linuxjournal.com/pub/lj/listings/issue82).

There are some additional directories in Linux for libraries, and they include files that may need to be added to your Makefile:

  • X libs in /usr/X11R6/lib

  • X headers in /usr/X11R6/include

  • OpenGL in /usr/include/GL, /usr/X11R6/GL

Make sure that CFLAGS has -c if you have separate compile and link steps. Otherwise GNU defaults to trying to do it in one step. If you get “storage size not known” error when compiling, try removing the -ansi specifier from the command line.

You can use the same Makefiles for IRIX and Linux, use xmkmf to generate architecture-specific Makefiles in both IRIX and Linux.

Let's turn our attention from Makefiles to C source code. As a general rule, the SGI compilers are more tolerant than the GNU compilers. Expect your code to have to be closer to the standard to pass the GNU compilers.

The following are items we modified from the IRIX code when porting to Linux.

1. Bstring.h, bcopy and bzero are not POSIX. We replaced them with their POSIX counterparts:

bstring.h -> string.h
bcopy(a, b, nbytes) -> memcpy (b, a, nbytes)
bzero(a, nbytes) -> memset(a, 0, nbytes)

GNU does have these in string.h instead of bstring.h, so this is not strictly necessary (though if you don't, you'll need to conditionally include “bstring.h”). Note that IRIX keeps “select” in bstring.h, while Linux puts in unistd.h.

2. Here are some things that generate warnings. Since the GNU compiler is more vocal than the IRIX, we fixed these:

  • Main should return int.

  • Watch for uninitialized vars.

  • Parenthesize defensively.

  • Format specs in printf/scanf: args not matching var types -scanf using the wrong type can get you in trouble

  • sprintf(astring, "") -> astring[0] = 0;

  • 2D array initializers need braces to be ansi -int a[2][2] = { {1, 2}, {3, 4} };

3. There is no “recalloc” in POSIX:

  • Replace recalloc with realloc and use memset to zero out the additional memory.

4. Added NULL timezone as second argument to gettimeofday
  • gettimeofday is not POSIX, but SGI, Linux and NT all accept it and timezone as the second argument.

5. Change sginap to POSIX usleep:
  • sginap (hundredths) -> usleep (hundredths * 10000).

6. Linux “select” decrements timeval structure:
  • The documentation for some other UNIX systems say they may modify timeval in the future: with Linux, the future is now

  • Don't use the same timeval struct on successive calls to “select” without refreshing it.

7. Added __ANSI_C__ parseargs.h for Linux:
  • Parseargs was an argument parsing library last maintained by Brad Appelton in 1991. It supports multiple platforms and tries to figure out what's available on each system (sort of a primitive precursor of the GNU configure utility).

8. Code involving the font manager (fmclient.h and variables of type fmfonthandle) was commented out—I'm not sure if this was an IrisGL holdover.

9. Ulocks.h is commented out. Possibly another IrisGL hold over?

10. Code involving sproc (SGI's lightweight process model) is migrated to POSIX threads (pthreads):

  • Use -D_REENTRANT on Linux compile.

  • Add library -Lpthread to link step.

  • Use XInitThreads() if threads are used in an X application.

  • Get the patches for gdb from the LinuxThreads page.

  • Be aware that the LinuxThreads Library uses SIGUSR1 and SIGUSR2 for its own purposes. If your application uses these signals you might have to look at some other mechanism. In the worst case scenario, use the Linux clone function.

11. Serial port handling used for grips and touch screens migrates to the POSIX interface.

  • See man termios for overview.

12. IRIX has a high-speed malloc library -lmalloc.
  • No high-speed malloc lib on Linux (that I'm aware of) so lmalloc is dropped.

13. Fabs, fsqrtf, fmod are not in math.h but are in the library.
  • Fabs is POSIX, fsqrtf is not

  • We suggest simply using sqrt

  • fmodf

  • use -D_BSD_SOURCE to get at M_PI, etc.

14. fabsf -> fabs in Linux.

15. fsin -> sin in Linux.

16. fcos -> cos in Linux.

17. fceil -> ceil & do math in double.

18. Socket level differences in your header files:

  • ioctl in IRIX unistd.h, Linux has it in sys/ioctl.h.

  • SIOCGIFCONF in IRIX sys/sockio.h.

19. fcntl FNONBLK --> POSIX O_NONBLOCK for both IRIX and Linux.

20. sigsend -> kill for both IRIX and Linux

21. There is sysconf shell-command in Linux

  • Our spatial database tries to obtain RAM size to know how much memory it can afford to use.

  • In Linux, use the contents of /proc/meminfo instead.

22. Non-POSIX IRIX flock_t vs. Linux struct flock:

  • Use “struct flock” on Linux.

23. Linux mmap doesn't autogrow.
  • Autogrow is an optional part of standard (IRIX implements it, but Linux does not).

  • Fill the file with zeros to the right size before mmap-ing.

24. prctl PR_TERMCHILD becomes PR_SET_DEATHSIG.

25. POSIX signal handling is different from the BSD signal handling we were using.

  • Move to POSIX; man sigaction for details.

26. IRIX oserror Ý POSIX errno.

27. There is no sysmp command for Linux multiprocess control.

28. There are no Performer arenas in 2.3 (Mongoose)

  • All performer in one process.

  • Arena pointers will be NULL.

  • pfMalloc and company allocate off the stack.

29. xtouchmouse (a touch-screen driver that turns touch-screen data into X mouse events) works, but can do no button presses on the KDE root window, just on regular windows.

  • Unmatched button presses and releases on the root window cause the window manager to hang—tip 'o the hat to John Mellby for solving that

  • We chose not to use the built-in touch-screen driver support so that we could interoperate with the IRIX systems at that level. Once, when we integrated Future Scout with FBCB2 running on an SCO PC with no compiler, we were able to send the SCO's display to a monitor and plug that monitor's touch-screen into an IRIX system. The touch-screen inputs to xtouchmouse generated X events that were sent to the SCO system allowing us to interact with it.

30. Touch-screen calibration program that figures out the mapping from touch-screen device coordinates to X coordinates is converted from IrisGL to OpenGL.
  • If you still have IrisGL code, try SGI's toogl program to help with the conversion. You might have to convert to Motif if you want to suppress the window borders.

31. Replace Iris GL window management with the X Windows System. Here are some things that either the SGI compiler just let us get away with or are a function of different versions of Motif:
  • In order to use glwMDrawingAreaWidgetClass (instead of glwDrawingAreaWidgetClass) you need to include a library that defines __GLX_MOTIF to make sure the Motif libraries are included or just use the glwDrawingAreaWidgetClass if no Motif functionality is required. “M” indicates Motif and has the additional functionality of Motif's XmPrimitive widget class.

  • In XtPopup, you cannot use NULL for second param. Use XtGrabNone instead. This parameter specifies the way in which X events should be constrained.

  • Use the X Toolkit Intrinsics method for setting up a window instead of the X Lib method in order to create a borderless window. The borderless window needs to use resources to let the window manager know that it doesn't need to manage the border. The resources are not accessible with the X Lib method.

  • Remove IrisGL device.h.

  • Use -lMesaGLw instead of -lGLw for library in the Makefile. This library has the OpenGL draw area widgets.

  • Note that there seems to be a bug in the current (as of February 2000) alpha TNT2 drivers that keeps glColorMask from working. If you're working on this now, I'd suggest switching to the newer drivers for XFree86 version 4 and the latest drivers.

32. Finally, if you do need to compile something conditionally, there is an automatically defined symbol for #ifdef (no -D needed):
#ifdef __linux__
    Linux specific stuff
#else
    IRIX specific stuff
#endif /* __linux__ */
The bulk of the data our simulator dealt with wasn't a problem. Much of the configuration files are ASCII and need only minor tweaks (like environment variables) to be simultaneously usable on IRIX, Linux and NT. In the case of Mongoose, the loaders did the byte swapping for me, so it didn't matter if I was on a big-endian SGI or a little-endian Intel box—the same visual models worked.

There were a few cases where endianness became an issue. We use the Compact Terrain Database (CTDB) files produced by the US Army Topographic Engineering Center. The database files we used were binary. Fortunately they came in big and little-endian versions with different suffixes. We could tell the system which to use by storing that suffix in an environment variable that's evaluated at runtime. The S1000 libraries are not implemented in Linux, just because they are larger and more complex than time allowed. Our Spatial Database has a binary representation of the shapes of different vehicles, so that needed to be converted. Finally, we use the BG Systems Cereal boxes to read our crewstation controls (grips). The Cereal box reads analog voltages from the crewstation controls and transmits its data over a serial line to the host computer. Since the data was assembled byte-wise into floats a little bit of their library needed to be modified. BG Systems was very helpful in that effort.

Once we had everything compiled, there were some surprises at runtime. A runtime error from the GNU compiler helped us find a case where we were accessing memory after it had been freed. IRIX will sometimes let you access memory even after you have freed it (see the IRIX mallopt function for different settings of their memory allocator). There is a mallopt function in Linux, though the man pages don't list it. You'll have to use the GNU “info” pages for that. Another feature of the GNU C library useful for tracking memory errors is mcheck. It's also detailed in the info pages.

The second thing is that the serial port device files have different names between IRIX and Linux:

IRIX: Linux: ---- ------/dev/ttyd1 /dev/ttyS0 serial port one/dev/ttyd2 /dev/ttyS1 serial port two... ...

The grip calibration programs decide based on architecture, and look for the value of $ARSI_GRIP_CALIBRATE_PORT as an optional override.

Was a case where the we had a different results from local variables in a function. We had a string next to an array of longs. The code contained an error where the string was overflowed. On the IRIX systems, the code worked fine. On the Linux systems, it did not. On further investigation, we found that the string was terminating against bytes in the array of longs. In the bigendian systems, those bytes happened to be zeros (making the system appear to work properly), while on the little-endian systems, they were nonzero, causing the string to appear to be corrupted. (Jim King gets the credit for finding that one.)

Finally, there is an error in the Flight loader that comes with Mongoose 2.3. MultiGen-Paradigm says that will be fixed in the next release. (A tip 'o the hat to Karen Davidson for tracking that one down.)

______________________

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix