mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 22:11:12 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			300 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			300 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| Unit FreeBSD;
 | |
| {
 | |
|    This file is part of the Free Pascal run time library.
 | |
|    (c) 2005 by Marco van de Voort
 | |
|    member of the Free Pascal development team.
 | |
|    based on the sendfile conversion of Ales Katona 30.01.2006
 | |
| 
 | |
|    See the file COPYING.FPC, included in this distribution,
 | |
|    for details about the copyright.
 | |
| 
 | |
|    Unit for FreeBSD specific calls. Calls may move to "BSD" unit in time,
 | |
|    if turns out that more BSDs include them. 
 | |
|    
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY;without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | |
| }
 | |
| 
 | |
| {$IFDEF FPC}
 | |
|   {$PACKRECORDS C}
 | |
|   {$inline on}
 | |
|   {$Macro On}
 | |
|   {$ifdef FPC_USE_LIBC}
 | |
|      {$define extdecl:=cdecl; external 'c'}
 | |
|   {$else}
 | |
|      {$define extdecl:=inline}
 | |
|   {$endif}
 | |
| {$ENDIF}
 | |
|               
 | |
| interface
 | |
| 
 | |
| uses
 | |
|   BaseUnix;
 | |
| 
 | |
| const
 | |
|   SF_NODISKIO = $00000001;  // don't wait for disk IO, similar to non-blocking socket setting
 | |
|   
 | |
|   // kernel threads
 | |
| 
 | |
|   KSE_VER_0        = 0;
 | |
|   KSE_VERSION      = KSE_VER_0;
 | |
| 
 | |
|   {* These flags are kept in km_flags *}
 | |
|   KMF_NOUPCALL      = $01;
 | |
|   KMF_NOCOMPLETED   = $02;
 | |
|   KMF_DONE          = $04;
 | |
|   KMF_BOUND         = $08;
 | |
|   KMF_WAITSIGEVENT  = $10;
 | |
| 
 | |
|   {* These flags are kept in tm_flags *}
 | |
|   TMF_NOUPCALL      = $01;
 | |
| 
 | |
|   {* These flags are kept in tm_dlfags *}
 | |
|   TMDF_SSTEP        = $01;
 | |
|   TMDF_SUSPEND      = $02;
 | |
| 
 | |
|   {* Flags for kse_switchin *}
 | |
|   KSE_SWITCHIN_SETTMBX = $01;
 | |
| 
 | |
|   {* Commands for kse_thr_interrupt *}
 | |
|   KSE_INTR_INTERRUPT   = 1;
 | |
|   KSE_INTR_RESTART     = 2;
 | |
|   KSE_INTR_SENDSIG     = 3;
 | |
|   KSE_INTR_SIGEXIT     = 4;
 | |
|   KSE_INTR_DBSUSPEND   = 5;
 | |
|   KSE_INTR_EXECVE      = 6;
 | |
|   
 | |
| {$i ucontexth.inc} // required for kse threads
 | |
| 
 | |
| Type  
 | |
|   SF_HDTR = record
 | |
|     headers: PIOVec;        {* pointer to an array of header struct iovec's *}
 | |
|     hdr_cnt: cint;          {* number of header iovec's *}
 | |
|     trailers: PIOVec;       {* pointer to an array of trailer struct iovec's *}
 | |
|     trl_cnt: cint;          {* number of trailer iovec's *}
 | |
|   end;
 | |
|   TSF_HDTR = SF_HDTR;
 | |
|   PSF_HDTR = ^TSF_HDTR;
 | |
|   
 | |
|   kld_file_stat = record
 | |
|     Version: cInt;            {* set to sizeof(linker_file_stat) *}
 | |
|     Name: array[0..MAXPATHLEN-1] of Char;
 | |
|     Refs: cInt;
 | |
|     ID: cInt;
 | |
|     Address: pChar;           {* load address *}
 | |
|     Size: size_t;             {* size in bytes *}
 | |
|   end;
 | |
|   tkld_file_stat = kld_file_stat;
 | |
|   pkld_file_stat = ^kld_file_stat;
 | |
|   TKldFileStat = kld_file_stat;
 | |
|   PKldFileStat = ^kld_file_stat;
 | |
|   
 | |
|   kld_sym_lookup = record
 | |
|     Version: cInt;            {* sizeof(struct kld_sym_lookup) *}
 | |
|     SymName: pChar;           {* Symbol name we are looking up *}
 | |
|     SymValue: culong;
 | |
|     SymSize: size_t;
 | |
|   end;
 | |
|   tkld_sym_lookup = kld_sym_lookup;
 | |
|   pkld_sym_lookup = ^kld_sym_lookup;
 | |
|   TKldSymLookup = kld_sym_lookup;
 | |
|   PKldSymLookup = ^kld_sym_lookup;
 | |
|   
 | |
|   // kernel threads
 | |
| 
 | |
|   pkse_mailbox = ^kse_mailbox;
 | |
|   
 | |
|   pkse_func_t = ^kse_func_t;
 | |
|   kse_func_t = procedure(mbx: pkse_mailbox);
 | |
|   TKseFunc = kse_func_t;
 | |
|   PKseFunc = pkse_func_t;
 | |
|   
 | |
|   {*
 | |
|    * Thread mailbox.
 | |
|    *
 | |
|    * This describes a user thread to the kernel scheduler.
 | |
|    *}
 | |
|   pkse_thr_mailbox = ^kse_thr_mailbox;
 | |
|   kse_thr_mailbox = record
 | |
|     tm_context: ucontext_t;	  {* User and machine context *}
 | |
|     tm_flags: cuint32;            {* Thread flags *}
 | |
|     tm_next: pkse_thr_mailbox;    {* Next thread in list *}
 | |
|     tm_udata: Pointer;            {* For use by the UTS *}
 | |
|     tm_uticks: cuint32;           {* Time in userland *}
 | |
|     tm_sticks: cuint32;           {* Time in kernel *}
 | |
|     tm_syncsig: siginfo_t;
 | |
|     tm_dflags: cuint32;           {* Debug flags *}
 | |
|     tm_lwp: lwpid_t;              {* kernel thread UTS runs on *}
 | |
|     __spare__: array [0..5] of cuint32;
 | |
|   end;
 | |
|   TKseThrMailBox = kse_thr_mailbox;
 | |
|   PKseThrMailBox = pkse_thr_mailbox;
 | |
| 
 | |
|   
 | |
|   {*
 | |
|    * KSE mailbox.
 | |
|    *
 | |
|    * Communication path between the UTS and the kernel scheduler specific to
 | |
|    * a single KSE.
 | |
|    *}
 | |
|    
 | |
|   kse_mailbox = record
 | |
|     km_version: cuint32;             {* Mailbox version *}
 | |
|     km_curthread: pkse_thr_mailbox;  {* Currently running thread *}
 | |
|     km_completed: pkse_thr_mailbox;  {* Threads back from kernel *}
 | |
|     km_sigscaught: sigset_t;	     {* Caught signals *}
 | |
|     km_flags: cuint32;               {* Mailbox flags *}
 | |
|     km_func: pkse_func_t;            {* UTS function *}
 | |
|     km_stack: stack_t;               {* UTS stack *}
 | |
|     km_udata: Pointer;               {* For use by the UTS *}
 | |
|     km_timeofday: TTimeSpec;         {* Time of day *}
 | |
|     km_quantum: cuint32;             {* Upcall quantum in msecs *}
 | |
|     km_lwp: lwpid_t;                 {* kernel thread UTS runs on *}
 | |
|     __spare2__: array[0..6] of cuint32
 | |
|   end;
 | |
|   TKseMailBox = kse_mailbox;
 | |
|   PKseMailBox = pkse_mailbox;
 | |
| 
 | |
| 
 | |
|   function sendfile(fd: cint; s: cint; Offset: TOff; nBytes: TSize;
 | |
|                       HDTR: PSF_HDTR; sBytes: POff; Flags: cint): cint; extdecl;
 | |
|                       
 | |
|   // Kernel modules support
 | |
|                     
 | |
|   function kldload(FileName: pChar): cInt; extdecl;
 | |
| 
 | |
|   function kldunload(fileid: cInt): cInt; extdecl;
 | |
| 
 | |
|   function kldfind(FileName: pChar): cInt; extdecl;
 | |
| 
 | |
|   function kldnext(fileid: cInt): cInt; extdecl;
 | |
| 
 | |
|   function kldstat(fileid: cInt; kld_file_stat: pKldFileStat): cInt; extdecl;
 | |
| 
 | |
|   function kldfirstmod(fileid: cInt): cInt; extdecl;
 | |
| 
 | |
|   function kldsym(fileid: cInt; command: cInt; data: PKldSymLookup): cInt; extdecl;
 | |
|   
 | |
|   // kernel threads support
 | |
|   
 | |
|   function kse_exit: cInt; extdecl;
 | |
|   function kse_wakeup(mbx: PKseMailBox): cInt; extdecl;
 | |
|   function kse_create(mbx: PKseMailBox; newgroup: cInt): cInt; extdecl;
 | |
|   function kse_thr_interrupt(tmbx: PKseThrMailBox; cmd: cInt; data: cLong): cInt; extdecl;
 | |
|   function kse_release(timeout: PTimeSpec): cInt; extdecl;
 | |
|   function kse_switchin(tmbx: PKseThrMailBox; flags: cInt): cInt; extdecl;
 | |
| 
 | |
| Const
 | |
|  MAP_FILE         = $0000;  { map from file (default) }
 | |
|  MAP_ANON         = $1000;  { allocated from memory, swap space }
 | |
|    
 | |
|  MAP_RENAME       = $0020; { Sun: rename private pages to file }
 | |
|  MAP_NORESERVE    = $0040; { Sun: don't reserve needed swap area }
 | |
|  //  MAP_INHERIT      = $0080; { region is retained after exec. not anymore in 5.x? }
 | |
|  //  MAP_NOEXTEND     = $0100; { for MAP_FILE, don't change file size. not anymore in 5.x? }
 | |
|  MAP_HASSEMAPHORE = $0200; { region may contain semaphores }
 | |
|  MAP_STACK        = $0400; { region grows down, like a stack }
 | |
|  MAP_NOSYNC       = $0800; { page to but do not sync underlying file}
 | |
|  MAP_NOCORE       = $20000;{ dont include these pages in a coredump}
 | |
| 
 | |
| implementation
 | |
| 
 | |
| Uses
 | |
| {$ifndef FPC_USE_LIBC}  SysCall; {$else} InitC; {$endif}
 | |
| 
 | |
| {$IFNDEF FPC_USE_LIBC}
 | |
| 
 | |
| function SendFile(fd: cint; s: cint; Offset: TOff; nBytes: TSize;
 | |
|                   HDTR: PSF_HDTR; sBytes: POff; Flags: cint): cint;
 | |
| begin
 | |
|   SendFile:=Do_Syscall(syscall_nr_sendfile, fd, s,
 | |
|  {$IFNDEF CPU64} 
 | |
|    {$IFDEF LITTLE_ENDIAN} // little endian is lo - hi
 | |
|       Lo(Offset), Hi(Offset), 
 | |
|    {$ELSE}  	          // big endian is hi - lo
 | |
|       Hi(Offset), Lo(Offset), 
 | |
|    {$ENDIF}
 | |
|  {$ELSE}  // 64-bit doesn't care. 
 | |
|     TSysParam(Offset),
 | |
|  {$ENDIF}
 | |
|     nBytes, TSysParam(HDTR), TSysParam(sBytes), Flags);
 | |
| end;
 | |
| 
 | |
| // kernel modules
 | |
| 
 | |
| function kldload(FileName: pChar): cInt;
 | |
| begin
 | |
|   kldload:=do_sysCall(syscall_nr_kldload, TSysParam(FileName));
 | |
| end;
 | |
| 
 | |
| function kldunload(fileid: cInt): cInt;
 | |
| begin
 | |
|   kldunload:=do_sysCall(syscall_nr_kldunload, TSysParam(fileid));
 | |
| end;
 | |
| 
 | |
| function kldfind(FileName: pChar): cInt;
 | |
| begin
 | |
|   kldfind:=do_sysCall(syscall_nr_kldfind, TSysParam(FileName));
 | |
| end;
 | |
| 
 | |
| function kldnext(fileid: cInt): cInt;
 | |
| begin
 | |
|   kldnext:=do_sysCall(syscall_nr_kldnext, TSysParam(fileid));
 | |
| end;
 | |
| 
 | |
| function kldstat(fileid: cInt; kld_file_stat: pKldFileStat): cInt;
 | |
| begin
 | |
|   kldstat:=do_sysCall(syscall_nr_kldstat, TSysParam(fileid),
 | |
|                                           TSysParam(kld_file_stat));
 | |
| end;
 | |
| 
 | |
| function kldfirstmod(fileid: cInt): cInt;
 | |
| begin
 | |
|   kldfirstmod:=do_sysCall(syscall_nr_kldfirstmod, TSysParam(fileid));
 | |
| end;
 | |
| 
 | |
| function kldsym(fileid: cInt; command: cInt; data: PKldSymLookup): cInt;
 | |
| begin
 | |
|   kldsym:=do_sysCall(syscall_nr_kldsym, TSysParam(fileid), TSysParam(command),
 | |
|                      TSysParam(data));
 | |
| end;
 | |
| 
 | |
| // kernel threads
 | |
| 
 | |
| function kse_exit: cInt;
 | |
| begin
 | |
|   kse_exit:=do_sysCall(TSysParam(syscall_nr_kse_exit));
 | |
| end;
 | |
| 
 | |
| function kse_wakeup(mbx: PKseMailBox): cInt;
 | |
| begin
 | |
|   kse_wakeup:=do_sysCall(syscall_nr_kse_wakeup, TSysParam(mbx));
 | |
| end;
 | |
| 
 | |
| function kse_create(mbx: PKseMailBox; newgroup: cInt): cInt;
 | |
| begin
 | |
|   kse_create:=do_sysCall(syscall_nr_kse_create, TSysParam(mbx),
 | |
|                          TSysParam(newgroup));
 | |
| end;
 | |
| 
 | |
| function kse_thr_interrupt(tmbx: PKseThrMailBox; cmd: cInt; data: cLong): cInt;
 | |
| begin
 | |
|   kse_thr_interrupt:=do_SysCall(syscall_nr_kse_thr_interrupt, TSysParam(tmbx),
 | |
|                                TSysParam(cmd), TSysParam(data));
 | |
| end;
 | |
| 
 | |
| function kse_release(timeout: PTimeSpec): cInt;
 | |
| begin
 | |
|   kse_release:=do_SysCall(syscall_nr_kse_release, TSysParam(timeout));
 | |
| end;
 | |
| 
 | |
| function kse_switchin(tmbx: PKseThrMailBox; flags: cInt): cInt;
 | |
| begin
 | |
|   kse_switchin:=do_SysCall(syscall_nr_kse_switchin, TSysParam(tmbx), TSysParam(flags));
 | |
| end;
 | |
| 
 | |
| {$ENDIF}
 | |
| 
 | |
| end.
 | 
