UNSAFE MODULE; IMPORT Ctypes, File, Unix, Text, M3toC, Uexec, Uuio, RTParams, Utime; IMPORT FilePosix, OSError; CONST readPort = 0; writePort = 1; TYPE Pipe = ARRAY [0..1] OF Ctypes.int; PROCEDURE LowPerfTool ClosePipe (READONLY p: Pipe) = BEGIN EVAL Unix.close (p[readPort]); EVAL Unix.close (p[writePort]); END ClosePipe; PROCEDUREStart (name: Text.T; VAR r, w: File.T): BOOLEAN = VAR toTool, fromTool: Pipe; oit: Utime.struct_itimerval; BEGIN (* open a pipe to send bytes to the performance tool *) IF Unix.pipe (toTool) = -1 THEN RETURN FALSE; END; (* open a pipe to get bytes from the performance tool *) IF Unix.pipe (fromTool) = -1 THEN ClosePipe (toTool); RETURN FALSE; END; (* disable the virtual timer used for thread preemption *) VAR nit: Utime.struct_itimerval; BEGIN nit.it_interval.tv_sec := 0; nit.it_interval.tv_usec := 0; nit.it_value.tv_sec := 0; nit.it_value.tv_usec := 0; IF Utime.setitimer (Utime.ITIMER_VIRTUAL, nit, oit) = -1 THEN ClosePipe (toTool); ClosePipe (fromTool); RETURN FALSE; END; END; (* Create the tool process *) CASE Unix.fork () OF | -1 => (* fork failed *) ClosePipe (fromTool); ClosePipe (toTool); RETURN FALSE; | 0 => (* in the child *) (* close the unused ends of the pipes *) EVAL Unix.close (toTool [writePort]); EVAL Unix.close (fromTool [readPort]); (* connect the useful ends to stdin and stdout *) IF toTool [readPort] # 0 THEN IF Unix.dup2 (toTool [readPort], 0) = -1 THEN RETURN FALSE; END; EVAL Unix.close (toTool [readPort]); END; IF fromTool [writePort] # 1 THEN IF Unix.dup2 (fromTool [writePort], 1) = -1 THEN RETURN FALSE; END; EVAL Unix.close (fromTool [writePort]); END; (* execute the perf tool *) VAR args: ARRAY [0..1] OF Ctypes.char_star; BEGIN args [0] := M3toC.SharedTtoS (name); args [1] := NIL; EVAL Uexec.execvp (args [0], ADR (args [0])); END; RETURN FALSE; ELSE (* in the parent, after the child has been forked *) (* disable the virtual timer used for thread preemption *) VAR nit: Utime.struct_itimerval; status := Utime.setitimer (Utime.ITIMER_VIRTUAL, oit, nit); BEGIN <* ASSERT status # -1 *> END; (* close the unused ends of the pipes *) EVAL Unix.close (toTool [readPort]); EVAL Unix.close (fromTool [writePort]); TRY (* update r and w *) r := FilePosix.New (fromTool [readPort], FilePosix.Read); w := FilePosix.New (toTool [writePort], FilePosix.Write); EXCEPT OSError.E => r := NIL; w := NIL; RETURN FALSE; END; END; (*CASE*) RETURN TRUE; END Start; PROCEDUREStartAndWait (name: Text.T; VAR r,w: File.T): BOOLEAN = VAR c: Ctypes.char; BEGIN IF NOT Start (name, r, w) THEN RETURN FALSE; END; EVAL Uuio.read (r.fd, ADR (c), 1); RETURN TRUE; END StartAndWait; PROCEDUREParamStart (param: Text.T; VAR r,w: File.T): BOOLEAN = VAR value := RTParams.Value (param); BEGIN IF value = NIL THEN RETURN FALSE; ELSIF Text.Length (value) = 0 THEN RETURN Start (param, r, w); ELSE RETURN Start (value, r, w); END; END ParamStart; PROCEDUREParamStartAndWait (param: Text.T; VAR r,w: File.T): BOOLEAN = VAR value := RTParams.Value (param); BEGIN IF value = NIL THEN RETURN FALSE; ELSIF Text.Length (value) = 0 THEN RETURN StartAndWait (param, r, w); ELSE RETURN StartAndWait (value, r, w); END; END ParamStartAndWait; BEGIN END LowPerfTool.