I would like to add my work to the core (when it's ready) as a new platform. Unless anyone objects, the platform name is 'Lamp', unix-name 'lamp', custom header 'lampish.h', and preprocessor macro MACOS_LAMP.

On Jul 19, 2005, at 11:31 AM, Joshua Juran wrote:

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

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.

Genie requires CFM...
Genie's sockets support requires Open Transport ...

I forgot to mention -- Genie builds and runs both as Carbon and classic. I typically develop in OS X using Carbon, running either natively or in Classic.

MachTen was delivered with gcc, so I didn't use MPW or CodeWarrior in porting perl. If you search in old perl5- 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.

Mac OS doesn't have a malloc(), per se. It has NewPtr(), which is a dreadfully bad substitute, and the standard C library has one. I don't know how MSL's malloc() compares to MPW's.

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:

[snip]

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?

For trivial uses, yes, but perl's code is rather more involved. I revisited Matthias' Natty project -- he writes:

        #define vfork()  setjmp( *NattyVFork() )

NattyVFork() dynamically allocates and returns a jmp_buf* which is dereferenced and passed to setjmp(). One problem with this is that there's no way to return -1 on failure. I did this:

        #define vfork() ( SpawnVFork() ? -1 : setjmp(gVfork_jmp_buf) )

SpawnVFork() does almost the same thing that my old vfork() did, but returns 0 on success. Genie programs have private globals, so we can use a global for the jmp_buf. Execve() and _exit() save getpid(), call their respective kernel routines, and (for execve(), if successful) longjmp() with the saved pid. The standard library makes very weak guarantees about setjmp(), but fortunately Metrowerks delivers what we need.

We now have a working 'system' operator.

Josh

--
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