Release Notes for Compaq C Compiler Developers' Toolkit Supplement +------------------------------------------------------------------------+ | Copyright 2002 Compaq Information Technologies Group, L.P. | | | | Compaq and the Compaq logo are trademarks of Compaq Information | | Technologies Group, L.P. in the U.S. and/or other countries. | | | | Confidential computer software. Valid license from Compaq required for | | possession, use or copying. Consistent with FAR 12.211 and 12.212, | | Commercial Computer Software, Computer Software Documentation, and | | Technical Data for Commercial Items are licensed to the U.S. Government| | under vendor's standard commercial license. | +------------------------------------------------------------------------+ 1. Purpose of the kit 2. Default Compilation Options Change 3. Parallel Programming Support 3.1 OpenMP API 3.2 old-style manual decomposition directives 4. Other Differences from V4.0D Base System cc compiler 4.1 -source_listing improvements 4.2 -check_bounds option 4.3 declarations interspersed with statements 4.4 variable length arrays 4.5 initializers with designators 4.6 new message controls 4.7 informationals to report unnecessary #include files 4.8 new diagnostics to detect undefined side effects 4.9 intrinsic function improvements 4.10 default command line options 4.11 Microsoft compatibility mode 4.12 thread local storage 4.13 restricted pointers 4.14 builtin functions 4.15 new command line option -FIpathname 4.16 new -SD command line option 4.17 new gcc compatibility features 5. Dense malloc Library 6. Header Files 6.1 new C99 library functions 6.2 #include_next preprocessing directive 6.3 numa.h 6.4 omp.h 1. Purpose of the kit This kit delivers new C compiler technology on currently-shipping versions of Compaq's Tru64 UNIX (V4.0D and later). This new Developers' Toolkit (dtk) compiler provides: o a proven and reliable compiler that incorporates many important bug fixes from previous versions. o an improved code generator/optimizer that exploits the latest Alpha hardware technology (especially the EV6 and EV7 processors). o a significantly improved diagnostic facility: better messages, more messages (including uninitialized variable detection, run-time array bounds checking, and unused header file detection), and improved command-line and #pragma diagnostic controls (including lint-style message groups). o a full implementation of the OpenMP Parallel Programming API for shared memory multi-processing. o new features from the C99 standard including restricted pointers, variable length arrays, interspersed declarations and statements, initializers with designators, compound literals, macros with a variable number of arguments, _Pragma preprocessing operator, __func__ predefined identifier, hexadecimal floating-point literals, and complex data types (on V5.1A and later systems). 2. Default Compilation Options Change The compilers that shipped with the V4.0* base operating systems default to -std0 (K&R mode). The Developers' Toolkit Supplement compiler defaults to -std (relaxed ANSI mode). This change in default language mode was carried to the base system cc compiler in V5.0. The change had long been requested by our user community and is consistent with industry trends. Please note this change. For compilations that rely on V4 default settings, it could result in differences in diagnostics or program behavior. If such differences are bothersome, the compiler can be made to emulate the V4 base system compiler by adding "-std0" to the command-line. The command-line change can be made noninvasively using a comp.config file or the DEC_CC environment variable (see the cc(1) man page for details). If that doesn't work, you can access the base system compiler directly using the "-nodtk" option. The (dtk) compiler also adds -intrinsics to the default command line. This option enables automatic intrinsic function recognition. It typically allows the compiler to produce better diagnostics and faster object code by allowing it to assume that external functions with names and argument types that match standard library functions actually are those standard library functions, even if the program does not #include the appropriate header file. This assumption allows the compiler to do argument checking and even replace those function calls with faster code. This may cause problems however. Unusual programs that define their own implementations of external functions whose names match the names of library functions may not behave as expected when compiled with this option turned on. In this case, as before, you can emulate the behavior of the compiler that shipped with the system by adding "-nointrinsics" to the command-line, or "-nodtk". 3. Parallel Programming Support This version of the compiler supports the OpenMP API for shared memory parallel programming, in addition to an older set of parallel decomposition features. 3.1 OpenMP API The OpenMP application program interface (API) supports multi-platform shared-memory programming on Unix platforms and Microsoft Windows NT architectures. Jointly defined by a group of major computer hardware and software vendors, OpenMP is a portable, scalable model that gives shared-memory programmers a simple and flexible interface for developing parallel applications for platforms ranging from the desktop to the supercomputer. The implementation of this feature consists of a set of compile-time #pragma directives, a new header file (omp.h), a new runtime library (libots3.so and .a), and a new command line option (-omp) that enables the pragmas and links with the new runtime library (and other existing thread libraries). If the command line option to enable the directives is not specified, then the compiler will ignore the directives (effectively treating them as comments), which can generally produce a valid sequential application that performs the same function. For more information, see Chapter 13 (OpenMP Parallel Processing) of the Programmer's Guide. After the kit is installed, use a Web browser to access the Developers' Toolkit Supplement edition of the Programmer's Guide at file:/usr/share/doclib/cc.dtk/guide/TITLE.HTM Also, information about OpenMP, including specifications for both the C language and Fortran language APIs is available at the OpenMP web site: www.openmp.org. 3.2 old-style manual decomposition directives This feature provides a similar kind of capability to that provided by OpenMP, but it is not recommended for use in new code. It provides compatibility with an older set of features provided by the SGI PowerC compiler, to allow existing programs to be ported easily from SGI platforms to Compaq Tru64 UNIX. To ease the process of converting existing code using the old-style directives to use OpenMP, the -mp compiler option enables both the OpenMP and the old- style directives. Note that while the compiler will process both kinds of directives under the -mp option, the two sets of directives have significantly different models of how the parallelism is controlled. In particular, OpenMP parallel regions have dynamic extent (i.e. the parallel region is available to functions called from a parallel region), while the old-style directives require that parallel constructs appear within the lexical scope of a parallel region. For this reason, incremental conversion from the old-style directives to the OpenMP API must be done carefully. Under the -omp option, only the OpenMP directives are recognized, and any old-style directives are ignored. Like OpenMP, the old-style decomposition feature consists of a set of #pragma directives, a header file (mpc.h), a runtime library (libots3.so and .a), and a command line option (-mp) that enables the pragmas and links with the runtime library and other thread libraries. A description of these pragmas is provided in Appendix D (Parallel Processing - Old Style) of the Programmer's Guide. After the kit is installed, use a Web browser to access the Developers' Toolkit Supplement edition of the Programmer's Guide at file:/usr/share/doclib/cc.dtk/guide/TITLE.HTM 4. Other Differences from V4.0D Base System cc compiler This compiler has a much newer version of the GEM optimizing backend and offers improved support and tuning for the latest Alpha processors, including ev6 and ev7. Other significant features include the following (see the man page, the Programmer's Guide, the Language Reference Manual, and/or the C99 standard for addiotional information): 4.1 -source_listing improvements When a listing file is requested via -source_listing, each source line is annoted with the statement nesting level in effect at the end of that line. This is a simple integer just before the line number. Statements at the outermost scope of a function definition are marked level 1, while outside of function definitions the field is blank. Also, additional sections can be added to the listing using new keyword arguments to the -show option as follows: o -show messages adds a section showing all of the compiler's diagnostic messages that are enabled at the start of the compilation, reflecting the effects of the language dialect mode and any command line message controls. The listing shows the message identifier (which can be used to suppress or alter the message severity), the severity, and the parameterized message text. If the -verbose command line option is also used, then the listing also provides the more detailed explanation and suggested user action for each message. o -show symbols adds a symbol table map to the listing. o -show brief is similar to -show symbols, but it suppresses unreferenced symbols declared in header files. o -show cross_reference adds a list of line numbers at which each listed symbol is referenced. When appropriate, the line number designating a reference to a symbol is annotated with a suffix indicating the way in which the symbol was used on that line. 4.2 -check_bounds option The -check_bounds option causes the compiler to generate code to check the bounds of array-indexing expressions at run-time, and raise an exception if the index is out of bounds. The C language defines the subscript expression a[i] to be equivalent to *(a+i), relying on the implicit conversion of an array name to a pointer to the first element of an array, and on the fact that adding an integer to a pointer involves "scaling" the index by the size of pointed-to object. Because of this equivalence, array syntax can be used either with pointers or with the names of arrays. The -check_bounds functionality checks array bounds only when an element is accessed using a declared array name (using either array notation or pointer dereference notation). The check is made at the point that the compiler processes an add or subtract of an array name and an integer. The result of that operation is a pointer and so subsequent operations are not included in the checking code. Also note that the C language considers computation of the address one past the end of an array to be fully portable. Therefore, expressions that appear to compute an address allow an extra element at the end. It is only when an array name is used directly with array subscript notation that the exact upper bound is checked. For example, { int a[5]; // elements are 0..4, but you // can take the address of a[5] int *pa, i=6, j=-6; pa = a + i; // trap, &a[6] pa = a + i + j; // trap, &a[6] - 6 pa = a + (i + j); // no trap, &a[0] pa = a + (i - 1); // no trap, &a[5] j = a[i - 1]; // trap, a[5] j = *(a + (i - 1)); // no trap, looks like &a[5] } For more information, see Section 2.4.3 (Enabling Run-Time Checking of Array Bounds) of the Programmer's Guide. After the kit is installed, use a Web browser to access the Developers' Toolkit Supplement edition of the Programmer's Guide at file:/usr/share/doclib/cc.dtk/guide/TITLE.HTM 4.3 declarations interspersed with statements This C99 feature is essentially the same as the C++ feature that permits declarations to be placed anywhere a statement is allowed. In addition, it allows the first expression of a "for" loop (typically the initial value assignment) to be a declaration. This permits declarations to be placed close to their point of first use without having to add a nested compound statement. It also permits loop control variables to be declared and initialized within the "for" statement itself, with scope limited to the body of the "for". For example, int main(void) { printf("Starting up.\n"); const int iterations = rand() % 50; for (int i = 0; i < iterations; i++) { printf("i = %d.\n", i); } } 4.4 variable length arrays This C99 feature permits "array objects with auto storage class" and "array typedefs declared at block scope" to have bounds that are runtime-computed expressions. It also permits the declaration and definition of functions whose parameters are arrays dimensioned by other parameters (similar to Fortran assumed-shape arrays). The following example illustrates both uses. Note that the definition of function sub() uses prototype syntax and that the dimension parameters precede the array parameter that uses them. In order to define a function with the dimension parameters following the array parameter that uses them, it is necessary to write the function definition using K&R syntax (since that syntax allows the declarations of the types of the parameters to be written in a different order from the parameters themselves). K&R function definitions should generally be avoided. #include #include void sub(int, int, int[*][*]); int main(int argc, char **argv) { if (argc != 3) { printf("Specify two array bound arguments.\n"); exit(EXIT_FAILURE); } { int dim1 = atoi(argv[1]); int dim2 = atoi(argv[2]); int a[dim1][dim2]; int i, j, k = 0; for (i = 0; i < dim1; i++) { for (j = 0; j < dim2; j++) { a[i][j] = k++; } } printf("dim1 = %d, dim2 = %d.", sizeof(a)/sizeof(a[0]), sizeof(a[0])/sizeof(int)); sub(dim1, dim2, a); sub(dim2, dim1, a); } exit(EXIT_SUCCESS); } void sub(int sub1, int sub2, int suba[sub1][sub2]) { int i, j, k = 0; printf("\nIn sub, sub1 = %d, sub2 = %d.", sub1, sub2); for (i = 0; i < sub1; i++) { printf("\n"); for (j = 0; j < sub2; j++) { printf("%4d", suba[i][j]); } } } Note that variable length arrays can often be used in place of the non-standard alloca() intrinsic. An important difference is that the storage allocated by alloca() is not freed until return from the function, while the storage allocated for variable length arrays is normally freed on exit from the block in which they are allocated. If alloca() is called within the scope of a variable length array declaration, then the storage allocated by that call to alloca will be freed on exit from the nearest enclosing block. 4.5 initializers with designators This C99 feature extends the current syntax for initializers to allow explicit initialization of a specified subset of the members in a struct or union, or elements in an array. Unspecified members or elements are implicitly initialized to zero. The syntax adds an optional "designation" before each initializer within an "initializer-list" as defined in the current ANSI/ISO C language grammar. The designation consists of member-selection and array-element syntax followed by and equals sign. The new syntax is: initializer: assignment-expression { initializer-list } { initializer-list , } initializer-list: designation-opt initializer initializer-list , designation-opt initializer designation: designator-list = designator-list: designator designator-list designator designator: [ constant-expression ] . identifier Some examples of use: enum {member_one, member_two}; const char *nm[] = { [member_two] = "member two", [member_one] = "member one", }; div_t answer = {.quot = 2, .rem = -1}; struct {int a[3], b;} w[] = {[0].a = {1}, [1].a[0] = 2}; int a[MAX] = {1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0 }; union {float f; int i;} u = {.i = 42}; 4.6 new message controls There are new command line options and #pragma syntax to control diagnostic messages issued by the compiler. The command-line options are described on the cc man page (see the -msg_* options). The #pragma syntax is described in the Programmer's Guide. Briefly, for each -msg_actiontype command-line option, there is a corresponding #pragma message syntax that gives the same effect. For example, command line option "-msg_enable a,b" corresponds exactly to "#pragma message enable (a,b)". The actions in the -msg* command-line options have abbreviated spellings, but when using the #pragma message syntax the words must be fully spelled out. The fully spelled names are: #pragma message enable #pragma message disable #pragma message emit_always #pragma message emit_once #pragma message fatal #pragma message error #pragma message warning #pragma message informational 4.7 informationals to report unnecessary #include files There are several of these. The most useful, unusedtop, reports only headers explicitly #included in the top-level of the compilation unit (typically the .c file) that did not provide anything used by the rest of the compilation. This message is enabled at level4 (i.e. it is not enabled by default). The other diagnostics report on the effects of #includes nested within other headers and are enabled at level5. All of these messages can be enabled by the message group unused. Unlike any other messages, these messages must be enabled on the command line in order to be effective. The processing that analyzes the dependencies on included files is signficant, and it must be started before processing of the input files begins (i.e. #pragma message directives within the source have no effect on these messages). 4.8 new diagnostics to detect undefined side effects There are new compiler diagnostics to detect simple expressions with side effects that have undefined behavior. The C standard formalized de facto rules about side effects in terms of "sequence points". An expression that modifies the same object more than once, or that modifies an object and fetches its value for a purpose other than computing the modified value, has undefined behavior unless there is an intervening sequence point. The compiler warns about such expressions (only for objects that are simple declared variables). For example, the user will now be warned that the expression "i = i++" relies on undefined behavior (the assignment operator does not introduce a sequence point). 4.9 intrinsic function improvements See the -[no]intrinsics option on the man page. 4.10 default command line options A new environment variable, DEC_CC, can supply default command line options. It is described in the cc(1) man page. 4.11 Microsoft compatibility mode See the -ms option on the man page. 4.12 thread local storage The compiler now supports a language feature to declare variables with static extent to be allocated locally to each thread when not using the -mp or -omp options. This is done using the same syntax used in Microsoft's C compiler for Visual C++, namely a storage class modifier __declspec(__thread). OpenMP also uses the functionality of thread local storage when variables are made "private". Note that though code using this feature is typically written as something like "extern Thread int i;", Thread is typically a macro that expands to __declspec(__thread). This language feature can be used to simplify source code that would otherwise use POSIX API's to obtain and access thread-local memory that has "static" extent for the life of a thread. While the POSIX API's are more portable, the language feature vastly simplifies the task of converting existing single-threaded code that uses globals and statics into code that can be used with multiple threads. 4.13 restricted pointers Restricted pointers are a mechanism by which the programmer can assert limitations on the aliasing properties of particular pointer variables, which often can enable additional code optimization. This mechanism has been present in Cray C compilers for some time, is being adopted by other vendors, and is present in the C99 standard. See also the -assume and -accept options on the man page for other features involving restricted pointers. 4.14 builtin functions The following new builtin functions for bit counting are provided in an updated version of long _popcnt(unsigned long) // number of 1 bits in argument long _poppar(unsigned long) // parity of argument, 1 = odd long _leadz(unsigned long) // leading zero bits in argument long _trailz(unsigned long) // trailing zero bits in argument unsigned long int_mult_upper(unsigned long, // #defined to unsigned long) // __UMULH() This updated version of the header is provided in /usr/include.dtk which is searched by the new compiler before it searches /usr/include. 4.15 new command line option -FIpathname See the cc(1) man page. 4.16 new -SD command line option See the cc(1) man page. 4.17 new gcc compatibility features The following extensions are supported or partially supported in this version of Compaq C (there are many other minor gcc features and behaviors in common with Compaq C not listed here): o #include_next This is very useful in adapting to various irregularities in system-supplied header files without having to provide or generate entirely new versions to make them compatible with the compiler. o Constructor Expressions Using the construct (type-name){initializer-list}. This is what C99 refers to as a compound literal. o Referring to a Type with typeof Compaq C only supports the __typeof__ spelling of this operator. It does not support the typeof spelling. o Arrays of Length Zero When appearing in a struct or union or parameter declaration, Compaq C will treat arrays of zero length in the same way gcc does. When appearing elsewhere, Compaq C will issue a diagnostic and treat the array as if it were declared with one element. o Inquiring on Alignment gcc supports the __alignof__ operator. Compaq C supports a similar __builtin_alignof operator. o Specifying Attributes of Variables Although Compaq C does not support the __attribute__ keyword on declarations, it does provide some similar capabilities. The gcc aligned attribute corresponds to the Compaq C __align storage class modifier. Some of the gcc nocommon, section attributes can be set using #pragma extern_model in Compaq C. o Inline Functions Both gcc and C99 define an inline (__inline) qualifier for functions, and allow it to be applied to functions with external linkage. Some of the details, in particular the conditions under which a function body with an external symbol is generated in the object module, differ. The command line option "-accept gccinline" tells the compiler to provide the gcc behavior (this is the default on Linux). The option "-accept nogccinline" tells the compiler to provide the C99 behavior (which is the default on Tru64). o Assembler Instructions with C Expression Operands The Compaq C compiler provides a simple but powerful form of inline-assembler capability that superficially resembles the gcc feature in that it looks like a function call. But the detailed syntax and semantics differ substantially. The Compaq C form is simple and flexible to use and generally works well with the optimizer without the need for semantic annotations that are often required with the machine-description based notation used by gcc. o Function Names as Strings The compiler implements the C99 __func__ predeclared variable that is equivalent to the gcc __FUNCTION__ variable. 5. Dense malloc Library This kit installs new library /usr/ccs/lib/libdensemalloc.a onto V5.1 systems. This library provides an alternate set of malloc routines that implement a "dense malloc" memory allocation strategy. This new strategy can improve runtime performance in programs that o make heavy use of heap memory o call malloc and free (and realloc) infrequently o allocate memory in lots of small chunks o reference those chunks very frequently In general, the "dense malloc" strategy decreases the execution speed of malloc and free but increases the cache density of the allocated memory chunks. It does this by reducing the bookkeeping overhead and round-up padding attached to allocated chunks. In applications where cache density is a dominant factor in runtime performance, this can have a significantly positive net effect. To use the "dense malloc" memory allocator, link this new library into your application by adding the following sequence to your cc or ld command-line(s) -all -ldensemalloc -none The new allocator can be adjusted with the tuning-variables described below. To use these, define a statically-initialized variable of the appropriate type with the desired value, for instance: const int __dense_malloc_max_size = 128; Allocator defaults, limits and tuning variables: (void *) __dense_malloc_base_address sets the mmap hint address for where to allocate the smallest of the pools; the rest are allocated upward from there. Default (taso): 0x0 (non-taso): 0x2F000000000 (int) __dense_malloc_max_size determines the size of the largest request that will be allocated by this allocator. If not a multiple of 16, the value is rounded up to the next multiple of 16. Requests for memory which are larger than this value are filled by the normal malloc routines. Default: 64 bytes Limit: 128 bytes (int) __dense_malloc_max_pool_size determines how large a chunk of the address space is reserved for each pool (each size 8, 16, 32, 48 ...). If this space is exhausted, another location will be used, but this slows down free(). Default (taso): 0x600000 (non-taso): 0x1800000 (int) __dense_malloc_mmap_pages specifies, in pages, how large an increment should be obtained on each allocation from the kernel. Default: 8 pages 6. Header Files The Compaq C kit delivers new header files into /usr/include.dtk. These include header files that define the parallel decomposition APIs (omp.h, mpc.h), new C99 header files (e.g. stdbool.h), and "supplemental" header files that contain new C99 declarations (e.g. stdio.h). 6.1 New C99 library functions The Compac C compiler kit ships system header files that declare new ANSI/ISO C99 library names such as round, roundf, and roundl (math.h). The C99 header files install into /usr/include.dtk. This directory is added to the compiler's #include search path automatically by the cc driver so that the header files will be read during "normal" compiles. The header files declare ALL of the new C99 names even though many of those functions do not yet exist in the libraries of shipping versions of Tru64 UNIX. The names are reserved by the C99 Standard and the library functions will become available in future versions of the OS. The header files are conditionalized so that the new C99 names ARE available in the default compilation mode (-std, relaxed ANSI). This may cause compilation problems, however, since the new names may conflict with user-declared program names. If such problems arise, users might consider o renaming the conflicting identifier(s) in their code. While sometimes difficult, this is clearly the preferred option. It is consistent with the emerging C99 Standard and leaves the new C99 API fully available. o adding -U__STDC_VERSION__ to the command-line or using -D to set it to something less than 199901. This turns off just those features introduced by C99. o defining an explicit library conformance macro on the command-line, i.e. -D_ANSI_C_SOURCE or -D_XOPEN_SOURCE. This turns off more features than just those introduced by C99 and so is not recommended for programs that rely on Tru64 UNIX extensions. See the standards(5) man page for details. o compiling in a language mode that does not provide these new C99 names. Such modes include -std0 (K&R), -std1 (strict ANSI C89), and -vaxc. To compile in a mode that does not support C99 language features (-std0, -std1, and -vaxc) but still get declarations for the new C99 library functions, users might consider o adding -D__STDC_VERSION__=199901 to the command-line. 6.2 #include_next preprocessing directive Compaq C implements the gcc #include_next directive. #include_next looks like and works like #include. The only difference is that it uses a slightly different algorithm for finding the specified file. To implement #include searching, the compiler constructs an ordered list of directories to search: 1) directory containing the original source file 2) directories specified by -I command-line switches 3) /usr/include To find a file, the compiler simply walks this directory search list (from the top) until it finds the file. The search list can be modified in two ways: a) the <> form (as opposed to the "" form) of #include means don't do #1 (don't search the original source dir) b) -I (with no argument) means don't do #3 (don't search /usr/include) #include_next uses the same search list, it just uses it in a slightly different way. Instead of starting from the top of the list every time it searches for a new file, #include_next remembers the directory where it finds every file. If it finds an #include_next directive in a file, it begins the search for the new file in the NEXT directory after that file in the search list. For example, if the search list looks like this 1) /usr/foo_dir (contains foo.c) 2) /usr/bar_dir (contains foo.h) 3) /usr/include (contains foo.h) If foo.c contains "#include " the compiler will find /usr/bar_dir/foo.h. If /usr/bar_dir/foo.h contains "#include " the compiler will find /usr/bar_dir/bar.h, the same file. If that file isn't properly guarded, this will lead to infinite recursive inclusion. If /usr/bar_dir/foo.h contains "#include_next " the compiler will find /usr/include/bar.h, a different file. This new directive allows users to create new header files that "supplement" existing header files. Users might, for instance, create a new stdio.h file that adds more declarations to the existing file. The new file would then contain "#include_next ". Any source file with "#include " would then, given the correct -I command-line switch, get both the new declarations from the supplemental file and also the full contents of the original system header file. The Compaq C compiler kit uses exactly this technique for adding new C99 declarations to the standard system header files such as stdio.h. o the supplemental header files are contained in /usr/include.dtk o the cc driver adds -I/usr/include.dtk to the default command-line o the supplemental files contain the new C99 declarations and also #include_next directives to get the full contents of their counterpart files from /usr/include 6.3 numa.h This kit installs /usr/include.dtk/numa.h to include declarations for five new routines that are contained in the libots3 library that ships with the kit (and installs on Tru64 UNIX V5.1 and later systems). The five new routines are useful in OpenMP and/or pthread programs running on NUMA machines. They are C-callable functions that underlie the NUMA directives added to the Fortran compiler. This new numa.h is a "supplemental" header file that includes /usr/include/numa.h using the #include_next directive described above, then adds the five aforementioned declarations. On pre-V5.1 versions of Tru64 UNIX, there is no numa.h header file because the underlying OS support was not yet implemented. Although this kit installs a numa.h on those earlier systems, applications that #include that file will still fail at compile-time because the #include_next contained therein will not find /usr/include/numa.h. 6.4 omp.h This file defines the OpenMP parallel decomposition API. The version of omp.h in this kit adds a new declaration for _OtsGetOmpThread(). This routine gets the pthread_t handle corresponding to the specified OpenMP thread ID. In order to get the declaration of pthread_t, omp.h now #includes , which brings in a large number of declarations.