mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 04:39:28 +01:00 
			
		
		
		
	(mantis #17100) * also use a syscall to call modify_ldt when FPC_USE_LIBC is defined, because it's not exported as a function from libc git-svn-id: trunk@15838 -
		
			
				
	
	
		
			574 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			574 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
{
 | 
						|
   This file is part of the Free Pascal run time library.
 | 
						|
   Copyright (c) 1999-2000 by Michael Van Canneyt,
 | 
						|
   BSD parts (c) 2000 by Marco van de Voort
 | 
						|
   members of the Free Pascal development team.
 | 
						|
 | 
						|
   New linux unit. Linux only calls only. Will be renamed to linux.pp
 | 
						|
   when 1.0.x support is killed off.
 | 
						|
 | 
						|
   See the file COPYING.FPC, included in this distribution,
 | 
						|
   for details about the copyright.
 | 
						|
 | 
						|
   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.
 | 
						|
 | 
						|
**********************************************************************}
 | 
						|
unit Linux;
 | 
						|
 | 
						|
{$packrecords c}
 | 
						|
 | 
						|
interface
 | 
						|
 | 
						|
uses
 | 
						|
  BaseUnix, unixtype;
 | 
						|
 | 
						|
type
 | 
						|
  TSysInfo = record
 | 
						|
    uptime: clong;                     //* Seconds since boot */
 | 
						|
    loads: array[0..2] of culong;      //* 1, 5, and 15 minute load averages */
 | 
						|
    totalram: culong;                  //* Total usable main memory size */
 | 
						|
    freeram: culong;                   //* Available memory size */
 | 
						|
    sharedram: culong;                 //* Amount of shared memory */
 | 
						|
    bufferram: culong;                 //* Memory used by buffers */
 | 
						|
    totalswap: culong;                 //* Total swap space size */
 | 
						|
    freeswap: culong;                  //* swap space still available */
 | 
						|
    procs: cushort;                    //* Number of current processes */
 | 
						|
    pad: cushort;                      //* explicit padding for m68k */
 | 
						|
    totalhigh: culong;                 //* Total high memory size */
 | 
						|
    freehigh: culong;                  //* Available high memory size */
 | 
						|
    mem_unit: cuint;                   //* Memory unit size in bytes */
 | 
						|
{$ifndef cpu64}
 | 
						|
    { the upper bound of the array below is negative for 64 bit cpus }
 | 
						|
    _f: array[0..19-2*sizeof(clong)-sizeof(cint)] of cChar;  //* Padding: libc5 uses this.. */
 | 
						|
{$endif cpu64}
 | 
						|
  end;
 | 
						|
  PSysInfo = ^TSysInfo;
 | 
						|
 | 
						|
function Sysinfo(Info: PSysinfo): cInt; {$ifdef FPC_USE_LIBC} cdecl; external name 'sysinfo'; {$endif}
 | 
						|
 | 
						|
const
 | 
						|
  CSIGNAL              = $000000ff; // signal mask to be sent at exit
 | 
						|
  CLONE_VM             = $00000100; // set if VM shared between processes
 | 
						|
  CLONE_FS             = $00000200; // set if fs info shared between processes
 | 
						|
  CLONE_FILES          = $00000400; // set if open files shared between processes
 | 
						|
  CLONE_SIGHAND        = $00000800; // set if signal handlers shared
 | 
						|
  CLONE_PID            = $00001000; // set if pid shared
 | 
						|
  CLONE_PTRACE         = $00002000; // Set if tracing continues on the child.
 | 
						|
  CLONE_VFORK          = $00004000; // Set if the parent wants the child to wake it up on mm_release.
 | 
						|
  CLONE_PARENT         = $00008000; // Set if we want to have the same parent as the cloner.
 | 
						|
  CLONE_THREAD         = $00010000; // Set to add to same thread group.
 | 
						|
  CLONE_NEWNS          = $00020000; // Set to create new namespace.
 | 
						|
  CLONE_SYSVSEM        = $00040000; // Set to shared SVID SEM_UNDO semantics.
 | 
						|
  CLONE_SETTLS         = $00080000; // Set TLS info.
 | 
						|
  CLONE_PARENT_SETTID  = $00100000; // Store TID in userlevel buffer before MM copy.
 | 
						|
  CLONE_CHILD_CLEARTID = $00200000; // Register exit futex and memory location to clear.
 | 
						|
  CLONE_DETACHED       = $00400000; // Create clone detached.
 | 
						|
  CLONE_UNTRACED       = $00800000; // Set if the tracing process can't force CLONE_PTRACE on this clone.
 | 
						|
  CLONE_CHILD_SETTID   = $01000000; // Store TID in userlevel buffer in the child.
 | 
						|
  CLONE_STOPPED        = $02000000; // Start in stopped state.
 | 
						|
 | 
						|
 | 
						|
  FUTEX_WAIT            = 0;
 | 
						|
  FUTEX_WAKE            = 1;
 | 
						|
  FUTEX_FD              = 2;
 | 
						|
  FUTEX_REQUEUE         = 3;
 | 
						|
  FUTEX_CMP_REQUEUE     = 4;
 | 
						|
  FUTEX_WAKE_OP         = 5;
 | 
						|
  FUTEX_LOCK_PI         = 6;
 | 
						|
  FUTEX_UNLOCK_PI       = 7;
 | 
						|
  FUTEX_TRYLOCK_PI      = 8;
 | 
						|
 | 
						|
  FUTEX_OP_SET          = 0;   // *(int *)UADDR2 = OPARG;
 | 
						|
  FUTEX_OP_ADD          = 1;   // *(int *)UADDR2 += OPARG;
 | 
						|
  FUTEX_OP_OR           = 2;   // *(int *)UADDR2 |= OPARG;
 | 
						|
  FUTEX_OP_ANDN         = 3;   // *(int *)UADDR2 &= ~OPARG;
 | 
						|
  FUTEX_OP_XOR          = 4;   // *(int *)UADDR2 ^= OPARG;
 | 
						|
 | 
						|
  FUTEX_OP_OPARG_SHIFT  = 8;   // Use (1 << OPARG) instead of OPARG.
 | 
						|
 | 
						|
  FUTEX_OP_CMP_EQ       = 0;   // if (oldval == CMPARG) wake
 | 
						|
  FUTEX_OP_CMP_NE       = 1;   // if (oldval != CMPARG) wake
 | 
						|
  FUTEX_OP_CMP_LT       = 2;   // if (oldval < CMPARG) wake
 | 
						|
  FUTEX_OP_CMP_LE       = 3;   // if (oldval <= CMPARG) wake
 | 
						|
  FUTEX_OP_CMP_GT       = 4;   // if (oldval > CMPARG) wake
 | 
						|
  FUTEX_OP_CMP_GE       = 5;   // if (oldval >= CMPARG) wake
 | 
						|
 | 
						|
{ FUTEX_WAKE_OP will perform atomically
 | 
						|
   int oldval = *(int *)UADDR2;
 | 
						|
   *(int *)UADDR2 = oldval OP OPARG;
 | 
						|
   if (oldval CMP CMPARG)
 | 
						|
     wake UADDR2; }
 | 
						|
 | 
						|
{$ifndef FPC_USE_LIBC}
 | 
						|
function futex(uaddr:Pcint;op,val:cint;timeout:Ptimespec;addr2:Pcint;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
function futex(var uaddr;op,val:cint;timeout:Ptimespec;var addr2;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
function futex(var uaddr;op,val:cint;var timeout:Ttimespec;var addr2;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
{$else}
 | 
						|
function futex(uaddr:Pcint;op,val:cint;timeout:Ptimespec;addr2:Pcint;val3:cint):cint; cdecl; external name 'futex';
 | 
						|
function futex(var uaddr;op,val:cint;timeout:Ptimespec;var addr2;val3:cint):cint; cdecl; external name 'futex';
 | 
						|
function futex(var uaddr;op,val:cint;var timeout:Ttimespec;var addr2;val3:cint):cint; cdecl; external name 'futex';
 | 
						|
{$endif}
 | 
						|
function futex(uaddr:Pcint;op,val:cint;timeout:Ptimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
function futex(var uaddr;op,val:cint;timeout:Ptimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
function futex(var uaddr;op,val:cint;var timeout:Ttimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
 | 
						|
{$ifndef FPC_USE_LIBC}
 | 
						|
function futex_op(op, oparg, cmp, cmparg: cint): cint; {$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
{$endif}
 | 
						|
 | 
						|
const
 | 
						|
  POLLMSG     = $0400;
 | 
						|
  POLLREMOVE  = $1000;
 | 
						|
  POLLRDHUP   = $2000;
 | 
						|
 | 
						|
  EPOLLIN  = $01; { The associated file is available for read(2) operations. }
 | 
						|
  EPOLLPRI = $02; { There is urgent data available for read(2) operations. }
 | 
						|
  EPOLLOUT = $04; { The associated file is available for write(2) operations. }
 | 
						|
  EPOLLERR = $08; { Error condition happened on the associated file descriptor. }
 | 
						|
  EPOLLHUP = $10; { Hang up happened on the associated file descriptor. }
 | 
						|
  EPOLLONESHOT = $40000000; { Sets the One-Shot behaviour for the associated file descriptor. }
 | 
						|
  EPOLLET  = $80000000; { Sets  the  Edge  Triggered  behaviour  for  the  associated file descriptor. }
 | 
						|
 | 
						|
  { Valid opcodes ( "op" parameter ) to issue to epoll_ctl }
 | 
						|
  EPOLL_CTL_ADD = 1;
 | 
						|
  EPOLL_CTL_DEL = 2;
 | 
						|
  EPOLL_CTL_MOD = 3;
 | 
						|
 | 
						|
  {Some console iotcl's.}
 | 
						|
  GIO_FONT        = $4B60;  {gets font in expanded form}
 | 
						|
  PIO_FONT        = $4B61;  {use font in expanded form}
 | 
						|
  GIO_FONTX       = $4B6B;  {get font using struct consolefontdesc}
 | 
						|
  PIO_FONTX       = $4B6C;  {set font using struct consolefontdesc}
 | 
						|
  PIO_FONTRESET   = $4B6D;  {reset to default font}
 | 
						|
  GIO_CMAP        = $4B70;  {gets colour palette on VGA+}
 | 
						|
  PIO_CMAP        = $4B71;  {sets colour palette on VGA+}
 | 
						|
  KIOCSOUND       = $4B2F;  {start sound generation (0 for off)}
 | 
						|
  KDMKTONE        = $4B30;  {generate tone}
 | 
						|
  KDGETLED        = $4B31;  {return current led state}
 | 
						|
  KDSETLED        = $4B32;  {set led state [lights, not flags]}
 | 
						|
  KDGKBTYPE       = $4B33;  {get keyboard type}
 | 
						|
  KDADDIO         = $4B34;  {add i/o port as valid}
 | 
						|
  KDDELIO         = $4B35;  {del i/o port as valid}
 | 
						|
  KDENABIO        = $4B36;  {enable i/o to video board}
 | 
						|
  KDDISABIO       = $4B37;  {disable i/o to video board}
 | 
						|
  KDSETMODE       = $4B3A;  {set text/graphics mode}
 | 
						|
  KDGETMODE       = $4B3B;  {get current mode}
 | 
						|
  KDMAPDISP       = $4B3C;  {map display into address space}
 | 
						|
  KDUNMAPDISP     = $4B3D;  {unmap display from address space}
 | 
						|
  GIO_SCRNMAP     = $4B40;  {get screen mapping from kernel}
 | 
						|
  PIO_SCRNMAP     = $4B41;  {put screen mapping table in kernel}
 | 
						|
  GIO_UNISCRNMAP  = $4B69;  {get full Unicode screen mapping}
 | 
						|
  PIO_UNISCRNMAP  = $4B6A;  {set full Unicode screen mapping}
 | 
						|
  GIO_UNIMAP      = $4B66;  {get unicode-to-font mapping from kernel}
 | 
						|
  PIO_UNIMAP      = $4B67;  {put unicode-to-font mapping in kernel}
 | 
						|
  PIO_UNIMAPCLR   = $4B68;  {clear table, possibly advise hash algorithm}
 | 
						|
  KDGKBDIACR      = $4B4A;  {read kernel accent table}
 | 
						|
  KDSKBDIACR      = $4B4B;  {write kernel accent table}
 | 
						|
  KDGETKEYCODE    = $4B4C;  {read kernel keycode table entry}
 | 
						|
  KDSETKEYCODE    = $4B4D;  {write kernel keycode table entry}
 | 
						|
  KDSIGACCEPT     = $4B4E;  {accept kbd generated signals}
 | 
						|
  KDFONTOP        = $4B72;  {font operations}
 | 
						|
 | 
						|
  {Keyboard types (for KDGKBTYPE)}
 | 
						|
  KB_84           = 1;
 | 
						|
  KB_101          = 2;    {Normal PC keyboard.}
 | 
						|
  KB_OTHER        = 3;
 | 
						|
 | 
						|
  {Keyboard LED constants.}
 | 
						|
  LED_SCR         = 1;    {scroll lock led}
 | 
						|
  LED_NUM         = 2;    {num lock led}
 | 
						|
  LED_CAP         = 4;    {caps lock led}
 | 
						|
    
 | 
						|
  {Tty modes. (for KDSETMODE)}
 | 
						|
  KD_TEXT         = 0;
 | 
						|
  KD_GRAPHICS     = 1;
 | 
						|
  KD_TEXT0        = 2;    {obsolete}
 | 
						|
  KD_TEXT1        = 3;    {obsolete}
 | 
						|
 | 
						|
  MAP_GROWSDOWN  = $100;       { stack-like segment }
 | 
						|
  MAP_DENYWRITE  = $800;       { ETXTBSY }
 | 
						|
  MAP_EXECUTABLE = $1000;      { mark it as an executable }
 | 
						|
  MAP_LOCKED     = $2000;      { pages are locked }
 | 
						|
  MAP_NORESERVE  = $4000;      { don't check for reservations }
 | 
						|
 | 
						|
type
 | 
						|
  TCloneFunc = function(args:pointer):longint;cdecl;
 | 
						|
 | 
						|
{$ifdef cpui386}
 | 
						|
  {$define clone_implemented}
 | 
						|
{$endif}
 | 
						|
 | 
						|
{$ifdef clone_implemented}
 | 
						|
function clone(func:TCloneFunc;sp:pointer;flags:longint;args:pointer):longint; {$ifdef FPC_USE_LIBC} cdecl; external name 'clone'; {$endif}
 | 
						|
{$endif}
 | 
						|
 | 
						|
{$if defined(cpui386) or defined(cpux86_64)}
 | 
						|
const
 | 
						|
  MODIFY_LDT_CONTENTS_DATA       = 0;
 | 
						|
  MODIFY_LDT_CONTENTS_STACK      = 1;
 | 
						|
  MODIFY_LDT_CONTENTS_CODE       = 2;
 | 
						|
 | 
						|
{ Flags for user_desc.flags }
 | 
						|
  UD_SEG_32BIT            = $01;
 | 
						|
  UD_CONTENTS_DATA        = MODIFY_LDT_CONTENTS_DATA  shl 1;
 | 
						|
  UD_CONTENTS_STACK       = MODIFY_LDT_CONTENTS_STACK shl 1;
 | 
						|
  UD_CONTENTS_CODE        = MODIFY_LDT_CONTENTS_CODE  shl 1;
 | 
						|
  UD_READ_EXEC_ONLY       = $08;
 | 
						|
  UD_LIMIT_IN_PAGES       = $10;
 | 
						|
  UD_SEG_NOT_PRESENT      = $20;
 | 
						|
  UD_USEABLE              = $40;
 | 
						|
  UD_LM                   = $80;
 | 
						|
 | 
						|
type
 | 
						|
  user_desc = packed record
 | 
						|
    entry_number  : cint;
 | 
						|
    base_addr     : cuint;
 | 
						|
    limit         : cuint;
 | 
						|
    flags         : cuint;
 | 
						|
  end;
 | 
						|
 | 
						|
  TUser_Desc = user_desc;
 | 
						|
  PUser_Desc = ^user_desc;
 | 
						|
 | 
						|
function modify_ldt(func:cint;p:pointer;bytecount:culong):cint;
 | 
						|
{$endif cpui386 or cpux86_64}
 | 
						|
 | 
						|
procedure sched_yield; {$ifdef FPC_USE_LIBC} cdecl; external name 'sched_yield'; {$endif}
 | 
						|
 | 
						|
type
 | 
						|
  EPoll_Data = record
 | 
						|
    case integer of
 | 
						|
      0: (ptr: pointer);
 | 
						|
      1: (fd: cint);
 | 
						|
      2: (u32: cuint);
 | 
						|
      3: (u64: cuint64);
 | 
						|
  end;
 | 
						|
  TEPoll_Data =  Epoll_Data;
 | 
						|
  PEPoll_Data = ^Epoll_Data;
 | 
						|
 | 
						|
  EPoll_Event = {$ifdef cpu64} packed {$endif} record
 | 
						|
    Events: cuint32;
 | 
						|
    Data  : TEpoll_Data;
 | 
						|
  end;
 | 
						|
 | 
						|
  TEPoll_Event =  Epoll_Event;
 | 
						|
  PEpoll_Event = ^Epoll_Event;
 | 
						|
 | 
						|
 | 
						|
{ open an epoll file descriptor }
 | 
						|
function epoll_create(size: cint): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'epoll_create'; {$endif}
 | 
						|
{ control interface for an epoll descriptor }
 | 
						|
function epoll_ctl(epfd, op, fd: cint; event: pepoll_event): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'epoll_ctl'; {$endif}
 | 
						|
{ wait for an I/O event on an epoll file descriptor }
 | 
						|
function epoll_wait(epfd: cint; events: pepoll_event; maxevents, timeout: cint): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'epoll_wait'; {$endif}
 | 
						|
 | 
						|
type Puser_cap_header=^user_cap_header;
 | 
						|
     user_cap_header=packed record
 | 
						|
       version,pid:cardinal;
 | 
						|
     end;
 | 
						|
     
 | 
						|
     Puser_cap_data=^user_cap_data;
 | 
						|
     user_cap_data=packed record
 | 
						|
        effective,permitted,inheritable:cardinal;
 | 
						|
     end;
 | 
						|
 | 
						|
{Get a capability.}
 | 
						|
function capget(header:Puser_cap_header;data:Puser_cap_data):cint;{$ifdef FPC_USE_LIBC} cdecl; external name 'capget'; {$endif}
 | 
						|
{Set a capability.}
 | 
						|
function capset(header:Puser_cap_header;data:Puser_cap_data):cint;{$ifdef FPC_USE_LIBC} cdecl; external name 'capset'; {$endif}
 | 
						|
 | 
						|
     
 | 
						|
const CAP_CHOWN            = 0;
 | 
						|
      CAP_DAC_OVERRIDE     = 1;
 | 
						|
      CAP_DAC_READ_SEARCH  = 2;
 | 
						|
      CAP_FOWNER           = 3;
 | 
						|
      CAP_FSETID           = 4;
 | 
						|
      CAP_FS_MASK          = $1f;
 | 
						|
      CAP_KILL             = 5;
 | 
						|
      CAP_SETGID           = 6;
 | 
						|
      CAP_SETUID           = 7;
 | 
						|
      CAP_SETPCAP          = 8;
 | 
						|
      CAP_LINUX_IMMUTABLE  = 9;
 | 
						|
      CAP_NET_BIND_SERVICE = 10;
 | 
						|
      CAP_NET_BROADCAST    = 11;
 | 
						|
      CAP_NET_ADMIN        = 12;
 | 
						|
      CAP_NET_RAW          = 13;
 | 
						|
      CAP_IPC_LOCK         = 14;
 | 
						|
      CAP_IPC_OWNER        = 15;
 | 
						|
      CAP_SYS_MODULE       = 16;
 | 
						|
      CAP_SYS_RAWIO        = 17;
 | 
						|
      CAP_SYS_CHROOT       = 18;
 | 
						|
      CAP_SYS_PTRACE       = 19;
 | 
						|
      CAP_SYS_PACCT        = 20;
 | 
						|
      CAP_SYS_ADMIN        = 21;
 | 
						|
      CAP_SYS_BOOT         = 22;
 | 
						|
      CAP_SYS_NICE         = 23;
 | 
						|
      CAP_SYS_RESOURCE     = 24;
 | 
						|
      CAP_SYS_TIME         = 25;
 | 
						|
      CAP_SYS_TTY_CONFIG   = 26;
 | 
						|
      CAP_MKNOD            = 27;
 | 
						|
      CAP_LEASE            = 28;
 | 
						|
      CAP_AUDIT_WRITE      = 29;
 | 
						|
      CAP_AUDIT_CONTROL    = 30;
 | 
						|
 | 
						|
      LINUX_CAPABILITY_VERSION = $19980330;
 | 
						|
 | 
						|
 | 
						|
//***********************************************SPLICE from kernel 2.6.17+****************************************
 | 
						|
 | 
						|
const
 | 
						|
{* Flags for SPLICE and VMSPLICE.  *}
 | 
						|
  SPLICE_F_MOVE		= 1;   { Move pages instead of copying.  }
 | 
						|
  SPLICE_F_NONBLOCK	= 2;   {* Don't block on the pipe splicing
 | 
						|
                            (but we may still block on the fd
 | 
						|
                                        we splice from/to).  *}
 | 
						|
  SPLICE_F_MORE	    = 4;   {* Expect more data.  *}
 | 
						|
  SPLICE_F_GIFT	    = 8;   {* Pages passed in are a gift.  *}
 | 
						|
 | 
						|
{$ifdef cpu86}
 | 
						|
{* Splice address range into a pipe.  *}
 | 
						|
function vmsplice (fdout: cInt; iov: PIOVec; count: size_t; flags: cuInt): cInt; {$ifdef FPC_USE_LIBC} cdecl; external name 'vmsplice'; {$ENDIF}
 | 
						|
 | 
						|
{* Splice two files together.  *}
 | 
						|
function splice (fdin: cInt; offin: off64_t; fdout: cInt;
 | 
						|
                             offout: off64_t; len: size_t; flags: cuInt): cInt; {$ifdef FPC_USE_LIBC} cdecl; external name 'splice'; {$ENDIF}
 | 
						|
                             
 | 
						|
function tee(fd_in: cInt; fd_out: cInt; len: size_t; flags: cuInt): cInt; {$ifdef FPC_USE_LIBC} cdecl; external name 'tee'; {$ENDIF}
 | 
						|
 | 
						|
{$endif} // x86
 | 
						|
 | 
						|
const
 | 
						|
  { flags for sync_file_range }
 | 
						|
  SYNC_FILE_RANGE_WAIT_BEFORE = 1;
 | 
						|
  SYNC_FILE_RANGE_WRITE       = 2;
 | 
						|
  SYNC_FILE_RANGE_WAIT_AFTER  = 4;
 | 
						|
 | 
						|
function sync_file_range(fd: cInt; offset, nbytes: off64_t; flags: cuInt): cInt; {$ifdef FPC_USE_LIBC} cdecl; external name 'sync_file_range'; {$ENDIF}
 | 
						|
function fdatasync (fd: cint): cint; {$ifdef FPC_USE_LIBC} cdecl; external name 'sync_file_range'; {$ENDIF}
 | 
						|
 | 
						|
implementation
 | 
						|
 | 
						|
 | 
						|
{$if not defined(FPC_USE_LIBC) or defined(cpui386) or defined(cpux86_64)}
 | 
						|
{ needed for modify_ldt on x86 }
 | 
						|
Uses Syscall;
 | 
						|
{$endif not defined(FPC_USE_LIBC) or defined(cpui386) or defined(cpux86_64)}
 | 
						|
 | 
						|
{$ifndef FPC_USE_LIBC}
 | 
						|
function Sysinfo(Info: PSysinfo): cInt;
 | 
						|
begin
 | 
						|
  Sysinfo := do_SysCall(SysCall_nr_Sysinfo, TSysParam(info));
 | 
						|
end;
 | 
						|
 | 
						|
{$ifdef clone_implemented}
 | 
						|
function clone(func:TCloneFunc;sp:pointer;flags:longint;args:pointer):longint;
 | 
						|
 | 
						|
begin
 | 
						|
  if (pointer(func)=nil) or (sp=nil) then
 | 
						|
   exit(-1); // give an error result
 | 
						|
{$ifdef cpui386}
 | 
						|
{$ASMMODE ATT}
 | 
						|
  asm
 | 
						|
        { Insert the argument onto the new stack. }
 | 
						|
        movl    sp,%ecx
 | 
						|
        subl    $8,%ecx
 | 
						|
        movl    args,%eax
 | 
						|
        movl    %eax,4(%ecx)
 | 
						|
 | 
						|
        { Save the function pointer as the zeroth argument.
 | 
						|
          It will be popped off in the child in the ebx frobbing below. }
 | 
						|
        movl    func,%eax
 | 
						|
        movl    %eax,0(%ecx)
 | 
						|
 | 
						|
        { Do the system call }
 | 
						|
        pushl   %ebx
 | 
						|
        movl    flags,%ebx
 | 
						|
        movl    syscall_nr_clone,%eax
 | 
						|
        int     $0x80
 | 
						|
        popl    %ebx
 | 
						|
        test    %eax,%eax
 | 
						|
        jnz     .Lclone_end
 | 
						|
 | 
						|
        { We're in the new thread }
 | 
						|
        subl    %ebp,%ebp       { terminate the stack frame }
 | 
						|
        call    *%ebx
 | 
						|
        { exit process }
 | 
						|
        movl    %eax,%ebx
 | 
						|
        movl    syscall_nr_exit,%eax
 | 
						|
        int     $0x80
 | 
						|
 | 
						|
.Lclone_end:
 | 
						|
        movl    %eax,__RESULT
 | 
						|
  end;
 | 
						|
{$endif cpui386}
 | 
						|
end;
 | 
						|
{$endif}
 | 
						|
 | 
						|
procedure sched_yield;
 | 
						|
 | 
						|
begin
 | 
						|
  do_syscall(syscall_nr_sched_yield);
 | 
						|
end;
 | 
						|
 | 
						|
function epoll_create(size: cint): cint;
 | 
						|
begin
 | 
						|
  epoll_create := do_syscall(syscall_nr_epoll_create,tsysparam(size));
 | 
						|
end;
 | 
						|
 | 
						|
function epoll_ctl(epfd, op, fd: cint; event: pepoll_event): cint;
 | 
						|
begin
 | 
						|
  epoll_ctl := do_syscall(syscall_nr_epoll_ctl, tsysparam(epfd),
 | 
						|
    tsysparam(op), tsysparam(fd), tsysparam(event));
 | 
						|
end;
 | 
						|
 | 
						|
function epoll_wait(epfd: cint; events: pepoll_event; maxevents, timeout: cint): cint;
 | 
						|
begin
 | 
						|
  epoll_wait := do_syscall(syscall_nr_epoll_wait, tsysparam(epfd),
 | 
						|
    tsysparam(events), tsysparam(maxevents), tsysparam(timeout));
 | 
						|
end;
 | 
						|
 | 
						|
function capget(header:Puser_cap_header;data:Puser_cap_data):cint;
 | 
						|
 | 
						|
begin
 | 
						|
  capget:=do_syscall(syscall_nr_capget,Tsysparam(header),Tsysparam(data));
 | 
						|
end;
 | 
						|
 | 
						|
function capset(header:Puser_cap_header;data:Puser_cap_data):cint;
 | 
						|
 | 
						|
begin
 | 
						|
  capset:=do_syscall(syscall_nr_capset,Tsysparam(header),Tsysparam(data));
 | 
						|
end;
 | 
						|
 | 
						|
// TODO: update also on non x86!
 | 
						|
{$ifdef cpu86} // didn't update syscall_nr on others yet
 | 
						|
 | 
						|
function vmsplice (fdout: cInt; iov: PIOVec; count: size_t; flags: cuInt): cInt;
 | 
						|
begin
 | 
						|
  vmsplice := do_syscall(syscall_nr_vmsplice, TSysParam(fdout), TSysParam(iov), 
 | 
						|
    TSysParam(count), TSysParam(flags));
 | 
						|
end;
 | 
						|
 | 
						|
function splice (fdin: cInt; offin: off64_t; fdout: cInt; offout: off64_t; len: size_t; flags: cuInt): cInt; 
 | 
						|
begin
 | 
						|
  splice := do_syscall(syscall_nr_splice, TSysParam(fdin), TSysParam(@offin), 
 | 
						|
    TSysParam(fdout), TSysParam(@offout), TSysParam(len), TSysParam(flags));
 | 
						|
end;
 | 
						|
 | 
						|
function tee(fd_in: cInt; fd_out: cInt; len: size_t; flags: cuInt): cInt;
 | 
						|
begin
 | 
						|
  tee := do_syscall(syscall_nr_tee, TSysParam(fd_in), TSysParam(fd_out),
 | 
						|
                    TSysParam(len), TSysParam(flags));
 | 
						|
end;
 | 
						|
 | 
						|
{$endif} // x86
 | 
						|
 | 
						|
function sync_file_range(fd: cInt; offset: off64_t; nbytes: off64_t; flags: cuInt): cInt;
 | 
						|
begin
 | 
						|
{$if defined(cpupowerpc) or defined(cpuarm)}
 | 
						|
  sync_file_range := do_syscall(syscall_nr_sync_file_range2, TSysParam(fd), TSysParam(flags), 
 | 
						|
    TSysParam(hi(offset)), TSysParam(lo(offset)), TSysParam(hi(nbytes)), TSysParam(lo(nbytes)));
 | 
						|
{$else}
 | 
						|
{$if defined(cpupowerpc64)}
 | 
						|
  sync_file_range := do_syscall(syscall_nr_sync_file_range2, TSysParam(fd), TSysParam(flags),
 | 
						|
    TSysParam(offset), TSysParam(nbytes));
 | 
						|
{$else}
 | 
						|
{$ifdef cpu64}
 | 
						|
  sync_file_range := do_syscall(syscall_nr_sync_file_range, TSysParam(fd), TSysParam(offset), 
 | 
						|
    TSysParam(nbytes), TSysParam(flags));
 | 
						|
{$else}
 | 
						|
  sync_file_range := do_syscall(syscall_nr_sync_file_range, TSysParam(fd), TSysParam(lo(offset)),
 | 
						|
    TSysParam(hi(offset)), TSysParam(lo(nbytes)), TSysParam(hi(nbytes)), TSysParam(flags));
 | 
						|
{$endif}
 | 
						|
{$endif}
 | 
						|
{$endif}
 | 
						|
end;
 | 
						|
 | 
						|
function fdatasync (fd: cint): cint;
 | 
						|
begin
 | 
						|
  fdatasync:=do_SysCall(syscall_nr_fdatasync, fd);
 | 
						|
end;
 | 
						|
 | 
						|
function futex(uaddr:Pcint;op,val:cint;timeout:Ptimespec;addr2:Pcint;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
 | 
						|
begin
 | 
						|
  futex:=do_syscall(syscall_nr_futex,Tsysparam(uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(timeout),
 | 
						|
                    Tsysparam(addr2),Tsysparam(val3));
 | 
						|
end;
 | 
						|
 | 
						|
function futex(var uaddr;op,val:cint;timeout:Ptimespec;var addr2;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
 | 
						|
begin
 | 
						|
  futex:=do_syscall(syscall_nr_futex,Tsysparam(@uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(timeout),
 | 
						|
                    Tsysparam(@addr2),Tsysparam(val3));
 | 
						|
end;
 | 
						|
 | 
						|
function futex(var uaddr;op,val:cint;var timeout:Ttimespec;var addr2;val3:cint):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
 | 
						|
begin
 | 
						|
  futex:=do_syscall(syscall_nr_futex,Tsysparam(@uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(@timeout),
 | 
						|
                    Tsysparam(@addr2),Tsysparam(val3));
 | 
						|
end;
 | 
						|
 | 
						|
function futex(uaddr:Pcint;op,val:cint;timeout:Ptimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
 | 
						|
begin
 | 
						|
  futex:=do_syscall(syscall_nr_futex,Tsysparam(uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(timeout));
 | 
						|
end;
 | 
						|
 | 
						|
function futex(var uaddr;op,val:cint;timeout:Ptimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
 | 
						|
begin
 | 
						|
  futex:=do_syscall(syscall_nr_futex,Tsysparam(@uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(timeout));
 | 
						|
end;
 | 
						|
 | 
						|
function futex(var uaddr;op,val:cint;var timeout:Ttimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
 | 
						|
begin
 | 
						|
  futex:=do_syscall(syscall_nr_futex,Tsysparam(@uaddr),Tsysparam(op),Tsysparam(val),Tsysparam(@timeout));
 | 
						|
end;
 | 
						|
 | 
						|
{$else}
 | 
						|
 | 
						|
{Libc case.}
 | 
						|
 | 
						|
function futex(uaddr:Pcint;op,val:cint;timeout:Ptimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
 | 
						|
begin
 | 
						|
  futex:=futex(uaddr,op,val,nil,nil,0);
 | 
						|
end;
 | 
						|
 | 
						|
function futex(var uaddr;op,val:cint;timeout:Ptimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
 | 
						|
begin
 | 
						|
  futex:=futex(@uaddr,op,val,nil,nil,0);
 | 
						|
end;
 | 
						|
 | 
						|
function futex(var uaddr;op,val:cint;var timeout:Ttimespec):cint;{$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
 | 
						|
begin
 | 
						|
  futex:=futex(@uaddr,op,val,@timeout,nil,0);
 | 
						|
end;
 | 
						|
 | 
						|
{$endif} // non-libc
 | 
						|
 | 
						|
{$if defined(cpui386) or defined(cpux86_64)}
 | 
						|
{ does not exist as a wrapper in glibc, and exists only for x86 }
 | 
						|
function modify_ldt(func:cint;p:pointer;bytecount:culong):cint;
 | 
						|
 | 
						|
begin
 | 
						|
  modify_ldt:=do_syscall(syscall_nr_modify_ldt,Tsysparam(func),
 | 
						|
                                               Tsysparam(p),
 | 
						|
                                               Tsysparam(bytecount));
 | 
						|
end;
 | 
						|
{$endif}
 | 
						|
 | 
						|
{ FUTEX_OP is a macro, doesn't exist in libC as function}
 | 
						|
function FUTEX_OP(op, oparg, cmp, cmparg: cint): cint; {$ifdef SYSTEMINLINE}inline;{$endif}
 | 
						|
begin
 | 
						|
  FUTEX_OP := ((op and $F) shl 28) or ((cmp and $F) shl 24) or ((oparg and $FFF) shl 12) or (cmparg and $FFF);
 | 
						|
end;
 | 
						|
 | 
						|
end.
 |