Porting Central
Skip to main content

Porting Central

Miscellaneous questions

What is the analogy for UNIX shared library on iSeries?

Service programs are almost analagous to the UNIX shared library. Just like shared library which is a collection of .o files, service program is group of modules.

Is gettimeofday() API available on iSeries?

Yes. The gettimeofday() API is available on iSeries and iSeries.

Is data alignment on iSeries different than that on UNIX? If, yes, what are the implication or issues while porting UNIX app to iSeries?

Yes, the data alignment requirement for pointers is different on iSeries that on UNIX. iSeries uses 16-byte pointers. The issues which is on concern while porting UNIX app to iSeries are because of the diffrent alignment requirement for pointers and integers. On UNIX pointers and integers both align at 4-byte boundary whereas on iSeries pointers align at 16-byte and integers align at 4-byte boundary.

The difference in size of the data types may also effect alignment of structure or union that contains pointers. In structures containing pointers, there may be some padding for 16-byte alignment requirement for the pointers. The same problem may manifest in other ways while using a union in conjunction with the C ellipses as per following example:

 



typedef union {



    int   ui;



    char *up;



} u_t;







int foo(char *, ...);



Now if the function is called as:




int   i;



char *p;



u_t   u;







/* 1 */  foo("Int Now", i);



/* 2 */  foo("Int Now", u.ui);   /* wrong */



/* 3 */  foo("Union Int Now", u.ui);



The alignment requirement have changed between invocation of foo 1 and foo 2 in each case.

Case 1:




stack:         4-byte align - return code



               4-byte align - argument 1



               4-byte align - integer i (argument 2)



Case 2:




stack:         4-byte align - return code



               4-byte align - argument 1



               8-byte padding



               16-byte align - union u (argument 2)



If the code for foo() uses va_arg macro to try to pull off the u-t structure versus an int, alignment requirements may mean you get unexpected data.

The int will only have word alignment required on the stack, while inserting the int into the union will force 16-byte alignment and possibly padding on the stack. Bottom line: you need to know exactly which data type you are getting.

To save some storage to prevent padding _Packed qualifier can be used with structures. However, padding may still occur if there is a pointer in the structure, because of 16-byte alignment requirement of the pointers.

The above question uses va_arg macro, are there other considerations for use of variable arguments?

iSeries has a runtime difference during execution of va_arg. If the variable identified on va_start (the last right-most variable) is a short or char, va_arg does not position it's pointers correctly to pick up the variable length value. The ANSI C standard says that "The last argument must not have register storage class, and it must have a type that is not changed by the translator. (It cannot have an array type, a function type, type float, or any integer type that changes when promoted)." However, other platforms do allow shorts for the last fixed argument. The following example shows code that will cause a runtime exception on iSeries, but works fine on most UNIX platforms:




#include <stdio.h>



#include <stdarg.h>







int vout(short max, ...); /* on iSeries, short causes runtime error



                             This works O.K. on most UNIX  */







int main(void)



{



   vout(3, "Sat", "Sun", "Mon");



   printf("\n");



   vout(5, "Mon", "Tues", "Wed", "Thurs", "Fri");



}







int vout(short max, ...)



{



   va_list arg_ptr;



   int args = 0;



   char *days[7];







   va_start(arg_ptr, max);



   while(args < max)



   {



      days[args] = va_arg(arg_ptr, char *);



      printf("Day:  %s  \n", days[args++]);



      }



   va_end(arg_ptr);



}



The above example may be corrected by using the following on iSeries:




int vout(int max, ...);



Does iSeries has sys_nerr[] array for error message to be used in a C program?

sys_nerr[] is an array that exists on other systems that allows direct access to the strings that represent failure messages associated with errno values. The array is indexed on the errno value. On OS/400, errno message strings are translated along with most other readable text into many different languages. Because of this, the strings exist in a message file whose message ID's are indexed by the errno values. You can use function strerror() to retrieve a message text for an error number. Function strerror() gives the message text only in english, so if your job is using another language or if you want to retrieve message text in other languages you can use system API QMHRTVM. You can download an example which is a replacement for sys_nerr[].

Does iSeries support pointer arithmetic? Is it different from UNIX?

Yes, iSeries supports pointer arithmetic, but depending on the usage, there may be differences from UNIX. iSeries single-level storage assigns 16 megabyte segments on a per process basis. If, through pointer arithmetic, the 16 meg boundary is exceeded an exception occurs. The following example shows code that will cause a runtime exception on iSeries, but works fine on most UNIX platforms:




#include <stdio.h>



#include <string.h>







typedef struct {



    char one[10];



    char two[10];



    int  three;



    int  four;



    } SomeStruct;







main()



{



    SomeStruct *fp;



    SomeStruct Fred[500];



    int number1, number2;







    number1 = 5000001;



    number2 = 5000000;







    fp = Fred+number1 - number2;



}



Fred+number1 causes 16 meg segment to be exceeded; resulting pointer value set to NULL.

With the following change, the code runs OK:




    fp = Fred+(number1-number2);



(number1-number2) results in 1. Fred+1 is within 16 meg segment.

Is iSeries Big-Endian or Little-Endian machine?

iSeries is a Big-Endian machine.

I have heard that the iSeries uses 16 byte pointers. What are the porting considerations

One consideration is for data alignment, as mentioned above. Another consideration is casting between data types of integer and pointer. The result of integer-pointer casting will vary depending on the operating system release. In V4R2 and earlier releases any integer-pointer casting will result in a corrupted pointer and an runtime error. In V4R3 and later releases, a non-zero 4-byte integer value is preserved when converting to a pointer value and back to an integer. However, converting an integer to a pointer value does not yield a pointer value that can be used to call a function or access storage.

Does the iSeries support 64 bit integer data types?

Yes. In V4R3 and later releases, the iSeries supports the following data types in C and C++:

  • long long
  • long long int
  • signed long long
  • signed long long int
  • unsigned long long
  • unsigned long long int

[BACK]