diff --git a/.gitattributes b/.gitattributes index 3d42334832..e67f70acd4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4174,6 +4174,7 @@ rtl/freebsd/termio.pp svneol=native#text/plain rtl/freebsd/termios.inc svneol=native#text/plain rtl/freebsd/termiosproc.inc svneol=native#text/plain rtl/freebsd/tthread.inc svneol=native#text/plain +rtl/freebsd/ucontexth.inc -text svneol=unset#plain/text rtl/freebsd/unixsock.inc svneol=native#text/plain rtl/freebsd/unxconst.inc svneol=native#text/plain rtl/freebsd/unxfunc.inc svneol=native#text/plain diff --git a/rtl/freebsd/freebsd.pas b/rtl/freebsd/freebsd.pas index 39e96de488..78938d081c 100644 --- a/rtl/freebsd/freebsd.pas +++ b/rtl/freebsd/freebsd.pas @@ -30,10 +30,42 @@ Unit FreeBSD; interface uses - BaseUnix,Unix; + 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 @@ -68,9 +100,67 @@ Type 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; @@ -85,13 +175,22 @@ Type 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; implementation Uses {$ifndef FPC_USE_LIBC} SysCall; {$else} InitC; {$endif} -{$IFNDEF FPC_USE_LIBC} +{$IFNDEF FPC_USE_LIBC} function SendFile(fd: cint; s: cint; Offset: TOff; nBytes: TSize; HDTR: PSF_HDTR; sBytes: POff; Flags: cint): cint; @@ -109,6 +208,8 @@ begin nBytes, TSysParam(HDTR), TSysParam(sBytes), Flags); end; +// kernel modules + function kldload(FileName: pChar): cInt; begin kldload:=do_sysCall(syscall_nr_kldload, TSysParam(FileName)); @@ -146,6 +247,40 @@ begin 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. diff --git a/rtl/freebsd/signal.inc b/rtl/freebsd/signal.inc index c09bc980dc..79f7259e89 100644 --- a/rtl/freebsd/signal.inc +++ b/rtl/freebsd/signal.inc @@ -177,6 +177,16 @@ type sigset_t = array[0..3] of Longint; Sa_Mask : TSigSet; end; PSigActionRec = ^SigActionRec; + + + pstack_t = ^stack_t; + stack_t = record + ss_sp: pChar; {* signal stack base *} + ss_size: size_t; {* signal stack length *} + ss_flags: cInt; {* SS_DISABLE and/or SS_ONSTACK *} + end; + TStack = stack_t; + PStack = pstack_t; { Change action of process upon receipt of a signal. diff --git a/rtl/freebsd/sysnr.inc b/rtl/freebsd/sysnr.inc index bbef5130a3..0e482683a8 100644 --- a/rtl/freebsd/sysnr.inc +++ b/rtl/freebsd/sysnr.inc @@ -13,7 +13,7 @@ **********************************************************************} const -{ Crude converted FreeBSD 4.0-release syscall.h. Copy and paste if you +{ Crude converted FreeBSD 6.1-release syscall.h. Copy and paste if you checked the function. syscall_nr_syscall = 0; syscall_nr_exit = 1; @@ -221,7 +221,12 @@ syscall_nr_getdirentries =196; syscall_nr_aio_waitcomplete =359; syscall_nr_getresuid =360; syscall_nr_getresgid =361; - syscall_nr_MAXSYSCALL =362; + syscall_nr_kse_exit = 379; + syscall_nr_kse_wakeup = 380; + syscall_nr_kse_create = 381; + syscall_nr_kse_thr_interrupt = 382; + syscall_nr_kse_release = 383; + syscall_nr_kse_switchin = 440; } @@ -326,4 +331,11 @@ syscall_nr_getdirentries =196; syscall_nr_kldfirstmod = 309; syscall_nr_kldsym = 337; syscall_nr_sendfile = 393; + syscall_nr_kse_exit = 379; + syscall_nr_kse_wakeup = 380; + syscall_nr_kse_create = 381; + syscall_nr_kse_thr_interrupt = 382; + syscall_nr_kse_release = 383; + syscall_nr_kse_switchin = 440; + diff --git a/rtl/freebsd/ucontexth.inc b/rtl/freebsd/ucontexth.inc new file mode 100644 index 0000000000..aec4d8c69d --- /dev/null +++ b/rtl/freebsd/ucontexth.inc @@ -0,0 +1,74 @@ +const + {* Used by swapcontext(3). *} + UCF_SWAPPED = $00000001; + _MC_FPFMT_NODEV = $10000; {* device not present or configured *} + _MC_FPFMT_387 = $10001; + _MC_FPFMT_XMM = $10002; + _MC_FPOWNED_NONE = $20000; {* FP state not used *} + _MC_FPOWNED_FPU = $20001; {* FP state came from FPU *} + _MC_FPOWNED_PCB = $20002; {* FP state came from PCB *} + +type + plwpid_t = ^lwpid_t; + lwpid_t = cint32; + TLwPid = lwpid_t; + PLwPid = ^lwpid_t; + + {$packrecords 16} + TMCFPStateArray = record + items: array[0..127] of cInt; + end; + {$packrecords C} + + mcontext_t = record + {* + * The first 20 fields must match the definition of + * sigcontext. So that we can support sigcontext + * and ucontext_t at the same time. + *} + mc_onstack: cInt; {* XXX - sigcontext compat. *} + mc_gs: cInt; {* machine state (struct trapframe) *} + mc_fs: cInt; + mc_es: cInt; + mc_ds: cInt; + mc_edi: cInt; + mc_esi: cInt; + mc_ebp: cInt; + mc_isp: cInt; + mc_ebx: cInt; + mc_edx: cInt; + mc_ecx: cInt; + mc_eax: cInt; + mc_trapno: cInt; + mc_err: cInt; + mc_eip: cInt; + mc_cs: cInt; + mc_eflags: cInt; + mc_esp: cInt; + mc_ss: cInt; + mc_len: cInt; {* sizeof(mcontext_t) *} + mc_fpformat: cInt; + mc_ownedfp: cInt; + mc_spare1: array[0..0] of cInt; {* align next field to 16 bytes *} + mc_fpstate: TMCFPStateArray; + mc_spare2: array[0..7] of cInt; + end; + + + pucontext_t = ^ucontext_t; + ucontext_t = record // required for kse threads + {* + * Keep the order of the first two fields. Also, + * keep them the first two fields in the structure. + * This way we can have a union with struct + * sigcontext and ucontext_t. This allows us to + * support them both at the same time. + * note: the union is not defined, though. + *} + uc_sigmask: sigset_t; + uc_mcontext: mcontext_t; + uc_link: pucontext_t; + uc_stack: stack_t; + uc_flags: cInt; + __spare__: array[0..3] of cInt; + end;