; .Ve .PP The flavor \fIperl_\|_.exe\fR is required if you want to start your program without a VIO window present, but not \f(CW\*(C`detach\*(C'\fRed (run \f(CW\*(C`help detach\*(C'\fR for more info). Very useful for extensions which use PM, like \f(CW\*(C`Perl/Tk\*(C'\fR or \f(CW\*(C`OpenGL\*(C'\fR. .PP Note also that the differences between PM and VIO executables are only in the \fIdefault\fR behaviour. One can start \fIany\fR executable in \&\fIany\fR kind of session by using the arguments \f(CW\*(C`/fs\*(C'\fR, \f(CW\*(C`/pm\*(C'\fR or \&\f(CW\*(C`/win\*(C'\fR switches of the command \f(CW\*(C`start\*(C'\fR (of \fICMD.EXE\fR or a similar shell). Alternatively, one can use the numeric first argument of the \&\f(CW\*(C`system\*(C'\fR Perl function (see OS2::Process). .SS \fIperl_\|_\|_.exe\fP .IX Subsection "perl___.exe" This is an \f(CW\*(C`omf\*(C'\fR\-style executable which is dynamically linked to \&\fIperl.dll\fR and CRT DLL. I know no advantages of this executable over \f(CW\*(C`perl.exe\*(C'\fR, but it cannot \fBfork()\fR at all. Well, one advantage is that the build process is not so convoluted as with \f(CW\*(C`perl.exe\*(C'\fR. .PP It is a VIO application. .SS "Why strange names?" .IX Subsection "Why strange names?" Since Perl processes the \f(CW\*(C`#!\*(C'\fR\-line (cf. "DESCRIPTION" in perlrun, "Command Switches" in perlrun, "No Perl script found in input" in perldiag), it should know when a program \fIis a Perl\fR. There is some naming convention which allows Perl to distinguish correct lines from wrong ones. The above names are almost the only names allowed by this convention which do not contain digits (which have absolutely different semantics). .SS "Why dynamic linking?" .IX Subsection "Why dynamic linking?" Well, having several executables dynamically linked to the same huge library has its advantages, but this would not substantiate the additional work to make it compile. The reason is the complicated-to-developers but very quick and convenient-to-users "hard" dynamic linking used by OS/2. .PP There are two distinctive features of the dyna-linking model of OS/2: first, all the references to external functions are resolved at the compile time; second, there is no runtime fixup of the DLLs after they are loaded into memory. The first feature is an enormous advantage over other models: it avoids conflicts when several DLLs used by an application export entries with the same name. In such cases "other" models of dyna-linking just choose between these two entry points using some random criterion \- with predictable disasters as results. But it is the second feature which requires the build of \fIperl.dll\fR. .PP The address tables of DLLs are patched only once, when they are loaded. The addresses of the entry points into DLLs are guaranteed to be the same for all the programs which use the same DLL. This removes the runtime fixup \- once DLL is loaded, its code is read-only. .PP While this allows some (significant?) performance advantages, this makes life much harder for developers, since the above scheme makes it impossible for a DLL to be "linked" to a symbol in the \fI.EXE\fR file. Indeed, this would need a DLL to have different relocations tables for the (different) executables which use this DLL. .PP However, a dynamically loaded Perl extension is forced to use some symbols from the perl executable, e.g., to know how to find the arguments to the functions: the arguments live on the perl internal evaluation stack. The solution is to put the main code of the interpreter into a DLL, and make the \fI.EXE\fR file which just loads this DLL into memory and supplies command-arguments. The extension DLL cannot link to symbols in \fI.EXE\fR, but it has no problem linking to symbols in the \fI.DLL\fR. .PP This \fIgreatly\fR increases the load time for the application (as well as complexity of the compilation). Since interpreter is in a DLL, the C RTL is basically forced to reside in a DLL as well (otherwise extensions would not be able to use CRT). There are some advantages if you use different flavors of perl, such as running \fIperl.exe\fR and \&\fIperl_\|_.exe\fR simultaneously: they share the memory of \fIperl.dll\fR. .PP \&\fBNOTE\fR. There is one additional effect which makes DLLs more wasteful: DLLs are loaded in the shared memory region, which is a scarse resource given the 512M barrier of the "standard" OS/2 virtual memory. The code of \&\fI.EXE\fR files is also shared by all the processes which use the particular \&\fI.EXE\fR, but they are "shared in the private address space of the process"; this is possible because the address at which different sections of the \fI.EXE\fR file are loaded is decided at compile-time, thus all the processes have these sections loaded at same addresses, and no fixup of internal links inside the \fI.EXE\fR is needed. .PP Since DLLs may be loaded at run time, to have the same mechanism for DLLs one needs to have the address range of \fIany of the loaded\fR DLLs in the system to be available \fIin all the processes\fR which did not load a particular DLL yet. This is why the DLLs are mapped to the shared memory region. .SS "Why chimera build?" .IX Subsection "Why chimera build?" Current EMX environment does not allow DLLs compiled using Unixish \&\f(CW\*(C`a.out\*(C'\fR format to export symbols for data (or at least some types of data). This forces \f(CW\*(C`omf\*(C'\fR\-style compile of \fIperl.dll\fR. .PP Current EMX environment does not allow \fI.EXE\fR files compiled in \&\f(CW\*(C`omf\*(C'\fR format to \fBfork()\fR. \fBfork()\fR is needed for exactly three Perl operations: .IP \(bu 4 explicit \fBfork()\fR in the script, .IP \(bu 4 \&\f(CW\*(C`open FH, "|\-"\*(C'\fR .IP \(bu 4 \&\f(CW\*(C`open FH, "\-|"\*(C'\fR, in other words, opening pipes to itself. .PP While these operations are not questions of life and death, they are needed for a lot of useful scripts. This forces \f(CW\*(C`a.out\*(C'\fR\-style compile of \&\fIperl.exe\fR. .SH ENVIRONMENT .IX Header "ENVIRONMENT" Here we list environment variables with are either OS/2\- and DOS\- and Win*\-specific, or are more important under OS/2 than under other OSes. .ie n .SS """PERLLIB_PREFIX""" .el .SS \f(CWPERLLIB_PREFIX\fP .IX Subsection "PERLLIB_PREFIX" Specific for EMX port. Should have the form .PP .Vb 1 \& path1;path2 .Ve .PP or .PP .Vb 1 \& path1 path2 .Ve .PP If the beginning of some prebuilt path matches \fIpath1\fR, it is substituted with \fIpath2\fR. .PP Should be used if the perl library is moved from the default location in preference to \f(CW\*(C`PERL(5)LIB\*(C'\fR, since this would not leave wrong entries in \f(CW@INC\fR. For example, if the compiled version of perl looks for \f(CW@INC\fR in \fIf:/perllib/lib\fR, and you want to install the library in \&\fIh:/opt/gnu\fR, do .PP .Vb 1 \& set PERLLIB_PREFIX=f:/perllib/lib;h:/opt/gnu .Ve .PP This will cause Perl with the prebuilt \f(CW@INC\fR of .PP .Vb 5 \& f:/perllib/lib/5.00553/os2 \& f:/perllib/lib/5.00553 \& f:/perllib/lib/site_perl/5.00553/os2 \& f:/perllib/lib/site_perl/5.00553 \& . .Ve .PP to use the following \f(CW@INC:\fR .PP .Vb 5 \& h:/opt/gnu/5.00553/os2 \& h:/opt/gnu/5.00553 \& h:/opt/gnu/site_perl/5.00553/os2 \& h:/opt/gnu/site_perl/5.00553 \& . .Ve .ie n .SS """PERL_BADLANG""" .el .SS \f(CWPERL_BADLANG\fP .IX Subsection "PERL_BADLANG" If 0, perl ignores \fBsetlocale()\fR failing. May be useful with some strange \fIlocale\fRs. .ie n .SS """PERL_BADFREE""" .el .SS \f(CWPERL_BADFREE\fP .IX Subsection "PERL_BADFREE" If 0, perl would not warn of in case of unwarranted \fBfree()\fR. With older perls this might be useful in conjunction with the module DB_File, which was buggy when dynamically linked and OMF-built. .PP Should not be set with newer Perls, since this may hide some \fIreal\fR problems. .ie n .SS """PERL_SH_DIR""" .el .SS \f(CWPERL_SH_DIR\fP .IX Subsection "PERL_SH_DIR" Specific for EMX port. Gives the directory part of the location for \&\fIsh.exe\fR. .ie n .SS """USE_PERL_FLOCK""" .el .SS \f(CWUSE_PERL_FLOCK\fP .IX Subsection "USE_PERL_FLOCK" Specific for EMX port. Since \fBflock\fR\|(3) is present in EMX, but is not functional, it is emulated by perl. To disable the emulations, set environment variable \f(CW\*(C`USE_PERL_FLOCK=0\*(C'\fR. .ie n .SS """TMP"" or ""TEMP""" .el .SS "\f(CWTMP\fP or \f(CWTEMP\fP" .IX Subsection "TMP or TEMP" Specific for EMX port. Used as storage place for temporary files. .SH Evolution .IX Header "Evolution" Here we list major changes which could make you by surprise. .SS "Text-mode filehandles" .IX Subsection "Text-mode filehandles" Starting from version 5.8, Perl uses a builtin translation layer for text-mode files. This replaces the efficient well-tested EMX layer by some code which should be best characterized as a "quick hack". .PP In addition to possible bugs and an inability to follow changes to the translation policy with off/on switches of TERMIO translation, this introduces a serious incompatible change: before \fBsysread()\fR on text-mode filehandles would go through the translation layer, now it would not. .SS Priorities .IX Subsection "Priorities" \&\f(CW\*(C`setpriority\*(C'\fR and \f(CW\*(C`getpriority\*(C'\fR are not compatible with earlier ports by Andreas Kaiser. See "setpriority, getpriority". .SS "DLL name mangling: pre 5.6.2" .IX Subsection "DLL name mangling: pre 5.6.2" With the release 5.003_01 the dynamically loadable libraries should be rebuilt when a different version of Perl is compiled. In particular, DLLs (including \fIperl.dll\fR) are now created with the names which contain a checksum, thus allowing workaround for OS/2 scheme of caching DLLs. .PP It may be possible to code a simple workaround which would .IP \(bu 4 find the old DLLs looking through the old \f(CW@INC\fR; .IP \(bu 4 mangle the names according to the scheme of new perl and copy the DLLs to these names; .IP \(bu 4 edit the internal \f(CW\*(C`LX\*(C'\fR tables of DLL to reflect the change of the name (probably not needed for Perl extension DLLs, since the internally coded names are not used for "specific" DLLs, they used only for "global" DLLs). .IP \(bu 4 edit the internal \f(CW\*(C`IMPORT\*(C'\fR tables and change the name of the "old" \&\fIperl????.dll\fR to the "new" \fIperl????.dll\fR. .SS "DLL name mangling: 5.6.2 and beyond" .IX Subsection "DLL name mangling: 5.6.2 and beyond" In fact mangling of \fIextension\fR DLLs was done due to misunderstanding of the OS/2 dynaloading model. OS/2 (effectively) maintains two different tables of loaded DLL: .IP "Global DLLs" 4 .IX Item "Global DLLs" those loaded by the base name from \f(CW\*(C`LIBPATH\*(C'\fR; including those associated at link time; .IP "specific DLLs" 4 .IX Item "specific DLLs" loaded by the full name. .PP When resolving a request for a global DLL, the table of already-loaded specific DLLs is (effectively) ignored; moreover, specific DLLs are \&\fIalways\fR loaded from the prescribed path. .PP There is/was a minor twist which makes this scheme fragile: what to do with DLLs loaded from .ie n .IP """BEGINLIBPATH"" and ""ENDLIBPATH""" 4 .el .IP "\f(CWBEGINLIBPATH\fR and \f(CWENDLIBPATH\fR" 4 .IX Item "BEGINLIBPATH and ENDLIBPATH" (which depend on the process) .ie n .IP "\fI.\fR from ""LIBPATH""" 4 .el .IP "\fI.\fR from \f(CWLIBPATH\fR" 4 .IX Item ". from LIBPATH" which \fIeffectively\fR depends on the process (although \f(CW\*(C`LIBPATH\*(C'\fR is the same for all the processes). .PP Unless \f(CW\*(C`LIBPATHSTRICT\*(C'\fR is set to \f(CW\*(C`T\*(C'\fR (and the kernel is after 2000/09/01), such DLLs are considered to be global. When loading a global DLL it is first looked in the table of already-loaded global DLLs. Because of this the fact that one executable loaded a DLL from \&\f(CW\*(C`BEGINLIBPATH\*(C'\fR and \f(CW\*(C`ENDLIBPATH\*(C'\fR, or \fI.\fR from \f(CW\*(C`LIBPATH\*(C'\fR may affect \&\fIwhich\fR DLL is loaded when \fIanother\fR executable requests a DLL with the same name. \fIThis\fR is the reason for version-specific mangling of the DLL name for perl DLL. .PP Since the Perl extension DLLs are always loaded with the full path, there is no need to mangle their names in a version-specific ways: their directory already reflects the corresponding version of perl, and \f(CW@INC\fR takes into account binary compatibility with older version. Starting from \f(CW5.6.2\fR the name mangling scheme is fixed to be the same as for Perl 5.005_53 (same as in a popular binary release). Thus new Perls will be able to \fIresolve the names\fR of old extension DLLs if \f(CW@INC\fR allows finding their directories. .PP However, this still does not guarantee that these DLL may be loaded. The reason is the mangling of the name of the \fIPerl DLL\fR. And since the extension DLLs link with the Perl DLL, extension DLLs for older versions would load an older Perl DLL, and would most probably segfault (since the data in this DLL is not properly initialized). .PP There is a partial workaround (which can be made complete with newer OS/2 kernels): create a forwarder DLL with the same name as the DLL of the older version of Perl, which forwards the entry points to the newer Perl's DLL. Make this DLL accessible on (say) the \f(CW\*(C`BEGINLIBPATH\*(C'\fR of the new Perl executable. When the new executable accesses old Perl's extension DLLs, they would request the old Perl's DLL by name, get the forwarder instead, so effectively will link with the currently running (new) Perl DLL. .PP This may break in two ways: .IP \(bu 4 Old perl executable is started when a new executable is running has loaded an extension compiled for the old executable (ouph!). In this case the old executable will get a forwarder DLL instead of the old perl DLL, so would link with the new perl DLL. While not directly fatal, it will behave the same as new executable. This beats the whole purpose of explicitly starting an old executable. .IP \(bu 4 A new executable loads an extension compiled for the old executable when an old perl executable is running. In this case the extension will not pick up the forwarder \- with fatal results. .PP With support for \f(CW\*(C`LIBPATHSTRICT\*(C'\fR this may be circumvented \- unless one of DLLs is started from \fI.\fR from \f(CW\*(C`LIBPATH\*(C'\fR (I do not know whether \f(CW\*(C`LIBPATHSTRICT\*(C'\fR affects this case). .PP \&\fBREMARK\fR. Unless newer kernels allow \fI.\fR in \f(CW\*(C`BEGINLIBPATH\*(C'\fR (older do not), this mess cannot be completely cleaned. (It turns out that as of the beginning of 2002, \fI.\fR is not allowed, but \fI.\e.\fR is \- and it has the same effect.) .PP \&\fBREMARK\fR. \f(CW\*(C`LIBPATHSTRICT\*(C'\fR, \f(CW\*(C`BEGINLIBPATH\*(C'\fR and \f(CW\*(C`ENDLIBPATH\*(C'\fR are not environment variables, although \fIcmd.exe\fR emulates them on \f(CW\*(C`SET \&...\*(C'\fR lines. From Perl they may be accessed by Cwd::extLibpath and Cwd::extLibpath_set. .SS "DLL forwarder generation" .IX Subsection "DLL forwarder generation" Assume that the old DLL is named \fIperlE0AC.dll\fR (as is one for 5.005_53), and the new version is 5.6.1. Create a file \&\fIperl5shim.def\-leader\fR with .PP .Vb 5 \& LIBRARY \*(AqperlE0AC\*(Aq INITINSTANCE TERMINSTANCE \& DESCRIPTION \*(Aq@#perl5\-porters@perl.org:5.006001#@ Perl module for 5.00553 \-> Perl 5.6.1 forwarder\*(Aq \& CODE LOADONCALL \& DATA LOADONCALL NONSHARED MULTIPLE \& EXPORTS .Ve .PP modifying the versions/names as needed. Run .PP .Vb 2 \& perl \-wnle "next if 0../EXPORTS/; print qq( \e"$1\e") \& if /\e"(\ew+)\e"/" perl5.def >lst .Ve .PP in the Perl build directory (to make the DLL smaller replace perl5.def with the definition file for the older version of Perl if present). .PP .Vb 2 \& cat perl5shim.def\-leader lst >perl5shim.def \& gcc \-Zomf \-Zdll \-o perlE0AC.dll perl5shim.def \-s \-llibperl .Ve .PP (ignore multiple \f(CW\*(C`warning L4085\*(C'\fR). .SS Threading .IX Subsection "Threading" As of release 5.003_01 perl is linked to multithreaded C RTL DLL. If perl itself is not compiled multithread-enabled, so will not be perl's \&\fBmalloc()\fR. However, extensions may use multiple thread on their own risk. .PP This was needed to compile \f(CW\*(C`Perl/Tk\*(C'\fR for XFree86\-OS/2 out-of-the-box, and link with DLLs for other useful libraries, which typically are compiled with \f(CW\*(C`\-Zmt \-Zcrtdll\*(C'\fR. .SS "Calls to external programs" .IX Subsection "Calls to external programs" Due to a popular demand the perl external program calling has been changed wrt Andreas Kaiser's port. \fIIf\fR perl needs to call an external program \fIvia shell\fR, the \fIf:/bin/sh.exe\fR will be called, or whatever is the override, see "\f(CW\*(C`PERL_SH_DIR\*(C'\fR". .PP Thus means that you need to get some copy of a \fIsh.exe\fR as well (I use one from pdksh). The path \fIF:/bin\fR above is set up automatically during the build to a correct value on the builder machine, but is overridable at runtime, .PP \&\fBReasons:\fR a consensus on \f(CW\*(C`perl5\-porters\*(C'\fR was that perl should use one non-overridable shell per platform. The obvious choices for OS/2 are \fIcmd.exe\fR and \fIsh.exe\fR. Having perl build itself would be impossible with \fIcmd.exe\fR as a shell, thus I picked up \f(CW\*(C`sh.exe\*(C'\fR. This assures almost 100% compatibility with the scripts coming from *nix. As an added benefit this works as well under DOS if you use DOS-enabled port of pdksh (see "Prerequisites"). .PP \&\fBDisadvantages:\fR currently \fIsh.exe\fR of pdksh calls external programs via \fBfork()\fR/\fBexec()\fR, and there is \fIno\fR functioning \fBexec()\fR on OS/2. \fBexec()\fR is emulated by EMX by an asynchronous call while the caller waits for child completion (to pretend that the \f(CW\*(C`pid\*(C'\fR did not change). This means that 1 \fIextra\fR copy of \fIsh.exe\fR is made active via \fBfork()\fR/\fBexec()\fR, which may lead to some resources taken from the system (even if we do not count extra work needed for \fBfork()\fRing). .PP Note that this a lesser issue now when we do not spawn \fIsh.exe\fR unless needed (metachars found). .PP One can always start \fIcmd.exe\fR explicitly via .PP .Vb 1 \& system \*(Aqcmd\*(Aq, \*(Aq/c\*(Aq, \*(Aqmycmd\*(Aq, \*(Aqarg1\*(Aq, \*(Aqarg2\*(Aq, ... .Ve .PP If you need to use \fIcmd.exe\fR, and do not want to hand-edit thousands of your scripts, the long-term solution proposed on p5\-p is to have a directive .PP .Vb 1 \& use OS2::Cmd; .Ve .PP which will override \fBsystem()\fR, \fBexec()\fR, \f(CW\`\`\fR, and \&\f(CW\*(C`open(,\*(Aq...|\*(Aq)\*(C'\fR. With current perl you may override only \fBsystem()\fR, \&\fBreadpipe()\fR \- the explicit version of \f(CW\`\`\fR, and maybe \fBexec()\fR. The code will substitute the one-argument call to \fBsystem()\fR by \&\f(CW\*(C`CORE::system(\*(Aqcmd.exe\*(Aq, \*(Aq/c\*(Aq, shift)\*(C'\fR. .PP If you have some working code for \f(CW\*(C`OS2::Cmd\*(C'\fR, please send it to me, I will include it into distribution. I have no need for such a module, so cannot test it. .PP For the details of the current situation with calling external programs, see "Starting OS/2 (and DOS) programs under Perl". Set us mention a couple of features: .IP \(bu 4 External scripts may be called by their basename. Perl will try the same extensions as when processing \fB\-S\fR command-line switch. .IP \(bu 4 External scripts starting with \f(CW\*(C`#!\*(C'\fR or \f(CW\*(C`extproc \*(C'\fR will be executed directly, without calling the shell, by calling the program specified on the rest of the first line. .SS "Memory allocation" .IX Subsection "Memory allocation" Perl uses its own \fBmalloc()\fR under OS/2 \- interpreters are usually malloc-bound for speed, but perl is not, since its malloc is lightning-fast. Perl-memory-usage-tuned benchmarks show that Perl's malloc is 5 times quicker than EMX one. I do not have convincing data about memory footprint, but a (pretty random) benchmark showed that Perl's one is 5% better. .PP Combination of perl's \fBmalloc()\fR and rigid DLL name resolution creates a special problem with library functions which expect their return value to be \fBfree()\fRd by system's \fBfree()\fR. To facilitate extensions which need to call such functions, system memory-allocation functions are still available with the prefix \f(CW\*(C`emx_\*(C'\fR added. (Currently only DLL perl has this, it should propagate to \fIperl_.exe\fR shortly.) .SS Threads .IX Subsection "Threads" One can build perl with thread support enabled by providing \f(CW\*(C`\-D usethreads\*(C'\fR option to \fIConfigure\fR. Currently OS/2 support of threads is very preliminary. .PP Most notable problems: .ie n .IP """COND_WAIT""" 4 .el .IP \f(CWCOND_WAIT\fR 4 .IX Item "COND_WAIT" may have a race condition (but probably does not due to edge-triggered nature of OS/2 Event semaphores). (Needs a reimplementation (in terms of chaining waiting threads, with the linked list stored in per-thread structure?)?) .IP \fIos2.c\fR 4 .IX Item "os2.c" has a couple of static variables used in OS/2\-specific functions. (Need to be moved to per-thread structure, or serialized?) .PP Note that these problems should not discourage experimenting, since they have a low probability of affecting small programs. .SH BUGS .IX Header "BUGS" This description is not updated often (since 5.6.1?), see \fI./os2/Changes\fR for more info. .SH AUTHOR .IX Header "AUTHOR" Ilya Zakharevich, cpan@ilyaz.org .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fBperl\fR\|(1).