On Jul 19, 2005, at 5:43 AM, Dominic Dunlop wrote:

On 19/07/2005, at 10:27 AM, Joshua Juran wrote:
I'm porting perl to a platform called Genie, which is a Unix-like subsystem that runs in Mac OS. The purpose of this exercise is to have a command-line perl tool available for Mac OS, in a stdio environment with polymorphic file descriptors, without the limitations of MPW.

Good to hear. You don't say whether this is PPC or 68k Mac OS. I guess the former, though the FAQs on your site make me wonder.

I wonder too.  I haven't looked at them in years.  :-)

Genie requires CFM -- Genie programs are built as CFM drop-ins, or plugins. CFM-68K Runtime Enabler 4.0 requires System 7.6.1, which requires a 32-bit clean ROM (and perhaps a 68020 or better). This leaves out the Mac II, IIx, IIcx, SE/30, and 68000-based machines (unless an earlier version of the CFM-68K Runtime Enabler with an earlier system works, which I don't plan to test any time soon). While it might be possible to use code resources (with Genie fiddling the A4 register for plugin globals) I don't see the value, since much faster Macs are readily available on the cheap. Genie does actually build and run on 68K, although you have to patch a bug in Threads.h if you want to use Thread Manager callbacks without crashing.

Genie's sockets support requires Open Transport -- MacTCP is not supported. I don't think this will upset anyone.

One caveat is that Open Transport only supports CFM-68K as of version 1.3, which requires Mac OS 8.1, which in addition to ruling out anything less than a 68040 nails you to a specific OS version. Fortunately, the OTCFM68KGlue library hacks around this by calling OT from a 68K code resource and should make it possible to support System 7.5.5 and 7.6.1. I haven't tried this yet.

Back in the day, I worked on keeping Perl running on PPC MachTen, a commercial UNIX-under-Mac OS product from Tenon Intersystems (http://www.tenon.com). The product, though still apparently available, is, as far as I know, unsupported, and suffers from a number of long-standing bugs and security issues. Vague requests from some users that the code be open-sourced after support ended were rebuffed.

Apple phrased it this way: "Open source is not a dumping ground for dead products."[1]

Most unfortunate, since I'm sure I could have found *something* useful in the source code. ;-) Other closed Unix-on-Mac products include Mac06 and (though this is a stretch) Apple's own MPW. Open-source projects include MacMiNT and PATMOS.

MachTen was delivered with gcc, so I didn't use MPW or CodeWarrior in porting perl. If you search in old perl5-

Genie requires a real C++ compiler to build, which rules out MrC/SC. Plugins shouldn't require C++ at all, but I haven't investigated using anything other than MW C. Perhaps I should -- I ran into some curious MW linker issues that prevent me from linking Genie plugins against my own shared libraries, and had to link in the standard library statically.

porters archives, you'll find mail about various issues I tripped over, including malloc() (once tweaked to work, Perl's own malloc was much faster than Mac OS' own); and fork() (MachTen, thanks to deep and probably dark magic, has both fork() and vfork(), but the latter is MUCH faster, as Mac OS does not support Copy on Write). You'll also find clues in hints/machten.sh.

One of the problems is returning twice. Matthias got the idea to provide vfork() as a macro that calls setjmp(), which he implemented in his Natty project.[2] I opted against this for now, since what you'd have to do with the return value of setjmp() to implement proper vfork() semantics and what the standard says you're allowed to do with it are not compatible. AFAICT you're not even allowed to assign the return value to a variable. It might work anyway, but I didn't wish to go there.

My interim solution requires as a compromise that code be written thus:

        #ifndef macintosh
        #define is_child_pid( pid )  ((pid) == 0)
        #endif
        
        pid_t pid;
        
        while ( (pid = vfork()) == -1 )  sleep(5);
        
        if ( is_child_pid( pid ) )
        {
                /* We're the child */
                /* setenv, dup2, etc. */
                
                execve( ... );
                
                _exit( EXIT_FOO );
        }
        
        /* We're the parent */
        
        waitpid( ... );

The trick here is that for a Genie plugin, vfork() saves the caller's process context and returns the child pid (once), is_child_pid() is the identity function (always true for a pid), and either execve() (unless it fails) or _exit() restores the original process context AND RETURNS. (Unless you call without forking, in which case it terminates the caller's thread.)

Hey -- it works, doesn't it?

The third way is to decide you're not just an application but really part of the operating system and actually implement per-process address spaces, a la MachTen. This has been left as an exercise for the reader.

For implementing qx// and system, vfork() is sufficient. For fork, we should be able to use the same perl_clone()-based emulation that Windows uses. See perlfork. It may even be possible to clone into a 'real' Genie process (which is really a kind of pseudo-process) without resorting to pseudo-(pseudo-)processes, such that 'fork and exit' would work.

Josh

[1] ...When asked to open-source HyperCard, at the 'Apple Handshake' session of MacHack 2000.

[2] http://www.sourceforge.net/projects/natty/

--
Joshua Juran
Metamage Software Creations - Mac Software and Consulting
http://www.metamage.com/

               * Creation at the highest state of the art *


Reply via email to