From 5e694a801e52b64c879974b51e7ff7b7e953e61c Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sat, 21 Jan 2006 20:19:19 +0000 Subject: [PATCH] * use vfork instead of fork for popen and one variant of executeprocess if USE_VFORK is defined (currently only if both BSD and FPC_USE_LIBC are defined). Speeds up the compilation of the compiler under Darwin by 20-25% (the larger the project, the bigger the speedup). git-svn-id: trunk@2317 - --- rtl/unix/oscdeclh.inc | 1 + rtl/unix/sysutils.pp | 8 +++ rtl/unix/unix.pp | 162 +++++++++++++++++++++++++++++------------- 3 files changed, 120 insertions(+), 51 deletions(-) diff --git a/rtl/unix/oscdeclh.inc b/rtl/unix/oscdeclh.inc index d257e1d9f4..9d5e27686d 100644 --- a/rtl/unix/oscdeclh.inc +++ b/rtl/unix/oscdeclh.inc @@ -33,6 +33,7 @@ Type TGrpArr = Array [0..0] of TGid; { C style array workarounds} function FpDup2 (oldd:cint;newd:cint):cint; cdecl; external clib name 'dup2'; function FpExecve (path : pchar; argv : ppchar; envp: ppchar): cint; cdecl; external clib name 'execve'; function FpFork : TPid; cdecl; external clib name 'fork'; + function FpvFork : TPid; cdecl; external clib name 'vfork'; function FpFtruncate(fd : cint; flength : TOff): cint; cdecl; external clib name 'ftruncate'; function FpLseek (fd : cint; offset : TOff; whence : cint): TOff; cdecl; external clib name 'lseek'; function FpMkdir (path : pchar; mode: TMode):cint; cdecl; external clib name 'mkdir'; diff --git a/rtl/unix/sysutils.pp b/rtl/unix/sysutils.pp index bec9bcde0c..81c6a4bc02 100644 --- a/rtl/unix/sysutils.pp +++ b/rtl/unix/sysutils.pp @@ -20,6 +20,10 @@ interface { force ansistrings } {$H+} +{$if defined(BSD) and defined(FPC_USE_LIBC)} +{$define USE_VFORK} +{$endif} + {$DEFINE OS_FILESETDATEBYNAME} {$DEFINE HAS_SLEEP} {$DEFINE HAS_OSERROR} @@ -984,7 +988,11 @@ Begin if ComLine <> '' then CommandLine := Commandline + ' ' + ComLine; {$endif} + {$ifdef USE_VFORK} + pid:=fpvFork; + {$else USE_VFORK} pid:=fpFork; + {$endif USE_VFORK} if pid=0 then begin {The child does the actual exec, and then exits} diff --git a/rtl/unix/unix.pp b/rtl/unix/unix.pp index 829c87d080..06e972d6c8 100644 --- a/rtl/unix/unix.pp +++ b/rtl/unix/unix.pp @@ -17,6 +17,10 @@ Interface Uses BaseUnix,UnixType; +{$if defined(BSD) and defined(FPC_USE_LIBC)} +{$define USE_VFORK} +{$endif} + {$i aliasptp.inc} { Get Types and Constants only exported in this unit } @@ -128,8 +132,8 @@ Function AssignPipe (var pipe_in,pipe_out:text):cint; Function AssignPipe (var pipe_in,pipe_out:file):cint; //Function PClose (Var F:text) : cint; //Function PClose (Var F:file) : cint; -Function POpen (var F:text;const Prog:String;rw:char):cint; -Function POpen (var F:file;const Prog:String;rw:char):cint; +Function POpen (var F:text;const Prog:Ansistring;rw:char):cint; +Function POpen (var F:file;const Prog:Ansistring;rw:char):cint; Function AssignStream(Var StreamIn,Streamout:text;Const Prog:ansiString;const args : array of ansistring) : cint; Function AssignStream(Var StreamIn,Streamout,streamerr:text;Const Prog:ansiString;const args : array of ansistring) : cint; @@ -736,7 +740,7 @@ begin end; -function POpen(var F:text;const Prog:String;rw:char):cint; +Function POpen(var F:text;const Prog:Ansistring;rw:char):cint; { Starts the program in 'Prog' and makes it's input or out put the other end of a pipe. If rw is 'w' or 'W', then whatever is written to @@ -747,11 +751,12 @@ function POpen(var F:text;const Prog:String;rw:char):cint; var pipi, pipo : text; - pid : pid_t; + pid : cint; pl : ^cint; -{$ifndef FPC_USE_FPEXEC} - pp : ppchar; -{$endif not FPC_USE_FPEXEC} +{$if not defined(FPC_USE_FPEXEC) or defined(USE_VFORK)} + pp : array[0..3] of pchar; + temp : string[255]; +{$endif not FPC_USE_FPEXEC or USE_VFORK} ret : cint; begin rw:=upcase(rw); @@ -760,9 +765,14 @@ begin FpSetErrno(ESysEnoent); exit(-1); end; - if AssignPipe(pipi,pipo)=-1 Then - Exit(-1); - pid:=fpfork; // vfork in FreeBSD. + ret:=AssignPipe(pipi,pipo); + if ret=-1 then + exit(-1); +{$ifdef USE_VFORK} + pid:=fpvfork; +{$else USE_VFORK} + pid:=fpfork; +{$endif USE_VFORK} if pid=-1 then begin close(pipi); @@ -774,27 +784,53 @@ begin { We're in the child } if rw='W' then begin + if (textrec(pipi).handle <> stdinputhandle) then + begin + ret:=fpdup2(pipi,input); +{$ifdef USE_VFORK} + fpclose(textrec(pipi).handle); +{$else USE_VFORK} + close(pipi); +{$endif USE_VFORK} + end; +{$ifdef USE_VFORK} + fpclose(textrec(pipo).handle); +{$else USE_VFORK} close(pipo); - ret:=fpdup2(pipi,input); - close(pipi); +{$endif USE_VFORK} if ret=-1 then - halt(127); + fpexit(127); end else begin +{$ifdef USE_VFORK} + fpclose(textrec(pipi).handle); +{$else USE_VFORK} close(pipi); - ret:=fpdup2(pipo,output); - close(pipo); - if ret=-1 then - halt(127); +{$endif USE_VFORK} + if (textrec(pipo).handle <> stdoutputhandle) then + begin + ret:=fpdup2(pipo,output); +{$ifdef USE_VFORK} + fpclose(textrec(pipo).handle); +{$else USE_VFORK} + close(pipo); +{$endif USE_VFORK} + end; + if ret=1 then + fpexit(127); end; - {$ifdef FPC_USE_FPEXEC} - fpexecl('/bin/sh',['-c',Prog]); + {$if defined(FPC_USE_FPEXEC) and not defined(USE_VFORK)} + fpexecl(pchar('/bin/sh'),['-c',Prog]); {$else} - pp:=createshellargv(prog); - fpExecve(pp^,pp,envp); + temp:='/bin/sh'#0'-c'#0; + pp[0]:=@temp[1]; + pp[1]:=@temp[9]; + pp[2]:=@prog[1]; + pp[3]:=Nil; + fpExecve('/bin/sh',@pp,envp); {$endif} - halt(127); + fpexit(127); end else begin @@ -803,23 +839,22 @@ begin begin close(pipi); f:=pipo; - textrec(f).bufptr:=@textrec(f).buffer; end else begin close(pipo); f:=pipi; - textrec(f).bufptr:=@textrec(f).buffer; end; + textrec(f).bufptr:=@textrec(f).buffer; {Save the process ID - needed when closing } pl:=@(textrec(f).userdata[2]); pl^:=pid; textrec(f).closefunc:=@PCloseText; end; - ret:=0; + POpen:=0; end; -Function POpen(var F:file;const Prog:String;rw:char):cint; +Function POpen(var F:file;const Prog:Ansistring;rw:char):cint; { Starts the program in 'Prog' and makes it's input or out put the other end of a pipe. If rw is 'w' or 'W', then whatever is written to @@ -832,10 +867,10 @@ var pipo : file; pid : cint; pl : ^cint; -{$ifndef FPC_USE_FPEXEC} - p,pp : ppchar; +{$if not defined(FPC_USE_FPEXEC) or defined(USE_VFORK)} + pp : array[0..3] of pchar; temp : string[255]; -{$endif not FPC_USE_FPEXEC} +{$endif not FPC_USE_FPEXEC or USE_VFORK} ret : cint; begin rw:=upcase(rw); @@ -847,7 +882,11 @@ begin ret:=AssignPipe(pipi,pipo); if ret=-1 then exit(-1); +{$ifdef USE_VFORK} + pid:=fpvfork; +{$else USE_VFORK} pid:=fpfork; +{$endif USE_VFORK} if pid=-1 then begin close(pipi); @@ -859,36 +898,53 @@ begin { We're in the child } if rw='W' then begin + if (filerec(pipi).handle <> stdinputhandle) then + begin + ret:=fpdup2(filerec(pipi).handle,stdinputhandle); +{$ifdef USE_VFORK} + fpclose(filerec(pipi).handle); +{$else USE_VFORK} + close(pipi); +{$endif USE_VFORK} + end; +{$ifdef USE_VFORK} + fpclose(filerec(pipo).handle); +{$else USE_VFORK} close(pipo); - ret:=fpdup2(filerec(pipi).handle,stdinputhandle); - close(pipi); +{$endif USE_VFORK} if ret=-1 then - halt(127); + fpexit(127); end else begin +{$ifdef USE_VFORK} + fpclose(filerec(pipi).handle); +{$else USE_VFORK} close(pipi); - ret:=fpdup2(filerec(pipo).handle,stdoutputhandle); - close(pipo); +{$endif USE_VFORK} + if (filerec(pipo).handle <> stdoutputhandle) then + begin + ret:=fpdup2(filerec(pipo).handle,stdoutputhandle); +{$ifdef USE_VFORK} + fpclose(filerec(pipo).handle); +{$else USE_VFORK} + close(pipo); +{$endif USE_VFORK} + end; if ret=1 then - halt(127); + fpexit(127); end; - {$ifdef FPC_USE_FPEXEC} - fpexecl('/bin/sh',['-c',Prog]); + {$if defined(FPC_USE_FPEXEC) and not defined(USE_VFORK)} + fpexecl(pchar('/bin/sh'),['-c',Prog]); {$else} - getmem(pp,sizeof(pchar)*4); - temp:='/bin/sh'#0'-c'#0+prog+#0; - p:=pp; - p^:=@temp[1]; - inc(p); - p^:=@temp[9]; - inc(p); - p^:=@temp[12]; - inc(p); - p^:=Nil; - fpExecve(ansistring('/bin/sh'),pp,envp); + temp:='/bin/sh'#0'-c'#0; + pp[0]:=@temp[1]; + pp[1]:=@temp[9]; + pp[2]:=@prog[1]; + pp[3]:=Nil; + fpExecve('/bin/sh',@pp,envp); {$endif} - halt(127); + fpexit(127); end else begin @@ -931,8 +987,12 @@ begin AssignStream:=-1; if AssignPipe(streamin,pipo)=-1 Then exit(-1); - if AssignPipe(pipi,streamout)=-1 Then // shouldn't this close streamin and pipo? - exit(-1); + if AssignPipe(pipi,streamout)=-1 Then + begin + close(streamin); + close(pipo); + exit(-1); + end; pid:=fpfork; if pid=-1 then begin