spawn.mx raw

   1  //go:build linux
   2  
   3  package runtime
   4  
   5  import "unsafe"
   6  
   7  // spawnDomain creates a new isolated domain by forking the current process.
   8  // The child process executes fn(args) with its own cooperative scheduler.
   9  // Communication between parent and child happens over a Unix socketpair.
  10  func spawnDomain(fn uintptr, args unsafe.Pointer) {
  11  	// Create a socketpair for IPC between parent and child.
  12  	var fds [2]int32
  13  	r := moxie_socketpair(1, 1, 0, unsafe.Pointer(&fds[0])) // AF_UNIX=1, SOCK_STREAM=1
  14  	if r < 0 {
  15  		runtimePanic("spawn: socketpair failed")
  16  	}
  17  
  18  	pid := moxie_fork()
  19  	if pid < 0 {
  20  		runtimePanic("spawn: fork failed")
  21  	}
  22  
  23  	if pid == 0 {
  24  		// Child process — run the spawned function directly.
  25  		moxie_close(fds[0]) // close parent's end
  26  
  27  		// Call the function directly. With no scheduler, the child
  28  		// domain is single-threaded and runs to completion.
  29  		spawnCall(fn, args)
  30  
  31  		// Exit child process.
  32  		exit(0)
  33  	}
  34  
  35  	// Parent process.
  36  	moxie_close(fds[1]) // close child's end
  37  
  38  	domainRegister(pid, fds[0])
  39  }
  40  
  41  // spawnCall invokes fn(args) directly. The function pointer fn
  42  // is a $gowrapper that takes a single pointer argument.
  43  func spawnCall(fn uintptr, args unsafe.Pointer) {
  44  	// The function pointer is a wrapper generated by the compiler
  45  	// that unpacks args and calls the real function.
  46  	type funcType func(unsafe.Pointer)
  47  	(*(*funcType)(unsafe.Pointer(&fn)))(args)
  48  }
  49  
  50  // C functions defined in spawn_unix.c
  51  
  52  //export moxie_fork
  53  func moxie_fork() int32
  54  
  55  //export moxie_close
  56  func moxie_close(fd int32) int32
  57  
  58  //export moxie_socketpair
  59  func moxie_socketpair(domain, typ, protocol int32, fds unsafe.Pointer) int32
  60