PreviousUpNext

15.4.1187  src/lib/std/src/psx/posix-process.pkg

## posix-process.pkg
#
# Posix-specific process support.
# This is a subpackage of the POSIX 1003.1 based
# 'Posix' package
#
#     src/lib/std/src/psx/posixlib.pkg
#
#
# An alternative higher-level unix 'spawn' interface
# is defined and implemented (respectively) in:
#
#     src/lib/std/src/posix/spawn--premicrothread.api
#     src/lib/std/src/posix/spawn--premicrothread.pkg
#
#
# A portable (cross-platform) process interface
# is defined and implemented (respectively) in:
#
#     src/lib/std/src/winix/winix-process--premicrothread.api
#     src/lib/std/src/posix/winix-process--premicrothread.pkg

# Compiled by:
#     src/lib/std/src/standard-core.sublib




###             "I wanted to separate data from programs,
###              because data and instructions are very different."
###
###                                      -- Ken Thompson 



###     "The Hobbits named it the Shire, as the region
###      of the authority of their Thain, and a district
###      of well-ordered business; and there in that
###      pleasant corner of the world they plied their
###      well-ordered business of living, and they heeded
###      less and less the world outside where dark things
###      moved, until they came to think that peace and
###      plenty were the rule in Middle-earth and the right
###      of all sensible folk.
###
###     "They forgot or ignored what little they had
###      ever known of the Guardians, and of the labours of
###      those that made possible the long peace of the Shire.
###      They were, in fact, sheltered, but they had ceased
###      to remember it."
###
###                               -- J R R Tolkien


stipulate
    package hi  =  host_int;                                                                    # host_int                              is from   src/lib/std/src/psx/host-int.pkg
    package hu  =  host_unt_guts;                                                               # host_unt_guts                         is from   src/lib/std/src/bind-sysword-32.pkg
    package u1b =  one_byte_unt_guts;                                                           # one_byte_unt_guts                     is from   src/lib/std/src/one-byte-unt-guts.pkg
    package tim =  time_guts;                                                                   # time_guts                             is from   src/lib/std/src/time-guts.pkg
    package ig  =  int_guts;                                                                    # int_guts                              is from   src/lib/std/src/int-guts.pkg
    package sig =  interprocess_signals;                                                        # interprocess_signals                  is from   src/lib/std/src/nj/interprocess-signals.pkg
    package ci  =  mythryl_callable_c_library_interface;                                        # mythryl_callable_c_library_interface  is from   src/lib/std/src/unsafe/mythryl-callable-c-library-interface.pkg
    #
    fun cfun  fun_name  =  ci::find_c_function   { lib_name => "posix_process", fun_name };     # "posix_process"                       def in    src/c/lib/posix-process/cfun-list.h
    fun cfun' fun_name  =  ci::find_c_function'' { lib_name => "posix_process", fun_name };     # "posix_process"                       def in    src/c/lib/posix-process/cfun-list.h
        #
        #
        ###############################################################
        # The functions in this package -- fork(), exec() etc -- are
        # mostly not the sort where latency is a concern or where
        # execution in another posix thread  is appropriate.
        #
        # Consequently I've not taken the time and effort to switch them
        # over from using find_c_function() to using find_c_function'().
        #
        # The exceptions are  sysconf, osval, kill and waitpid.
        # These I have switched over to find_c_function'.
        #
        # (waitpid might be a mistake;  I'm presuming it is only used
        # to harvest the status of children in response to SIGCHLF.)
        #
        #                                  -- 2012-04-21 CrT

        Signal = sig::Signal;

herein

    package posix_process {                                                                     # Posix_Process                         is from   src/lib/std/src/psx/posix-process.api
        #
        Unt    = hu::Unt;
        Sy_Int = hi::Int;

        Process_Id =  PID Sy_Int;


        fun pid_to_unt (PID i)
            =
            hu::from_int i;


        fun unt_to_pid w
            =
            PID (hu::to_int w);




        (cfun' "osval")                                                                                 # osval                         def in    src/c/lib/posix-process/osval.c
            ->
            (      osval__syscall:    String -> Sy_Int,
                   osval__ref,
              set__osval__ref
            );

        fun osval string
            =
            *osval__ref  string;



        w_osval =  hu::from_int o osval;


        stipulate
            fun cfun'  fun_name
                =
                ci::find_c_function'' { lib_name => "posix_process_environment", fun_name };            # "posix_process_environment"   def in    src/c/lib/posix-process-environment/cfun-list.h
        herein
            (cfun' "sysconf")                                                                           # sysconf                       def in    src/c/lib/posix-process-environment/sysconf.c
                ->
                (      sysconf__syscall:    String -> hu::Unt,
                       sysconf__ref,
                  set__sysconf__ref
                );

            fun sysconf  string
                =
                *sysconf__ref  string;
        end;

        fork' =   cfun "fork" :   Void -> Sy_Int;                                                       # fork                          def in    src/c/lib/posix-process/fork.c


        fun fork ()
            =
            case (fork' ())
                #
                0         =>  NULL;
                child_pid =>  THE (PID child_pid);
            esac;
            #
            # This is essentially the unix-level fork().
            # For a higher-level fork() see fork_process() in
            #
            #     src/lib/std/src/posix/spawn--premicrothread.api
            #     src/lib/std/src/posix/spawn--premicrothread.pkg


        fun exec  (x: (String, List( String )) ) :                 X =    cfun "exec"  x;               # exec                          def in    src/c/lib/posix-process/exec.c
        fun exece (x: (String, List( String ), List( String )) ) : X =    cfun "exece" x;               # exece                         def in    src/c/lib/posix-process/exece.c
        fun execp (x: (String, List( String )) ):                  X =    cfun "execp" x;               # execp                         def in    src/c/lib/posix-process/execp.c

        Waitpid_Arg
          #
          = W_ANY_CHILD 
          | W_CHILD  Process_Id 
          | W_GROUP  Process_Id
          | W_SAME_GROUP
          ;

        Killpid_Arg
          #
          = K_PROC  Process_Id
          | K_GROUP Process_Id
          | K_SAME_GROUP
          ;

        Exit_Status
          #
          = W_EXITED
          | W_EXITSTATUS  u1b::Unt
          | W_SIGNALED  Signal
          | W_STOPPED   Signal
          ;

        #  (pid', status, status_val) = waitpid' (pid, options)  

        (cfun' "waitpid")                                                                               # waitpid                       def in    src/c/lib/posix-process/waitpid.c
            ->
            (      waitpid__syscall:    (hi::Int, Unt) -> (hi::Int, hi::Int, hi::Int),
                   waitpid__ref,
              set__waitpid__ref
            );


        fun arg_to_int W_ANY_CHILD         => -1;
            arg_to_int (W_CHILD (PID pid)) =>  pid;
            arg_to_int (W_SAME_GROUP)      =>  0;
            arg_to_int (W_GROUP (PID pid)) => -pid;
        end;

        # The exit status from wait is encoded as a pair of integers.
        # If the first integer is 0, the child exited normally, and
        # the second integer gives its exit value.
        # If the first integer is 1, the child exited due to an uncaught
        # signal, and the second integer gives the signal value.
        # Otherwise, the child is stopped and the second integer 
        # gives the signal value that caused the child to stop.

        fun make_exit_status (0, 0) =>  W_EXITED;
            make_exit_status (0, v) =>  W_EXITSTATUS (u1b::from_int v);
            make_exit_status (1, s) =>  W_SIGNALED   (sig::int_to_signal s);
            make_exit_status (_, s) =>  W_STOPPED    (sig::int_to_signal s);
        end;

        package w {
            #
            stipulate
                package w0 = bit_flags_g ();
            herein
                include package   w0;
            end;

            untraced =  from_unt (   {   *sysconf__ref "JOB_CONTROL";
                                         w_osval "WUNTRACED";
                                     }
                                     except _ = 0u0
                                 );
        };


        fun waitpid (arg, flags)
            =
            {   (*waitpid__ref (arg_to_int arg, w::to_unt (w::flags flags)))
                    ->
                    (pid, status, exit_value);

                (PID pid,  make_exit_status (status, exit_value));
            };

        stipulate
            wnohang =  w::from_unt (w_osval "WNOHANG");
        herein
            fun waitpid_without_blocking (arg, flags)
                =
                case (*waitpid__ref (arg_to_int arg, w::to_unt (w::flags (wnohang ! flags))))
                    #
                    (0, _, _)                 =>  NULL;
                    (pid, status, exit_value) =>  THE (PID pid, make_exit_status (status, exit_value));
                esac;
        end;

        fun wait ()
            =
            waitpid (W_ANY_CHILD,[]);


        fun exit (x: u1b::Unt) : X
            =
            {
                cfun "exit" x;                                                  # exit          def in    src/c/lib/posix-process/exit.c
            };

        (cfun' "kill")                                                          # kill          def in    src/c/lib/posix-process/kill.c
            ->
            (      kill__syscall:    (Sy_Int, Sy_Int) -> Void,
                   kill__ref,
              set__kill__ref
            );


        fun kill (K_PROC (PID pid),  s) =>  *kill__ref (pid,  sig::signal_to_int s);            # "Kill me to-morrow; let me live to-night!"    -- William Shakespeare, "Othello"
            kill (K_SAME_GROUP,      s) =>  *kill__ref (-1,   sig::signal_to_int s);
            kill (K_GROUP (PID pid), s) =>  *kill__ref (-pid, sig::signal_to_int s);
        end;


        stipulate
            fun wrap f t
                =
                tim::from_seconds (ig::to_multiword_int (f (ig::from_multiword_int (tim::to_seconds t))));

            alarm' =   cfun "alarm" :   Int -> Int;
            sleep' =   cfun "sleep" :   Int -> Int;                             # sleep         def in    src/c/lib/posix-process/sleep.c
                #
                # From the manpage:
                #
                #    BUGS
                #           sleep()  may be implemented using SIGALRM; mixing calls to alarm(2) and
                #           sleep() is a bad idea.

        herein

            alarm =  wrap alarm';
            sleep =  wrap sleep';
                #
                # Note that you can sleep with sub-second resolution
                # via winix__premicrothread::process::sleep or winix__premicrothread::io::poll.

        end;

        pause =   cfun "pause":  Void -> Void;                                  # pause         def in    src/c/lib/posix-process/pause.c


    }; #  package posix_process 
end;



Comments and suggestions to: bugs@mythryl.org

PreviousUpNext