Teraspace Usage Tips

You might encounter the following scenarios as you work with the teraspace storage model. Recommended solutions are provided.

  • Scenario 1: You need more than 16 MB of dynamic storage in a single allocation

    Use _C_TS_malloc or create your programs so that teraspace will be used for heap storage, as described in Using Teraspace for Storage.

  • Scenario 2: You need more than 16 MB of shared memory

    Use shared memory (shmget) with the teraspace option.

  • Scenario 3: You need to access large byte-stream files efficiently

    Use memory mapped files (mmap).

    You can access memory-mapped files from any program, but for best performance, use the teraspace storage model and, if your language supports it, the 8-byte pointer data model.

  • Scenario 4: You need greater than 16 MB of contiguous automatic or static storage

    Use teraspace storage model.

  • Scenario 5: Your application makes heavy use of space pointers

    Use the teraspace storage model and a language that supports the 8-byte pointer data model, to reduce memory footprint and speed up pointer operations.

  • Scenario 6: You need to port code from another system and want to avoid issues that are unique to 16-byte pointer usage

    Use the teraspace storage model and a language that supports the 8-byte pointer data model.

  • Scenario 7: You need to use single-level storage in your teraspace program
    Sometimes your only choice is to use single-level storage in your teraspace storage model programs. For example, you might need it to store user data for interprocess communication. You can get single-level storage from any of the following sources:
    • Storage in a user space, obtained from the QUSCRTUS API or the CRTS MI instruction
    • Single-level storage heap interfaces in your programming language
    • Single-level storage reference that was passed to your program
    • Single-level storage heap space obtained from the ALCHS MI instruction
  • Scenario 8: Take advantage of 8-byte pointers in your code

    Create your module and program with STGMDL(*TERASPACE). Use DTAMDL(*LLP64) or explicit declarations (__ptr64) to get 8-byte pointers to refer to teraspace (as opposed to 16-byte pointers pointing into teraspace). Then you will get the advantages listed in Taking Advantage of 8-byte Pointers in Your C and C++ Code.

  • Scenario 9: Incorporating a single-level storage model module
    You cannot bind a single-level storage module with a teraspace storage model module. If you need to do this, first try to get a version of the module that uses (or inherits) the teraspace storage model, then simply use it as described in Using Teraspace: Best Practices. Otherwise, you have two options:
    • Package the module into a separate service program. The service program will use the single-level storage model, so use the approach given in scenario 10, below, to call it.
    • Package the module into a separate program. This program will use the single-level storage model. Use the approach outlined in scenario 11, below, to call it.
  • Scenario 10: Binding to a single-level storage model service program

    You can bind your teraspace program to a service program that uses single-level storage if the two service programs activate into separate activation groups. You cannot do this if the single-level storage service program specifies the ACTGRP(*CALLER) option.

  • Scenario 11: Calling functions that have pointer-to-pointer parameters

    Calls to some functions that have pointer-to-pointer parameters require special handling from modules compiled with the DTMDL(*LLP64 option). Implicit conversions between 8- and 16-byte pointers apply to pointer parameters. They do not apply to the data object pointed to by the pointer parameter, even if that pointer target is also a pointer. For example, the use of a char** interface declared in a header file that asserts the commonly used P128 data model will require some code in modules that are created with data model LLP64. Be sure to pass the address of a 16-byte pointer for this case. Here are some examples:

    • In this example, you have created a teraspace storage model program using 8-byte pointers with the STGMDL (*TERASPACE) DTAMDL(*LLP64) options on a create command, such as CRTCMOD. You now want to pass a pointer to a pointer to a character in an array from your teraspace storage model program to a P128 char** interface. To do so, you must explicitly declare a 16-byte pointer:
      #pragma datamodel(P128)
      void func(char **);
      #pragma datamodel(pop)
      
      char myArray[32];
      char *_ptr128 myPtr;
      
      myPtr = myArray; /* assign address of array to 16-byte pointer */
      func(&myPtr);    /* pass 16-byte pointer address to the function */
    • One commonly used application programming interface (API) with pointer-to-pointer parameters is iconv. It expects only 16-byte pointers. Here is part of the header file for iconv:
      ...
      #pragma datamodel(P128)
      ...
      size_t iconv(iconv_t cd,
                   char     **inbuf,
                   size_t   *inbytesleft,
                   char     **outbuf,
                   size_t   *outbytesleft);
      ...
      #pragma datamodel(pop)
      ...
      The following code calls iconv from a program compiled with the DTAMDL(*LLP64) option:
      ...
      iconv_t myCd;
      size_t myResult;
      char *_ptr128 myInBuf, myOutBuf;
      size_t myInLeft, myOutLeft;
      ...
      myResult = iconv(myCd, &myInBuf, &myInLeft, &myOutBuf, &myOutLeft);
      ...
      You should also be aware that the header file of the Retrieve Pointer to User Space (QUSPTRUS) interface specifies a void* parameter where a pointer to a pointer is actually expected. Be sure to pass the address of a 16-byte pointer for the second operand.
  • Scenario 12: Redeclaring functions

    Avoid redeclaring functions that are already declared in header files supplied by IBM®. Usually, the local declarations do not have the correct pointer lengths specified. One such commonly used interface is errno, which is implemented as a function call in IBM i.

  • Scenario 13: Using data model *LLP64 with programs and functions that return a pointer

    If you are using data model *LLP64, look carefully at programs and functions that return a pointer. If the pointer points to single-level storage, its value cannot be correctly assigned to an 8-byte pointer, so clients of these interfaces must maintain the returned value in a 16-byte pointer. One such API is QUSPTRUS. User spaces reside in single-level storage.