So far, two ways of loading and running actors have been described: either the inclusion of the actor as part of the system image, or the usage of the arun mechanism. The ChorusOS operating system also enables an actor to dynamically spawn another actor from a binary file. This spawned actor may be either a supervisor or a user actor. This service is similar to the exec() UNIX system call:
#include <am/afexec.h> int afexecve (const char* path, KnCap* actorCap, const AcParam* param, char* const* argv, char* const* envp);
This service creates a new actor whose capability is returned by the system at the location pointed to by the actorCap argument. The actor created will execute the binary file stored in the file named path. The main thread of this actor will run the main routine of the program. This thread will have the same scheduling attributes and stack size as an actor loaded using the arun mechanism.
argv and envp are pointers to the array of arguments and environments that will be received by the newly created actor.
The afexec() service comes in several variants, similar to the UNIX exec() call variants. When successful, all afexec() routines return the actor identifier of the newly created actor. Otherwise, they return -1, and the error code is returned in the errno variable.
Most of the time, application writers will not need to use the afexec() service. They will use either the arun facility or include the actor as part of the system image. However, for convenience, some examples within this document do use this service.
Below is an example of use of the afexecve() service call.
A user actor loaded by arun spawns another user actor, running the same executable file.
They both print a trace and terminate.
The first actor is distinguished from the one it spawns by the number of arguments: the first actor has no argument, but spawns the second actor passing it a string as its first argument. This string is printed by the spawned actor.
The first actor prints the actor identifier of the spawned actor.
#include <stdio.h> #include <errno.h> #include <am/afexec.h> AcParam param; char* spawnedArgs[3]; char* tagPtr = "Welcome newly created actor!"; main(int argc, char** argv, char**envp) { KnCap spawnedCap; int res; if (argc == 1) { /* * This is the first actor (or spawning actor): * Binary file used to load this actor is passed * by "arun" as argv[0], * * Set an argument in order to enable the second * actor to know it is the second one. */ param.acFlags = AFX_USER_SPACE; spawnedArgs[0] = argv[0]; spawnedArgs[1] = tagPtr; spawnedArgs[2] = NULL; /* * Other fields are implicitly set to NULL, as * param is allocated within the bss segment of * the program. */ res = afexecve(argv[0], &spawnedCap, ¶m , spawnedArgs, envp); if (res == -1) { printf("Cannot spawn second actor, error %d\n", errno); exit(1); } printf("I succeeded creating actor whose aid is %d\n", res); } else { /* * This is the spawned actor: * Check the number of args, * Print args, * Exit */ if ((argc == 2) && (strcmp(tagPtr, argv[1]) == 0)) { /* * This is really the spawned actor. */ printf("My spawning actor passed me this argument: %s\n", argv[1]); } else { printf("You ran %s with an argument, you should not!\n", argv[0]); exit(1); } } exit(0); }
This example assumes that argv[0] is valid, and the actor is linked with the ~lib/classix/libcx.a library, since the library is common to both user and supervisor actors. Referencing argv[0] without checking if argc is greater than zero can cause the actor to make an exception and be deleted.
A null AcParam argument instructs the system to use default values for afexec() calls.
The acFlags field indicates, among other possibilities, whether the actor should be created as a user actor (when the flag is set to AFX_USER_SPACE), or as a supervisor actor (when the flag is set to AFX_SUPERVISOR_SPACE). These values are mutually exclusive: one and only one of the two values may be set. In addition, the user must make sure that the value of the flag is consistent with the binary file used to load the actor. Trying to create a supervisor actor with a binary file prepared for a user actor, by linking with the user libraries, will result in an error.
The AFX_ANY_SPACE option can be passed to instruct the operating system to retrieve the privilege of the binary file and create an actor with the same privilege.
Unused fields of the AcParam argument must be set to 0.