This commit is contained in:
Pavel 2024-02-18 02:08:40 +03:00
parent efd934f00b
commit ecf4f7d7bc
36 changed files with 1337 additions and 969 deletions

View File

@ -846,6 +846,14 @@
<Filename Value="sys\dev\display_interface.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="sys\dev\devfs_int.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="sys\sys_conf.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>

View File

@ -9,6 +9,7 @@ uses
Classes,
SysUtils,
kern_thr,
md_sleep,
md_pipe,
host_ipc,
md_host_ipc,
@ -54,6 +55,8 @@ uses
sys_tty,
md_exception, //<- install custom
sys_event,
kern_proc,
md_systm,
@ -106,6 +109,8 @@ begin
//init all
sys_init;
kern_ipc.thread_new;
PROC_INIT_HOST_IPC(kern_ipc);
Writeln(Item.FGameInfo.Exec);
@ -204,7 +209,7 @@ begin
r:=kthread_add(@prepare,Item,@td,'[main]');
Assert(r=0);
sleep(-1);
msleep_td(0);
end;
function run_item(const cfg:TGameRunConfig;Item:TGameItem):TGameProcess;
@ -213,6 +218,10 @@ var
kern2mgui:array[0..1] of THandle;
fork_info:t_fork_proc;
kev:t_kevent;
p_mgui_ipc:THostIpcPipeMGUI;
s_kern_ipc:THostIpcSimpleKERN;
@ -228,6 +237,8 @@ begin
SetStdHandle(STD_OUTPUT_HANDLE,cfg.hOutput);
SetStdHandle(STD_ERROR_HANDLE ,cfg.hError );
fork_info:=Default(t_fork_proc);
if cfg.fork_proc then
begin
Result:=TGameProcessPipe.Create;
@ -252,9 +263,11 @@ begin
Item.Serialize(mem);
r:=md_fork_process(@fork_process,mem.Memory,mem.Size,fork_info);
with TGameProcessPipe(Result) do
begin
FProcess:=md_fork_process(@fork_process,mem.Memory,mem.Size);
FProcess:=fork_info.hProcess;
end;
mem.Free;
@ -278,10 +291,23 @@ begin
Ftd:=nil;
r:=kthread_add(@prepare,Item,@Ftd,'[main]');
fork_info.fork_pid:=GetProcessID;
end;
end;
Result.g_ipc.thread_new;
kev.ident :=fork_info.fork_pid;
kev.filter:=EVFILT_PROC;
kev.flags :=EV_ADD;
kev.fflags:=NOTE_EXIT or NOTE_EXEC;
kev.data :=0;
kev.udata :=nil;
Result.g_ipc.kevent(@kev,1);
runing:=True;
end;

View File

@ -78,8 +78,7 @@ uses
TypInfo,
Rtti,
evbuffer,
evpoll;
sys_event;
//
@ -123,28 +122,49 @@ type
TGuiIpcHandler=class(THostIpcHandler)
Form:TfrmMain;
function OnMessage(mtype:t_mtype;mlen:DWORD;buf:Pointer):Ptruint; override;
function OnKevent(kev:p_kevent;count:Integer):Ptruint;
end;
function TGuiIpcHandler.OnMessage(mtype:t_mtype;mlen:DWORD;buf:Pointer):Ptruint;
begin
Result:=0;
case mtype of
iKNOTE:
with PHostIpcKnote(buf)^ do
begin
ShowMessage('iKNOTE pid:'+IntToStr(pid)+
' filter:'+IntToStr(filter)+
' hint:'+HexStr(hint,16)
);
end;
iKEV_EVENT:Result:=OnKevent(buf,mlen div sizeof(t_kevent));
else;
ShowMessage(GetEnumName(TypeInfo(mtype),ord(mtype)));
end;
end;
//PHostIpcKnote
function TGuiIpcHandler.OnKevent(kev:p_kevent;count:Integer):Ptruint;
var
i:Integer;
begin
Result:=0;
i:=0;
while (i<>count) do
begin
case kev[i].filter of
EVFILT_PROC:
begin
if ((kev[i].fflags and NOTE_EXIT)<>0) then
begin
ShowMessage('NOTE_EXIT pid:'+IntToStr(kev[i].ident));
end;
if ((kev[i].fflags and NOTE_EXEC)<>0) then
begin
ShowMessage('NOTE_EXEC pid:'+IntToStr(kev[i].ident));
end;
end;
else;
end;
Inc(i);
end;
end;
var
IpcHandler:TGuiIpcHandler;
@ -409,7 +429,7 @@ begin
cfg.hOutput:=FAddHandle;
cfg.hError :=FAddHandle;
cfg.fork_proc:=False;
cfg.fork_proc:=True;
GameProcess:=run_item(cfg,Item);
end;

View File

@ -9,7 +9,7 @@ uses
sysutils,
vm,
vmparam,
kern_conf,
sys_conf,
sys_event,
time,
kern_mtx,
@ -38,7 +38,6 @@ uses
subr_backtrace,
sys_vm_object,
vm_pager,
kern_event,
md_time,
kern_proc,
kern_timeout;
@ -755,10 +754,13 @@ type
rout :PQWORD; //extraout of result
end;
var
f_eop_count:Integer=0;
Function dce_submit_flip(dev:p_cdev;data:p_submit_flip_args):Integer;
var
submit:t_submit_flip;
eop_val:PQWORD;
submit_eop:QWORD;
ures:QWORD;
begin
Result:=0;
@ -766,24 +768,12 @@ begin
if (data^.canary<>$a5a5) then Exit(EINVAL);
if (data^.bufferIndex>15) then Exit(EINVAL);
if (data^.eop_nz>1) then Exit(EINVAL);
submit.bufferIndex:=data^.bufferIndex;
submit.flipMode :=data^.flipMode;
submit.flipArg :=data^.flipArg;
submit.flipArg2 :=data^.flipArg2;
// count canary
//eop=0x[00000001] [ff] [00] [a5a5]
if (data^.eop_nz=1) then
begin
eop_val:=data^.eop_val;
end else
begin
eop_val:=nil;
end;
mtx_lock(dce_mtx);
if (dce_handle=nil) then
@ -791,7 +781,22 @@ begin
Result:=EINVAL;
end else
begin
Result:=dce_handle.SubmitFlip(@submit,eop_val);
if (data^.eop_nz=1) then
begin
// count canary
//eop=0x[00000001] [ff] [00] [a5a5]
f_eop_count:=f_eop_count+1;
submit_eop:=(QWORD(f_eop_count) shl 32) or QWORD($ff00a5a5);
Result:=dce_handle.SubmitFlipEop(@submit,submit_eop);
end else
begin
Result:=dce_handle.SubmitFlip(@submit);
end;
end;
mtx_unlock(dce_mtx);
@ -805,6 +810,11 @@ begin
flipArg:=data^.flipArg;
if (data^.eop_nz=1) then
begin
Result:=copyout(@submit_eop,data^.eop_val,SizeOf(QWORD));
end;
if (data^.rout<>nil) then
begin
ures:=Result;

View File

@ -6,7 +6,7 @@ unit dev_dipsw;
interface
uses
kern_conf;
sys_conf;
procedure dipsw_init();

View File

@ -6,7 +6,7 @@ unit dev_dmem;
interface
uses
kern_conf;
sys_conf;
procedure dmemdev_init();

View File

@ -6,7 +6,7 @@ unit dev_gc;
interface
uses
kern_conf;
sys_conf;
procedure gc_initialize();
@ -16,7 +16,6 @@ uses
errno,
kern_mtx,
sys_event,
kern_event,
kern_authinfo,
vm,
vmparam,
@ -265,6 +264,8 @@ var
cap:Boolean;
unk:Integer;
begin
Result:=0;
event_id:=Byte(kn^.kn_data);
cap:=sceSblACMgrHasUseHp3dPipeCapability(@g_authinfo);
@ -333,7 +334,7 @@ begin
begin
Result:=1;
event_id:=PByte(@kn^.kn_kevent.data)[1];
event_id:=Byte(kn^.kn_kevent.data shr 8);
kn^.kn_kevent.data:=(hint and QWORD($ffffffffffff00ff)) or
(QWORD(event_id) shl 8);

View File

@ -6,7 +6,7 @@ unit dev_null;
interface
uses
kern_conf;
sys_conf;
const
ZERO_REGION_SIZE=(2 * 1024 * 1024); // 2MB

View File

@ -6,7 +6,7 @@ unit dev_rng;
interface
uses
kern_conf;
sys_conf;
procedure rng_init();

View File

@ -9,7 +9,7 @@ uses
sysutils,
vselinfo,
kern_thr,
kern_conf,
sys_conf,
sys_tty;
var

235
sys/dev/devfs_int.pas Normal file
View File

@ -0,0 +1,235 @@
unit devfs_int;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
uses
mqueue,
time,
vfile,
vdirent,
vnode,
vmount,
sys_conf,
kern_mtx,
kern_sx;
const
DEVFS_MAGIC=$db0a087a;
{
* Identifiers. The ruleset and rule numbers are 16-bit values. The
* "rule ID" is a combination of the ruleset and rule number; it
* should be able to univocally describe a rule in the system. In
* this implementation, the upper 16 bits of the rule ID is the
* ruleset number; the lower 16 bits, the rule number within the
* aforementioned ruleset.
}
type
p_devfs_rnum=^devfs_rnum;
devfs_rnum=WORD;
p_devfs_rsnum=^devfs_rsnum;
devfs_rsnum=WORD;
p_devfs_rid=^devfs_rid;
devfs_rid=DWORD;
ino_t=Integer;
const
DRC_DSWFLAGS =$001;
DRC_PATHPTRN =$002;
DEVFS_MAXPTRNLEN=200;
DRA_BACTS =$001;
DRA_UID =$002;
DRA_GID =$004;
DRA_MODE =$008;
DRA_INCSET=$010;
DRB_HIDE =$001; { Hide entry (DE_WHITEOUT). }
DRB_UNHIDE=$002; { Unhide entry. }
{
* Plain DEVFS rule. This gets shared between kernel and userland
* verbatim, so it shouldn't contain any pointers or other kernel- or
* userland-specific values.
}
type
p_devfs_rule=^t_devfs_rule;
t_devfs_rule=packed record
dr_magic:DWORD; { Magic number. }
dr_id :devfs_rid; { Identifier. }
{
* Conditions under which this rule should be applied. These
* are ANDed together since OR can be simulated by using
* multiple rules. dr_icond determines which of the other
* variables we should process.
}
dr_icond:Integer;
dr_dswflags:Integer; { cdevsw flags to match. }
dr_pathptrn:array[0..DEVFS_MAXPTRNLEN-1] of AnsiChar; { Pattern to match path. }
{
* Things to change. dr_iacts determines which of the other
* variables we should process.
}
dr_iacts:Integer;
dr_bacts:Integer; { Boolean (on/off) action. }
dr_uid :uid_t;
dr_gid :gid_t;
dr_mode :mode_t;
dr_incset:devfs_rsnum; { Included ruleset. }
end;
const
{
* Rule-related ioctls.
}
DEVFSIO_RADD =$C0F04400;
DEVFSIO_RDEL =$80044401;
DEVFSIO_RAPPLY =$80F04402;
DEVFSIO_RAPPLYID=$80044403;
DEVFSIO_RGETNEXT=$C0F04404;
DEVFSIO_SUSE =$8002440A;
DEVFSIO_SAPPLY =$8002440B;
DEVFSIO_SGETNEXT=$C002440C;
{ XXX: DEVFSIO_RS_GET_INFO for refcount, active if any, etc. }
DE_WHITEOUT=$01;
DE_DOT =$02;
DE_DOTDOT =$04;
DE_DOOMED =$08;
DE_COVERED =$10;
DE_USER =$20;
CDP_ACTIVE =(1 shl 0);
CDP_SCHED_DTR=(1 shl 1);
CDP_UNREF_DTR=(1 shl 2);
type
t_cdpd_dtr=procedure(P:Pointer);
p_cdev_privdata=^t_cdev_privdata;
t_cdev_privdata=packed record
cdpd_fp :p_file;
cdpd_data:Pointer;
cdpd_dtr :t_cdpd_dtr;
cdpd_list:LIST_ENTRY; //cdev_privdata
end;
pp_devfs_dirent=^p_devfs_dirent;
p_devfs_dirent=^t_devfs_dirent;
p_cdev_priv=^t_cdev_priv;
t_cdev_priv=packed record
cdp_c:t_cdev;
cdp_list:TAILQ_ENTRY; //cdev_priv
cdp_inode:DWORD;
cdp_flags:DWORD;
cdp_inuse :DWORD;
cdp_maxdirent:DWORD;
cdp_dirents:pp_devfs_dirent;
cdp_dirent0:p_devfs_dirent;
cdp_dtr_list:TAILQ_ENTRY; //cdev_priv
cdp_dtr_cb :t_cdpd_dtr;
cdp_dtr_cb_arg:Pointer;
cdp_fdpriv:LIST_HEAD; //cdev_privdata
end;
devfs_dlist_head=TAILQ_HEAD; //devfs_dirent
t_devfs_dirent=record
de_cdp :p_cdev_priv;
de_inode :Integer;
de_flags :Integer;
de_holdcnt:Integer;
de_dirent :p_dirent;
de_list :TAILQ_ENTRY;
de_dlist :devfs_dlist_head;
de_dir :p_devfs_dirent;
de_links :Integer;
de_mode :mode_t;
de_uid :uid_t;
de_gid :gid_t;
//label *de_label;
de_atime :timespec;
de_mtime :timespec;
de_ctime :timespec;
de_vnode :p_vnode;
de_symlink:PChar;
end;
p_devfs_mount=^t_devfs_mount;
t_devfs_mount=record
dm_idx :DWORD ;
dm_mount :p_mount ;
dm_rootdir :p_devfs_dirent;
dm_generation:DWORD ;
dm_holdcnt :Integer ;
dm_lock :t_sx ;
dm_ruleset :devfs_rsnum ;
end;
const
DEVFS_ROOTINO=2;
DEVFS_DEL_VNLOCKED =$01;
DEVFS_DEL_NORECURSE=$02;
var
devfs_rule_depth:DWORD=0;
type
p_dirlistent=^t_dirlistent;
t_dirlistent=record
dir :PChar;
refcnt:Integer;
link :LIST_ENTRY; //dirlistent
end;
var
devfs_dirlist:LIST_HEAD=(lh_first:nil); //dirlistent
dirlist_mtx :mtx; //MTX_SYSINIT(dirlist_mtx, &dirlist_mtx, "devfs dirlist lock", MTX_DEF);
devfs_de_interlock:mtx; //MTX_SYSINIT(devfs_de_interlock, @devfs_de_interlock, 'devfs interlock', MTX_DEF);
cdevpriv_mtx :mtx; //MTX_SYSINIT(cdevpriv_mtx, @cdevpriv_mtx, 'cdevpriv lock', MTX_DEF);
clone_drain_lock :t_sx=(n:'clone events drain lock';c:nil;m:0);
devfs_generation:DWORD=0;
var
cdevp_list:TAILQ_HEAD=(tqh_first:nil;tqh_last:@cdevp_list.tqh_first);
function devfs_alloc(flags:Integer):p_cdev; external;
function devfs_dev_exists(name:PChar):Integer; external;
procedure devfs_free(cdev:p_cdev); external;
procedure devfs_create(dev:p_cdev); external;
procedure devfs_destroy(dev:p_cdev); external;
procedure devfs_destroy_cdevpriv(p:p_cdev_privdata); external;
function devfs_dir_find(path:PChar):Integer; external;
procedure devfs_dir_ref_de(dm:p_devfs_mount;de:p_devfs_dirent); external;
procedure devfs_dir_unref_de(dm:p_devfs_mount;de:p_devfs_dirent); external;
function devfs_pathpath(p1,p2:PChar):Integer; external;
implementation
end.

View File

@ -65,7 +65,8 @@ type
function SubmitBufferAttribute (attrid:Byte;attr:p_register_buffer_attr):Integer; virtual;
function RegisterBuffer (buf:p_register_buffer):Integer; virtual;
function UnregisterBuffer (index:Integer):Integer; virtual;
function SubmitFlip (submit:p_submit_flip;eop_val:PQWORD):Integer; virtual;
function SubmitFlip (submit:p_submit_flip):Integer; virtual;
function SubmitFlipEop (submit:p_submit_flip;submit_id:QWORD):Integer; virtual;
end;
TDisplayInterface=class
@ -118,11 +119,15 @@ begin
Result:=0;
end;
function TDisplayHandle.SubmitFlip(submit:p_submit_flip;eop_val:PQWORD):Integer;
function TDisplayHandle.SubmitFlip(submit:p_submit_flip):Integer;
begin
Result:=0;
end;
function TDisplayHandle.SubmitFlipEop(submit:p_submit_flip;submit_id:QWORD):Integer;
begin
Result:=0;
end;
end.

View File

@ -7,196 +7,13 @@ interface
uses
sysutils,
devfs_int,
mqueue,
kern_param,
vfile,
vdirent,
vnode,
vmount,
time,
kern_conf,
kern_mtx,
kern_sx;
const
DEVFS_MAGIC=$db0a087a;
{
* Identifiers. The ruleset and rule numbers are 16-bit values. The
* "rule ID" is a combination of the ruleset and rule number; it
* should be able to univocally describe a rule in the system. In
* this implementation, the upper 16 bits of the rule ID is the
* ruleset number; the lower 16 bits, the rule number within the
* aforementioned ruleset.
}
type
p_devfs_rnum=^devfs_rnum;
devfs_rnum=WORD;
p_devfs_rsnum=^devfs_rsnum;
devfs_rsnum=WORD;
p_devfs_rid=^devfs_rid;
devfs_rid=DWORD;
ino_t=Integer;
const
DRC_DSWFLAGS =$001;
DRC_PATHPTRN =$002;
DEVFS_MAXPTRNLEN=200;
DRA_BACTS =$001;
DRA_UID =$002;
DRA_GID =$004;
DRA_MODE =$008;
DRA_INCSET=$010;
DRB_HIDE =$001; { Hide entry (DE_WHITEOUT). }
DRB_UNHIDE=$002; { Unhide entry. }
{
* Plain DEVFS rule. This gets shared between kernel and userland
* verbatim, so it shouldn't contain any pointers or other kernel- or
* userland-specific values.
}
type
p_devfs_rule=^t_devfs_rule;
t_devfs_rule=packed record
dr_magic:DWORD; { Magic number. }
dr_id :devfs_rid; { Identifier. }
{
* Conditions under which this rule should be applied. These
* are ANDed together since OR can be simulated by using
* multiple rules. dr_icond determines which of the other
* variables we should process.
}
dr_icond:Integer;
dr_dswflags:Integer; { cdevsw flags to match. }
dr_pathptrn:array[0..DEVFS_MAXPTRNLEN-1] of AnsiChar; { Pattern to match path. }
{
* Things to change. dr_iacts determines which of the other
* variables we should process.
}
dr_iacts:Integer;
dr_bacts:Integer; { Boolean (on/off) action. }
dr_uid :uid_t;
dr_gid :gid_t;
dr_mode :mode_t;
dr_incset:devfs_rsnum; { Included ruleset. }
end;
const
{
* Rule-related ioctls.
}
DEVFSIO_RADD =$C0F04400;
DEVFSIO_RDEL =$80044401;
DEVFSIO_RAPPLY =$80F04402;
DEVFSIO_RAPPLYID=$80044403;
DEVFSIO_RGETNEXT=$C0F04404;
DEVFSIO_SUSE =$8002440A;
DEVFSIO_SAPPLY =$8002440B;
DEVFSIO_SGETNEXT=$C002440C;
{ XXX: DEVFSIO_RS_GET_INFO for refcount, active if any, etc. }
DE_WHITEOUT=$01;
DE_DOT =$02;
DE_DOTDOT =$04;
DE_DOOMED =$08;
DE_COVERED =$10;
DE_USER =$20;
CDP_ACTIVE =(1 shl 0);
CDP_SCHED_DTR=(1 shl 1);
CDP_UNREF_DTR=(1 shl 2);
type
t_cdpd_dtr=procedure(P:Pointer);
p_cdev_privdata=^t_cdev_privdata;
t_cdev_privdata=packed record
cdpd_fp :p_file;
cdpd_data:Pointer;
cdpd_dtr :t_cdpd_dtr;
cdpd_list:LIST_ENTRY; //cdev_privdata
end;
pp_devfs_dirent=^p_devfs_dirent;
p_devfs_dirent=^t_devfs_dirent;
p_cdev_priv=^t_cdev_priv;
t_cdev_priv=packed record
cdp_c:t_cdev;
cdp_list:TAILQ_ENTRY; //cdev_priv
cdp_inode:DWORD;
cdp_flags:DWORD;
cdp_inuse :DWORD;
cdp_maxdirent:DWORD;
cdp_dirents:pp_devfs_dirent;
cdp_dirent0:p_devfs_dirent;
cdp_dtr_list:TAILQ_ENTRY; //cdev_priv
cdp_dtr_cb :t_cdpd_dtr;
cdp_dtr_cb_arg:Pointer;
cdp_fdpriv:LIST_HEAD; //cdev_privdata
end;
devfs_dlist_head=TAILQ_HEAD; //devfs_dirent
t_devfs_dirent=record
de_cdp :p_cdev_priv;
de_inode :Integer;
de_flags :Integer;
de_holdcnt:Integer;
de_dirent :p_dirent;
de_list :TAILQ_ENTRY;
de_dlist :devfs_dlist_head;
de_dir :p_devfs_dirent;
de_links :Integer;
de_mode :mode_t;
de_uid :uid_t;
de_gid :gid_t;
//label *de_label;
de_atime :timespec;
de_mtime :timespec;
de_ctime :timespec;
de_vnode :p_vnode;
de_symlink:PChar;
end;
p_devfs_mount=^t_devfs_mount;
t_devfs_mount=record
dm_idx :DWORD ;
dm_mount :p_mount ;
dm_rootdir :p_devfs_dirent;
dm_generation:DWORD ;
dm_holdcnt :Integer ;
dm_lock :t_sx ;
dm_ruleset :devfs_rsnum ;
end;
const
DEVFS_ROOTINO=2;
DEVFS_DEL_VNLOCKED =$01;
DEVFS_DEL_NORECURSE=$02;
var
devfs_rule_depth:DWORD=0;
sys_conf,
kern_mtx;
function rid2rsn(rid:devfs_rid):devfs_rsnum;
function rid2rn (rid:devfs_rid):devfs_rnum;
@ -210,58 +27,38 @@ function DEVFS_DMP_DROP(dmp:p_devfs_mount):Boolean;
//
type
p_dirlistent=^t_dirlistent;
t_dirlistent=record
dir :PChar;
refcnt:Integer;
link :LIST_ENTRY; //dirlistent
end;
var
devfs_dirlist:LIST_HEAD=(lh_first:nil); //dirlistent
dirlist_mtx :mtx; //MTX_SYSINIT(dirlist_mtx, &dirlist_mtx, "devfs dirlist lock", MTX_DEF);
devfs_de_interlock:mtx; //MTX_SYSINIT(devfs_de_interlock, @devfs_de_interlock, 'devfs interlock', MTX_DEF);
cdevpriv_mtx :mtx; //MTX_SYSINIT(cdevpriv_mtx, @cdevpriv_mtx, 'cdevpriv lock', MTX_DEF);
clone_drain_lock :t_sx=(n:'clone events drain lock';c:nil;m:0);
devfs_generation:DWORD=0;
function devfs_dir_find(path:PChar):Integer;
function devfs_dir_findent_locked(dir:PChar):p_dirlistent;
procedure devfs_dir_ref(dir:PChar);
procedure devfs_dir_ref_de(dm:p_devfs_mount;de:p_devfs_dirent);
procedure devfs_dir_unref(dir:PChar);
procedure devfs_dir_unref_de(dm:p_devfs_mount;de:p_devfs_dirent);
function devfs_pathpath(p1,p2:PChar):Integer;
procedure devfs_mtx_init;
var
cdevp_list:TAILQ_HEAD=(tqh_first:nil;tqh_last:@cdevp_list.tqh_first);
function devfs_alloc(flags:Integer):p_cdev; external;
function devfs_dev_exists(name:PChar):Integer; external;
procedure devfs_free(cdev:p_cdev); external;
function devfs_find(dd:p_devfs_dirent;name:PChar;namelen:Integer;_type:Integer):p_devfs_dirent; external;
function devfs_newdirent(name:PChar;namelen:Integer):p_devfs_dirent; external;
function devfs_parent_dirent(de:p_devfs_dirent):p_devfs_dirent; external;
function devfs_vmkdir(dmp:p_devfs_mount;name:PChar;namelen:Integer;dotdot:p_devfs_dirent;inode:DWORD):p_devfs_dirent; external;
procedure devfs_dirent_free(de:p_devfs_dirent); external;
procedure devfs_rmdir_empty(dm:p_devfs_mount;de:p_devfs_dirent); external;
procedure devfs_delete(dm:p_devfs_mount;de:p_devfs_dirent;flags:Integer); external;
procedure devfs_purge(dm:p_devfs_mount;dd:p_devfs_dirent); external;
procedure devfs_metoo(cdp:p_cdev_priv;dm:p_devfs_mount); external;
function devfs_populate_loop(dm:p_devfs_mount;cleanup:Integer):Integer; external;
procedure devfs_populate(dm:p_devfs_mount); external;
procedure devfs_cleanup(dm:p_devfs_mount); external;
procedure devfs_create(dev:p_cdev); external;
procedure devfs_destroy(dev:p_cdev); external;
function devfs_alloc_cdp_inode():ino_t; external;
procedure devfs_free_cdp_inode(ino:ino_t); external;
procedure devfs_rules_apply(dm:p_devfs_mount;de:p_devfs_dirent); external;
procedure devfs_rules_cleanup(dm:p_devfs_mount); external;
function devfs_rules_ioctl(dm:p_devfs_mount;cmd:QWORD;data:Pointer):Integer; external;
procedure devfs_ruleset_set(rsnum:devfs_rsnum;dm:p_devfs_mount); external;
procedure devfs_ruleset_apply(dm:p_devfs_mount); external;
function devfs_allocv(de:p_devfs_dirent;mp:p_mount;lockmode:Integer;vpp:pp_vnode):Integer; external;
function devfs_fqpn(buf:PChar;dmp:p_devfs_mount;dd:p_devfs_dirent;cnp:Pointer):PChar; external;
procedure devfs_delete(dm:p_devfs_mount;de:p_devfs_dirent;flags:Integer); external;
procedure devfs_dirent_free(de:p_devfs_dirent); external;
procedure devfs_populate(dm:p_devfs_mount); external;
procedure devfs_cleanup(dm:p_devfs_mount); external;
procedure devfs_unmount_final(fmp:p_devfs_mount); external;
function devfs_newdirent(name:PChar;namelen:Integer):p_devfs_dirent; external;
function devfs_parent_dirent(de:p_devfs_dirent):p_devfs_dirent; external;
function devfs_vmkdir(dmp:p_devfs_mount;
name:PChar;namelen:Integer;
dotdot:p_devfs_dirent;
inode:DWORD):p_devfs_dirent; external;
function devfs_find(dd:p_devfs_dirent;
name:PChar;namelen:Integer;
_type:Integer):p_devfs_dirent; external;
implementation
{
@ -307,7 +104,7 @@ end;
//
{ Exits 1 if the path is in the directory list. }
function devfs_dir_find(path:PChar):Integer;
function devfs_dir_find(path:PChar):Integer; public;
var
dle:p_dirlistent;
begin
@ -414,7 +211,7 @@ begin
end;
end;
procedure devfs_dir_unref_de(dm:p_devfs_mount;de:p_devfs_dirent);
procedure devfs_dir_unref_de(dm:p_devfs_mount;de:p_devfs_dirent); public;
var
dirname:array[0..SPECNAMELEN] of AnsiChar;
namep:PChar;
@ -426,7 +223,7 @@ begin
end;
{ Exits 1 if the path p1 contains the path p2. }
function devfs_pathpath(p1,p2:PChar):Integer;
function devfs_pathpath(p1,p2:PChar):Integer; public;
begin
repeat
if (p1^<>p2^) then

View File

@ -8,7 +8,8 @@ interface
uses
mqueue,
kern_id,
kern_conf,
sys_conf,
devfs_int,
devfs;
function devfs_alloc(flags:Integer):p_cdev;
@ -42,8 +43,7 @@ uses
kern_sx,
vfs_vnops,
vfs_subr,
vnode_if,
devfs_rule;
vnode_if;
var
devfs_desc:t_id_desc=(free:nil;refs:0);

View File

@ -8,7 +8,8 @@ interface
uses
mqueue,
kern_param,
kern_conf,
sys_conf,
devfs_int,
devfs,
kern_sx;
@ -84,7 +85,7 @@ uses
* exposed to the userland. This should be called with an exclusive
* lock on dm in case we need to run anything.
}
procedure devfs_rules_apply(dm:p_devfs_mount;de:p_devfs_dirent);
procedure devfs_rules_apply(dm:p_devfs_mount;de:p_devfs_dirent); public;
var
ds:p_devfs_ruleset;
begin
@ -104,7 +105,7 @@ end;
{
* Rule subsystem ioctl hook.
}
function devfs_rules_ioctl(dm:p_devfs_mount;cmd:QWORD;data:Pointer):Integer;
function devfs_rules_ioctl(dm:p_devfs_mount;cmd:QWORD;data:Pointer):Integer; public;
label
_break;
var
@ -807,7 +808,7 @@ begin
Exit(0);
end;
procedure devfs_rules_cleanup(dm:p_devfs_mount);
procedure devfs_rules_cleanup(dm:p_devfs_mount); public;
var
ds:p_devfs_ruleset;
begin
@ -823,7 +824,7 @@ end;
{
* Make rsnum the active ruleset for dm (locked)
}
procedure devfs_ruleset_set(rsnum:devfs_rsnum;dm:p_devfs_mount);
procedure devfs_ruleset_set(rsnum:devfs_rsnum;dm:p_devfs_mount); public;
begin
sx_assert(@dm^.dm_lock);
sx_xlock(@sx_rules);
@ -834,7 +835,7 @@ end;
{
* Apply the current active ruleset on a mount
}
procedure devfs_ruleset_apply(dm:p_devfs_mount);
procedure devfs_ruleset_apply(dm:p_devfs_mount); public;
var
ds:p_devfs_ruleset;
begin

View File

@ -9,6 +9,7 @@ uses
kern_param,
vnode,
vmount,
devfs_int,
devfs,
kern_id;
@ -66,13 +67,7 @@ uses
vfs_mount,
vfs_subr,
vnode_if,
devfs_rule;
//
function devfs_allocv(de:p_devfs_dirent;mp:p_mount;lockmode:Integer;vpp:pp_vnode):Integer; external;
//
devfs_devs;
var
unr_desc:t_id_desc=(free:nil;refs:0);
@ -217,7 +212,7 @@ begin
Exit(0);
end;
procedure devfs_unmount_final(fmp:p_devfs_mount);
procedure devfs_unmount_final(fmp:p_devfs_mount); public;
begin
sx_destroy(@fmp^.dm_lock);
FreeMem(fmp);

View File

@ -23,10 +23,11 @@ uses
vnode_if,
vfs_default,
vfs_vnops,
devfs_int,
devfs,
kern_mtx,
kern_sx,
kern_conf;
sys_conf;
function devfs_fp_check(fp:p_file;devp:pp_cdev;dswp:pp_cdevsw;ref:PInteger):Integer;
function devfs_get_cdevpriv(datap:PPointer):Integer;
@ -200,8 +201,7 @@ uses
kern_thr,
vfs_subr,
vsys_generic,
devfs_rule,
devfs_vfsops,
//devfs_vfsops,
kern_proc,
kern_descrip,
kern_mtxpool,
@ -236,7 +236,7 @@ begin
Exit(0);
end;
function devfs_get_cdevpriv(datap:PPointer):Integer;
function devfs_get_cdevpriv(datap:PPointer):Integer; public;
var
fp:p_file;
p:p_cdev_privdata;
@ -258,7 +258,7 @@ begin
Exit(error);
end;
function devfs_set_cdevpriv(priv:Pointer;priv_dtr:cdevpriv_dtr_t):Integer;
function devfs_set_cdevpriv(priv:Pointer;priv_dtr:cdevpriv_dtr_t):Integer; public;
var
fp:p_file;
cdp:p_cdev_priv;
@ -289,7 +289,7 @@ begin
Exit(error);
end;
procedure devfs_destroy_cdevpriv(p:p_cdev_privdata);
procedure devfs_destroy_cdevpriv(p:p_cdev_privdata); public;
begin
mtx_assert(cdevpriv_mtx);
p^.cdpd_fp^.f_cdevpriv:=nil;
@ -299,7 +299,7 @@ begin
FreeMem(p);
end;
procedure devfs_fpdrop(fp:p_file);
procedure devfs_fpdrop(fp:p_file); public;
var
p:p_cdev_privdata;
begin
@ -313,7 +313,7 @@ begin
devfs_destroy_cdevpriv(p);
end;
procedure devfs_clear_cdevpriv();
procedure devfs_clear_cdevpriv(); public;
var
fp:p_file;
begin

View File

@ -6,17 +6,20 @@ interface
uses
Classes,
time,
mqueue,
LFQueue,
kern_thr,
kern_thread,
sys_event,
kern_mtx;
type
t_mtype=(
iRESULT,
iMOUNT,
iKNOTE
iKEV_CHANGE,
iKEV_EVENT,
iMOUNT
);
PNodeHeader=^TNodeHeader;
@ -42,13 +45,6 @@ type
tid :DWORD;
end;
PHostIpcKnote=^THostIpcKnote;
THostIpcKnote=packed record
pid :Integer;
filter:Integer;
hint :QWORD
end;
THostIpcHandler=class
function OnMessage(mtype:t_mtype;mlen:DWORD;buf:Pointer):Ptruint; virtual;
end;
@ -58,6 +54,7 @@ type
FQueue:TIntrusiveMPSCQueue;
FWaits:LIST_HEAD;
FWLock:mtx;
Fkq:Pointer;
procedure SyncResult(tid:DWORD;value:Ptruint);
function NewNodeSync:PNodeIpcSync;
procedure FreeNodeSync(node:PNodeIpcSync);
@ -66,9 +63,12 @@ type
function Recv:PQNode;
procedure Flush;
procedure RecvSync(node:PQNode);
procedure RecvKevent(node:PQNode);
procedure UpdateKevent();
procedure WakeupKevent(); virtual;
public
//
procedure knote(pid,filter:Integer;hint:QWORD);
procedure kevent(kev:p_kevent;count:Integer);
//
function SendSync(mtype:t_mtype;mlen:DWORD;buf:Pointer):Ptruint;
procedure SendAsyn(mtype:t_mtype;mlen:DWORD;buf:Pointer);
@ -77,6 +77,8 @@ type
//
Constructor Create;
Destructor Destroy; override;
procedure thread_new; virtual;
procedure thread_free; virtual;
end;
THostIpcSimpleKERN=class;
@ -93,15 +95,17 @@ type
FHandler:THostIpcHandler;
Constructor Create;
Destructor Destroy; override;
procedure thread_new; override;
procedure thread_free; override;
procedure Send(mtype:t_mtype;mlen,mtid:DWORD;buf:Pointer); override;
procedure Update(Handler:THostIpcHandler); override;
procedure WakeupKevent(); override;
end;
implementation
function THostIpcHandler.OnMessage(mtype:t_mtype;mlen:DWORD;buf:Pointer):Ptruint;
begin
//
Result:=0;
end;
Constructor THostIpcConnect.Create;
@ -115,9 +119,23 @@ Destructor THostIpcConnect.Destroy;
begin
Flush;
mtx_destroy(FWLock);
if (Fkq<>nil) then
begin
kqueue_close2(Fkq);
end;
inherited;
end;
procedure THostIpcConnect.thread_new;
begin
//
end;
procedure THostIpcConnect.thread_free;
begin
//
end;
procedure THostIpcConnect.Pack(mtype:t_mtype;mlen,mtid:DWORD;buf:Pointer);
var
node:PQNode;
@ -166,6 +184,64 @@ begin
TriggerNodeSync(node^.header.mtid,value);
end;
procedure kq_wakeup(data:Pointer); SysV_ABI_CDecl;
begin
THostIpcConnect(data).WakeupKevent();
end;
procedure THostIpcConnect.RecvKevent(node:PQNode);
var
kev:p_kevent;
value:Ptruint;
count:Integer;
begin
kev :=@node^.buf;
count:=node^.header.mlen div SizeOf(t_kevent);
Writeln('RecvKevent ',kev^.ident,' ',count);
if (Fkq=nil) then
begin
Fkq:=kern_kqueue2('[ipc]',@kq_wakeup,Pointer(Self));
end;
//changelist
value:=kern_kevent2(Fkq,kev,count,nil,0,nil,@count);
//is sync
if (node^.header.mtid<>0) then
begin
SyncResult(node^.header.mtid,value);
end;
end;
procedure THostIpcConnect.UpdateKevent();
var
kev:array[0..7] of t_kevent;
t:timespec;
r:Integer;
begin
if (Fkq=nil) then Exit;
t:=Default(timespec);
repeat
r:=0;
kern_kevent2(Fkq,nil,0,@kev,8,@t,@r);
if (r>0) then
begin
SendAsyn(iKEV_EVENT,r*SizeOf(t_kevent),@kev);
end;
until (r<>8);
end;
procedure THostIpcConnect.WakeupKevent();
begin
//
end;
procedure THostIpcConnect.Update(Handler:THostIpcHandler);
var
node:PQNode;
@ -175,21 +251,25 @@ begin
while (node<>nil) do
begin
//
if (node^.header.mtype=DWORD(iRESULT)) then
begin
RecvSync(node);
end else
if (Handler<>nil) then
begin
value:=Handler.OnMessage(t_mtype(node^.header.mtype),node^.header.mlen,@node^.buf);
//is sync
if (node^.header.mtid<>0) then
begin
SyncResult(node^.header.mtid,value);
end;
case t_mtype(node^.header.mtype) of
iRESULT :RecvSync(node);
iKEV_CHANGE:RecvKevent(node);
else
if (Handler<>nil) then
begin
value:=Handler.OnMessage(t_mtype(node^.header.mtype),node^.header.mlen,@node^.buf);
//is sync
if (node^.header.mtid<>0) then
begin
SyncResult(node^.header.mtid,value);
end;
end;
end;
//
FreeMem(node);
//
@ -204,15 +284,9 @@ begin
Send(iRESULT,SizeOf(Ptruint),tid,@value);
end;
procedure THostIpcConnect.knote(pid,filter:Integer;hint:QWORD);
var
note:THostIpcKnote;
procedure THostIpcConnect.kevent(kev:p_kevent;count:Integer);
begin
note.pid :=pid;
note.filter:=filter;
note.hint :=hint;
//
SendAsyn(iKNOTE,SizeOf(note),@note);
SendAsyn(iKEV_CHANGE,count*SizeOf(t_kevent),kev);
end;
//
@ -312,6 +386,10 @@ begin
ipc:=THostIpcSimpleKERN(parameter);
repeat
if ipc.FQueue.IsEmpty then
begin
RTLEventWaitFor(ipc.FEvent);
end;
ipc.Update(ipc.FHandler);
until false;
@ -321,24 +399,30 @@ Constructor THostIpcSimpleKERN.Create;
begin
inherited;
FEvent:=RTLEventCreate;
Ftd:=nil;
kthread_add(@simple_kern_thread,Self,@Ftd,'[ipc_pipe]');
end;
Destructor THostIpcSimpleKERN.Destroy;
begin
thread_dec_ref(Ftd);
thread_free;
RTLEventDestroy(FEvent);
inherited;
end;
procedure THostIpcSimpleKERN.Update(Handler:THostIpcHandler);
procedure THostIpcSimpleKERN.thread_new;
begin
if FQueue.IsEmpty then
if (Ftd=nil) then
begin
RTLEventWaitFor(FEvent);
kthread_add(@simple_kern_thread,Self,@Ftd,'[ipc_pipe]');
end;
end;
procedure THostIpcSimpleKERN.thread_free;
begin
if (Ftd<>nil) then
begin
thread_dec_ref(Ftd);
Ftd:=nil;
end;
inherited Update(Handler);
end;
procedure THostIpcSimpleKERN.Send(mtype:t_mtype;mlen,mtid:DWORD;buf:Pointer);
@ -355,5 +439,10 @@ begin
end;
end;
procedure THostIpcSimpleKERN.WakeupKevent();
begin
UpdateKevent();
end;
end.

View File

@ -15,7 +15,7 @@ uses
kern_descrip,
vfile,
vfcntl,
kern_conf,
sys_conf,
vstat;
function blockpool_ioctl(fp:p_file;com:QWORD;data:Pointer):Integer;

View File

@ -99,18 +99,18 @@ function kqfd_register(fd:Integer;kev:p_kevent):Integer;
function sys_kqueue():Integer;
function sys_kqueueex(name:PChar):Integer;
function sys_kevent(fd:Integer;
function sys_kevent(fd :Integer;
changelist:Pointer;
nchanges:Integer;
eventlist:Pointer;
nevents:Integer;
timeout:Pointer):Integer;
nchanges :Integer;
eventlist :Pointer;
nevents :Integer;
timeout :Pointer):Integer;
implementation
uses
errno,
md_proc,
md_time,
kern_sig,
kern_sx,
@ -438,7 +438,7 @@ begin
immediate:=1;
end;
kn^.kn_ptr.p_proc:=nil;
kn^.kn_ptr.p_proc:=@p_proc;
kn^.kn_flags:=kn^.kn_flags or EV_CLEAR; { automatically set }
{
@ -453,7 +453,7 @@ begin
if (immediate=0) then
begin
knlist_add(@p_proc.p_klist, kn, 1);
knlist_add(@p_proc.p_klist, kn, 0);
end;
{
@ -843,7 +843,34 @@ end;
//
function kern_kqueue(pfd:PInteger;name:PAnsiChar):Integer;
function kern_kqueue2(name:PAnsiChar;
w_cb:t_kqueue_wakeup_cb;
data:Pointer):p_kqueue; public;
var
kq:p_kqueue;
begin
kq:=AllocMem(SizeOf(t_kqueue));
if (kq=nil) then Exit;
mtx_init(kq^.kq_lock, 'kqueue');
TAILQ_INIT(@kq^.kq_head);
//kq^.kq_fdp:=fdp;
knlist_init_mtx(@kq^.kq_sel.si_note, @kq^.kq_lock);
//TASK_INIT(@kq^.kq_task, 0, kqueue_task, kq);
if (name<>nil) then
begin
kq^.kq_name:=name;
end;
kq^.kq_wakeup:=w_cb;
kq^.kq_data :=data;
Result:=kq;
end;
function kern_kqueue(pfd :PInteger;
name:PAnsiChar):Integer;
var
kq:p_kqueue;
fp:p_file;
@ -856,18 +883,9 @@ begin
if (error<>0) then Exit(error);
{ An extra reference on `nfp' has been held for us by falloc(). }
kq:=AllocMem(SizeOf(t_kqueue));
mtx_init(kq^.kq_lock, 'kqueue');
TAILQ_INIT(@kq^.kq_head);
//kq^.kq_fdp:=fdp;
knlist_init_mtx(@kq^.kq_sel.si_note, @kq^.kq_lock);
//TASK_INIT(@kq^.kq_task, 0, kqueue_task, kq);
if (name<>nil) then
begin
kq^.kq_name:=name;
end;
kq:=kern_kqueue2(name,nil,nil);
if (kq=nil) then Exit(ENOMEM);
FILEDESC_XLOCK(@fd_table);
TAILQ_INSERT_HEAD(@fd_table.fd_kqlist, kq, @kq^.kq_list);
@ -922,12 +940,10 @@ end;
type
p_kevent_args=^t_kevent_args;
t_kevent_args=record
fd :Integer;
changelist:p_kevent;
nchanges :Integer;
eventlist :p_kevent;
nevents :Integer;
timeout :p_timespec;
end;
{
@ -949,6 +965,19 @@ begin
Exit(error);
end;
function kevent_copyout2(arg:Pointer;kevp:p_kevent;count:Integer):Integer;
var
uap:p_kevent_args;
begin
Assert(count <= KQ_NEVENTS, Format('count (%d) > KQ_NEVENTS', [count]));
uap:=arg;
Move(kevp^,uap^.eventlist^,count*sizeof(t_kevent));
Inc(uap^.eventlist,count);
Result:=0;
end;
{
* Copy 'count' items from the list pointed to by uap^.changelist.
}
@ -968,23 +997,97 @@ begin
Exit(error);
end;
function kevent_copyin2(arg:Pointer;kevp:p_kevent;count:Integer):Integer;
var
uap:p_kevent_args;
begin
Assert(count <= KQ_NEVENTS, Format('count (%d) > KQ_NEVENTS', [count]));
uap:=arg;
Move(uap^.changelist^,kevp^,count*sizeof(t_kevent));
Inc(uap^.changelist,count);
Result:=0;
end;
function _kern_kevent(td:p_kthread;
kq:p_kqueue;
nchanges:Integer;
nevents:Integer;
k_ops:p_kevent_copyops;
timeout:p_timespec):Integer;
type
t_keva=array[0..KQ_NEVENTS-1] of t_kevent;
var
keva:t_keva;
kevp,changes:p_kevent;
i,n,nerrors:Integer;
begin
Result:=0;
nerrors:=0;
keva:=Default(t_keva);
while (nchanges > 0) do
begin
if (nchanges > KQ_NEVENTS) then
n:=KQ_NEVENTS
else
n:=nchanges;
Result:=k_ops^.k_copyin(k_ops^.arg, keva, n);
if (Result<>0) then Exit; //goto done;
changes:=keva;
For i:=0 to n-1 do
begin
kevp:=@changes[i];
if (kevp^.filter=0) then continue;
kevp^.flags:=kevp^.flags and (not EV_SYSFLAGS);
Result:=kqueue_register(kq, kevp);
if (Result<>0) or ((kevp^.flags and EV_RECEIPT)<>0) then
begin
if (nevents<>0) then
begin
kevp^.flags:=EV_ERROR;
kevp^.data :=Result;
k_ops^.k_copyout(k_ops^.arg, kevp, 1);
Dec(nevents);
Inc(nerrors);
end else
begin
Exit(0); //goto done;
end;
end;
end;
Dec(nchanges,n);
end;
if (nerrors<>0) then
begin
td^.td_retval[0]:=nerrors;
Exit(0); //goto done;
end;
Result:=kqueue_scan(kq, nevents, k_ops, timeout, keva);
end;
function kern_kevent(fd:Integer;
nchanges:Integer;
nevents:Integer;
k_ops:p_kevent_copyops;
timeout:p_timespec):Integer;
label
done_norel,
done;
done_norel;
type
t_keva=array[0..KQ_NEVENTS-1] of t_kevent;
var
td:p_kthread;
keva:t_keva;
kevp,changes:p_kevent;
kq:p_kqueue;
fp:p_file;
i,n,nerrors,error:Integer;
error:Integer;
begin
td:=curkthread;
if (td=nil) then Exit(-1);
@ -1007,64 +1110,27 @@ begin
Writeln('kern_kevent:',kq^.kq_name);
nerrors:=0;
keva:=Default(t_keva);
error:=_kern_kevent(td,
kq,
nchanges,
nevents,
k_ops,
timeout);
while (nchanges > 0) do
begin
if (nchanges > KQ_NEVENTS) then
n:=KQ_NEVENTS
else
n:=nchanges;
error:=k_ops^.k_copyin(k_ops^.arg, keva, n);
if (error<>0) then goto done;
changes:=keva;
For i:=0 to n-1 do
begin
kevp:=@changes[i];
if (kevp^.filter=0) then continue;
kevp^.flags:=kevp^.flags and (not EV_SYSFLAGS);
error:=kqueue_register(kq, kevp);
if (error<>0) or ((kevp^.flags and EV_RECEIPT)<>0) then
begin
if (nevents<>0) then
begin
kevp^.flags:=EV_ERROR;
kevp^.data :=error;
k_ops^.k_copyout(k_ops^.arg, kevp, 1);
Dec(nevents);
Inc(nerrors);
end else
begin
goto done;
end;
end;
end;
Dec(nchanges,n);
end;
if (nerrors<>0) then
begin
td^.td_retval[0]:=nerrors;
error:=0;
goto done;
end;
error:=kqueue_scan(kq, nevents, k_ops, timeout, keva);
done:
//done:
kqueue_release(kq, 0);
done_norel:
fdrop(fp);
Exit(error);
end;
function sys_kevent(fd:Integer;
function sys_kevent(fd :Integer;
changelist:Pointer;
nchanges:Integer;
eventlist:Pointer;
nevents:Integer;
timeout:Pointer):Integer;
nchanges :Integer;
eventlist :Pointer;
nevents :Integer;
timeout :Pointer):Integer;
var
ts:timespec;
tsp:p_timespec;
@ -1082,12 +1148,10 @@ begin
tsp:=nil;
end;
uap.fd :=fd ;
uap.changelist:=changelist;
uap.nchanges :=nchanges ;
uap.eventlist :=eventlist ;
uap.nevents :=nevents ;
uap.timeout :=timeout ;
k_ops.arg :=@uap;
k_ops.k_copyout:=@kevent_copyout;
@ -1098,7 +1162,44 @@ begin
Exit(error);
end;
function kqueue_add_filteropts(filt:Integer;filtops:p_filterops):Integer;
function kern_kevent2(kq :p_kqueue;
changelist:p_kevent;
nchanges :Integer;
eventlist :p_kevent;
nevents :Integer;
timeout :p_timespec;
p_ncount :PInteger):Integer; public;
var
td:p_kthread;
error:Integer;
uap:t_kevent_args;
k_ops:t_kevent_copyops;
begin
td:=curkthread;
if (td=nil) then Exit(-1);
uap.changelist:=changelist;
uap.nchanges :=nchanges ;
uap.eventlist :=eventlist ;
uap.nevents :=nevents ;
k_ops.arg :=@uap;
k_ops.k_copyout:=@kevent_copyout2;
k_ops.k_copyin :=@kevent_copyin2;
error:=_kern_kevent(td,
kq,
nchanges,
nevents,
@k_ops,
timeout);
p_ncount^:=td^.td_retval[0];
Exit(error);
end;
function kqueue_add_filteropts(filt:Integer;filtops:p_filterops):Integer; public;
var
error:Integer;
begin
@ -1123,7 +1224,7 @@ begin
Exit(error);
end;
function kqueue_del_filteropts(filt:Integer):Integer;
function kqueue_del_filteropts(filt:Integer):Integer; public;
var
error:Integer;
begin
@ -1349,7 +1450,7 @@ findkn:
kev^.fflags:=0;
kev^.data:=0;
kn^.kn_kevent:=kev^;
kn^.kn_kevent.flags:=kn^.kn_kevent.flags and (not (EV_ADD or EV_DELETE or EV_ENABLE or EV_DISABLE));
kn^.kn_kevent.flags:=kn^.kn_kevent.flags and (not EV_ACTION);
kn^.kn_status:=KN_INFLUX or KN_DETACHED;
error:=knote_attach(kn, kq);
@ -1462,7 +1563,7 @@ done:
Exit(error);
end;
procedure kqueue_deregister(filter:SmallInt;pid,ident:PtrUint);
procedure kqueue_deregister(filter:SmallInt;pid,ident:PtrUint); public;
label
_lock,
_again;
@ -2018,21 +2119,13 @@ begin
Exit(0);
end;
{ARGSUSED}
function kqueue_close(fp:p_file):Integer;
procedure kqueue_close2(kq:p_kqueue); public;
var
kq:p_kqueue;
kn:p_knote;
i:Integer;
error:Integer;
filedesc_unlock:Integer;
begin
kq:=fp^.f_data;
if (kq=nil) then Exit;
error:=kqueue_acquire(fp, @kq);
if (error<>0) then Exit(error);
filedesc_unlock:=0;
KQ_LOCK(kq);
Assert((kq^.kq_state and KQ_CLOSING)<>KQ_CLOSING,'kqueue already closing');
@ -2120,6 +2213,39 @@ begin
KQ_UNLOCK(kq);
seldrain(@kq^.kq_sel);
knlist_destroy(@kq^.kq_sel.si_note);
mtx_destroy(kq^.kq_lock);
//kq^.kq_fdp:=nil;
if (kq^.kq_knhash<>nil) then
begin
FreeMem(kq^.kq_knhash);
end;
if (kq^.kq_knlist<>nil) then
begin
FreeMem(kq^.kq_knlist);
end;
//funsetown(@kq^.kq_sigio);
FreeMem(kq);
end;
{ARGSUSED}
function kqueue_close(fp:p_file):Integer;
var
kq:p_kqueue;
error:Integer;
filedesc_unlock:Integer;
begin
kq:=fp^.f_data;
error:=kqueue_acquire(fp, @kq);
if (error<>0) then Exit(error);
filedesc_unlock:=0;
{
* We could be called due to the knote_drop() doing fdrop(),
* called from kqueue_register(). In this case the global
@ -2142,22 +2268,8 @@ begin
FILEDESC_XUNLOCK(@fd_table);
end;
seldrain(@kq^.kq_sel);
knlist_destroy(@kq^.kq_sel.si_note);
mtx_destroy(kq^.kq_lock);
//kq^.kq_fdp:=nil;
kqueue_close2(kq);
if (kq^.kq_knhash<>nil) then
begin
FreeMem(kq^.kq_knhash);
end;
if (kq^.kq_knlist<>nil) then
begin
FreeMem(kq^.kq_knlist);
end;
//funsetown(@kq^.kq_sigio);
FreeMem(kq);
fp^.f_data:=nil;
Exit(0);
@ -2188,6 +2300,12 @@ begin
begin
//pgsigio(@kq^.kq_sigio, SIGIO, 0);
end;
if (kq^.kq_wakeup<>nil) then
begin
kq^.kq_wakeup(kq^.kq_data);
end;
end;
{
@ -2655,6 +2773,7 @@ begin
TAILQ_INSERT_TAIL(@kq^.kq_head,kn,@kn^.kn_tqe);
kn^.kn_status:=kn^.kn_status or KN_QUEUED;
Inc(kq^.kq_count);
kqueue_wakeup(kq);
end;
@ -2697,7 +2816,7 @@ end;
{
* Register the kev w/ the kq specified by fd.
}
function kqfd_register(fd:Integer;kev:p_kevent):Integer;
function kqfd_register(fd:Integer;kev:p_kevent):Integer; public;
label
noacquire;
var

View File

@ -59,7 +59,6 @@ uses
sys_resource,
kern_resource,
sys_event,
kern_event,
machdep,
kern_dlsym,
kern_authinfo,

View File

@ -70,7 +70,7 @@ uses
systm,
kern_proc,
sys_event,
kern_event,
md_sleep,
md_proc;
function _WSTATUS(x:Integer):Integer; inline;
@ -136,6 +136,9 @@ begin
if halt_on_exit then
begin
md_halt(rv);
end else
begin
msleep_td(0);
end;
end;

View File

@ -129,48 +129,9 @@ begin
mtx_unlock(p_proc.p_mtx);
end;
function filt_host_ipc_attach(kn:p_knote):Integer;
begin
Result:=0;
end;
procedure filt_host_ipc_detach(kn:p_knote);
begin
//
end;
function filt_host_ipc_event(kn:p_knote;hint:QWORD):Integer;
begin
p_proc.p_host_ipc.knote(p_proc.p_pid,EVFILT_PROC,hint);
Result:=0;
end;
const
filterops_host_ipc:t_filterops=(
f_isfd :0;
_align :0;
f_attach:@filt_host_ipc_attach;
f_detach:@filt_host_ipc_detach;
f_event :@filt_host_ipc_event;
);
procedure PROC_INIT_HOST_IPC(host_ipc:THostIpcConnect);
var
kn:p_knote;
begin
if (host_ipc=nil) then Exit;
p_proc.p_host_ipc:=host_ipc;
kn:=knote_alloc();
kn^.kn_fop:=@filterops_host_ipc;
kn^.kn_status:=KN_INFLUX or KN_DETACHED or KN_SCAN;
kn^.kn_ptr.p_proc:=@p_proc;
kn^.kn_flags:=kn^.kn_flags or EV_CLEAR;
knlist_add(@p_proc.p_klist, kn, 0);
end;
procedure PROC_INIT;

View File

@ -14,7 +14,7 @@ implementation
uses
kern_thr,
kern_descrip,
kern_conf,
sys_conf,
vsocket,
vfile,
vfcntl,

View File

@ -13,6 +13,7 @@ uses
machdep,
md_context,
md_proc,
kern_exit,
kern_thr,
subr_backtrace,
trap,
@ -330,8 +331,6 @@ begin
Writeln(stderr,_get_msg(Msg),' (',FName,', line ',LineNo,').');
print_backtrace(stderr,Get_pc_addr,get_frame,2);
//sleep(-1);
if IsDebuggerPresent then
Raise EAssertionFailed.
Createfmt('%s (%s, line %d).',
@ -343,9 +342,7 @@ begin
// int3
//end;
sleep(-1);
md_halt(217);
kern_exit.exit1(217);
end;
var

View File

@ -35,9 +35,8 @@ type
procedure set_pipe(fd:THandle);
procedure Recv; virtual;
Function Push(Node:Pointer):Boolean; virtual;
procedure thread_new; virtual;
procedure thread_free; virtual;
procedure Send(mtype:t_mtype;mlen,mtid:DWORD;buf:Pointer); override;
procedure WakeupKevent(); override;
Constructor Create;
Destructor Destroy; override;
end;
@ -168,26 +167,26 @@ begin
Result:=FQueue.Push(node);
end;
procedure THostIpcPipe.thread_new;
begin
//
end;
procedure THostIpcPipe.thread_free;
begin
//
end;
procedure THostIpcPipe.Send(mtype:t_mtype;mlen,mtid:DWORD;buf:Pointer);
begin
proto.Send(mtype,mlen,mtid,buf);
end;
Procedure ev_wakeup(param1:SizeUInt;param2:Pointer); register;
begin
THostIpcPipe(param2).UpdateKevent();
end;
procedure THostIpcPipe.WakeupKevent();
begin
evpoll_post(@evpoll,@ev_wakeup,0,Pointer(Self));
end;
Constructor THostIpcPipe.Create;
begin
inherited;
evpoll_init(@evpoll,nil);
thread_new;
//thread_new;
end;
Destructor THostIpcPipe.Destroy;
@ -213,13 +212,20 @@ end;
procedure THostIpcPipeMGUI.thread_new;
begin
Ftd:=BeginThread(@pipe_gui_thread,@evpoll);
if (Ftd=0) then
begin
Ftd:=BeginThread(@pipe_gui_thread,@evpoll);
end;
end;
procedure THostIpcPipeMGUI.thread_free;
begin
WaitForThreadTerminate(Ftd,0);
CloseThread(Ftd);
if (Ftd<>0) then
begin
WaitForThreadTerminate(Ftd,0);
CloseThread(Ftd);
Ftd:=0;
end;
end;
//
@ -233,13 +239,19 @@ end;
procedure THostIpcPipeKERN.thread_new;
begin
Ftd:=nil;
kthread_add(@pipe_kern_thread,@evpoll,@Ftd,'[ipc_pipe]');
if (Ftd=nil) then
begin
kthread_add(@pipe_kern_thread,@evpoll,@Ftd,'[ipc_pipe]');
end;
end;
procedure THostIpcPipeKERN.thread_free;
begin
thread_dec_ref(Ftd);
if (Ftd<>nil) then
begin
thread_dec_ref(Ftd);
Ftd:=nil;
end;
end;

View File

@ -13,6 +13,12 @@ uses
type
t_fork_cb=procedure(data:Pointer;size:QWORD); SysV_ABI_CDecl;
p_fork_proc=^t_fork_proc;
t_fork_proc=record
hProcess:THandle;
fork_pid:Integer;
end;
function md_copyin (hProcess:THandle;udaddr,kaddr:Pointer;len:ptruint;lencopied:pptruint):Integer;
function md_copyout(hProcess:THandle;kaddr,udaddr:Pointer;len:ptruint;lencopied:pptruint):Integer;
@ -25,7 +31,7 @@ function md_pidfd_open (pid:DWORD):THandle;
procedure md_run_forked;
procedure md_fork_unshare;
function md_fork_process(proc:Pointer;data:Pointer;size:QWORD):THandle;
function md_fork_process(proc:Pointer;data:Pointer;size:QWORD;var info:t_fork_proc):Integer;
implementation
@ -172,23 +178,23 @@ function SetInformationJobObject(hJob:HANDLE;
function AssignProcessToJobObject(hJob,hProcess:THandle):BOOL; stdcall; external kernel32;
function NtQueryTeb(td_handle:THandle):p_teb;
function NtQueryTeb(td_handle:THandle;var teb:p_teb):Integer;
var
TBI:THREAD_BASIC_INFORMATION;
err:Integer;
begin
Result:=nil;
Result:=0;
teb:=nil;
TBI:=Default(THREAD_BASIC_INFORMATION);
err:=NtQueryInformationThread(
td_handle,
ThreadBasicInformation,
@TBI,
SizeOf(THREAD_BASIC_INFORMATION),
nil);
if (err<>0) then Exit;
Result:=NtQueryInformationThread(
td_handle,
ThreadBasicInformation,
@TBI,
SizeOf(THREAD_BASIC_INFORMATION),
nil);
if (Result<>0) then Exit;
Result:=TBI.TebBaseAddress;
teb:=TBI.TebBaseAddress;
end;
procedure NtGetVirtualInfo(hProcess:THandle;var base:Pointer;var size:QWORD);
@ -259,8 +265,8 @@ begin
err:=NtGetContextThread(hThread,Context);
if (err<>0) then Exit(err);
teb:=NtQueryTeb(hThread);
if (teb=nil) then Exit(-1);
err:=NtQueryTeb(hThread,teb);
if (err<>0) then Exit(err);
kstack:=Default(t_td_stack);
err:=md_copyin(hProcess,@teb^.stack,@kstack,SizeOf(t_td_stack),nil);
@ -432,13 +438,15 @@ end;
function NtCreateShared(hProcess:THandle;proc:Pointer;data:Pointer;size:QWORD):Integer;
var
base:p_shared_info;
full:QWORD;
shared_info:t_shared_info;
begin
base:=Pointer(WIN_SHARED_ADDR);
size:=SizeOf(Pointer)+size;
size:=(size+(MD_PAGE_SIZE-1)) and (not (MD_PAGE_SIZE-1));
Result:=md_mmap(hProcess,base,size,MD_PROT_RW);
full:=SizeOf(shared_info)+size;
full:=(size+(MD_PAGE_SIZE-1)) and (not (MD_PAGE_SIZE-1));
Result:=md_mmap(hProcess,base,full,MD_PROT_RW);
if (Result<>0) then Exit;
shared_info:=Default(t_shared_info);
@ -450,7 +458,6 @@ begin
shared_info.hStdError :=md_dup_to_pidfd(hProcess,GetStdHandle(STD_ERROR_HANDLE));
shared_info.proc:=proc;
shared_info.size:=size;
Result:=md_copyout(hProcess,@shared_info,base,SizeOf(shared_info),nil);
@ -462,7 +469,7 @@ begin
end;
end;
function md_fork_process(proc:Pointer;data:Pointer;size:QWORD):THandle;
function md_fork_process(proc:Pointer;data:Pointer;size:QWORD;var info:t_fork_proc):Integer;
var
si:TSTARTUPINFO;
pi:PROCESS_INFORMATION;
@ -471,7 +478,6 @@ var
DATA :array[0..MAX_PATH*2] of WideChar;
end;
LEN:ULONG;
R:DWORD;
b:BOOL;
begin
Result:=0;
@ -479,12 +485,12 @@ begin
FillChar(BUF,SizeOf(BUF),0);
LEN:=SizeOf(BUF);
R:=NtQueryInformationProcess(NtCurrentProcess,
ProcessImageFileNameWin32,
@BUF,
LEN,
@LEN);
if (R<>0) then Exit;
Result:=NtQueryInformationProcess(NtCurrentProcess,
ProcessImageFileNameWin32,
@BUF,
LEN,
@LEN);
if (Result<>0) then Exit;
si:=Default(TSTARTUPINFO);
pi:=Default(PROCESS_INFORMATION);
@ -492,18 +498,27 @@ begin
si.cb:=SizeOf(si);
b:=CreateProcessW(PWideChar(@BUF.DATA),nil,nil,nil,False,CREATE_SUSPENDED,nil,nil,@si,@pi);
if not b then Exit;
if not b then Exit(-1);
b:=AssignProcessToJobObject(NtFetchJob, pi.hProcess);
if not b then Exit(-1);
NtMoveStack(pi.hProcess,pi.hThread);
NtReserve(pi.hProcess);
NtCreateShared(pi.hProcess,proc,data,size);
Result:=NtMoveStack(pi.hProcess,pi.hThread);
if (Result<>0) then Exit;
Result:=NtReserve(pi.hProcess);
if (Result<>0) then Exit;
Result:=NtCreateShared(pi.hProcess,proc,data,size);
if (Result<>0) then Exit;
Result:=NtResumeProcess(pi.hProcess);
if (Result<>0) then Exit;
NtResumeProcess(pi.hProcess);
NtClose(pi.hThread);
Result:=pi.hProcess;
info.hProcess:=pi.hProcess;
info.fork_pid:=pi.dwProcessId;
end;
end.

450
sys/sys_conf.pas Normal file
View File

@ -0,0 +1,450 @@
unit sys_conf;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
uses
mqueue,
time,
kern_param,
vmount,
vfile,
vuio,
vnode,
sys_event,
vm,
sys_vm_object,
kern_mtx;
const
//modeventtype
MOD_LOAD =0;
MOD_UNLOAD =1;
MOD_SHUTDOWN=2;
MOD_QUIESCE =3;
SI_ETERNAL =$0001; { never destroyed }
SI_ALIAS =$0002; { carrier of alias name }
SI_NAMED =$0004; { make_dev _alias has been called }
SI_CHEAPCLONE=$0008; { can be removed_dev'ed when vnode reclaims }
SI_CHILD =$0010; { child of another struct cdev *}
SI_DEVOPEN =$0020; { opened by device }
SI_CONSOPEN =$0040; { opened by console }
SI_DUMPDEV =$0080; { is kernel dumpdev }
SI_CANDELETE =$0100; { can do BIO_DELETE }
SI_CLONELIST =$0200; { on a clone list }
SI_UNMAPPED =$0400; { can handle unmapped I/O }
type
pp_cdev=^p_cdev;
p_cdev=^t_cdev;
t_cdev=packed record
si_mountpt :p_mount;
si_flags :DWORD;
_align1 :Integer;
si_atime :timespec;
si_ctime :timespec;
si_mtime :timespec;
si_uid :uid_t;
si_gid :gid_t;
si_mode :mode_t;
si_drv0 :Integer;
si_refcount :Integer;
_align2 :Integer;
si_list :LIST_ENTRY; //(cdev)
si_clone :LIST_ENTRY; //(cdev)
si_children :LIST_HEAD ; //(cdev)
si_siblings :LIST_ENTRY; //(cdev)
si_parent :p_cdev;
si_name :PChar;
si_drv1 :Pointer;
si_drv2 :Pointer;
si_devsw :Pointer; //cdevsw
si_iosize_max :Integer; { maximum I/O size (for physio &al) }
_align3 :Integer;
si_usecount :QWORD;
si_threadcount:QWORD;
si_snapdata :Pointer; //snapdata
__si_namebuf :array[0..SPECNAMELEN] of AnsiChar;
end;
d_open_t =Function (dev:p_cdev;oflags,devtype:Integer):Integer;
d_fdopen_t =Function (dev:p_cdev;oflags:Integer;fp:p_file):Integer;
d_close_t =Function (dev:p_cdev;fflag,devtype:Integer):Integer;
d_strategy_t =Procedure(bp:Pointer);//bio
d_ioctl_t =Function (dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer;
d_read_t =Function (dev:p_cdev;uio:p_uio;ioflag:Integer):Integer;
d_write_t =Function (dev:p_cdev;uio:p_uio;ioflag:Integer):Integer;
d_poll_t =Function (dev:p_cdev;events:Integer):Integer;
d_kqfilter_t =Function (dev:p_cdev;kn:p_knote):Integer;
d_mmap_t =Function (dev:p_cdev;offset:vm_ooffset_t;paddr:p_vm_paddr_t;nprot:Integer;memattr:p_vm_memattr_t):Integer;
d_mmap_single_t =Function (dev:p_cdev;offset:p_vm_ooffset_t;size:vm_size_t;obj:p_vm_object_t;nprot:Integer):Integer;
d_mmap_single2_t=Function (dev:p_cdev;offset:p_vm_ooffset_t;size:vm_size_t;obj:p_vm_object_t;nprot:Integer;maxprotp:p_vm_prot_t;flagsp:PInteger):Integer;
d_purge_t =Procedure(dev:p_cdev);
dumper_t=Function(
_priv:Pointer ; { Private to the driver. }
_virtual:Pointer ; { Virtual (mapped) address. }
_physical:vm_offset_t; { Physical address of virtual. }
_offset:Int64 ; { Byte-offset to write at. }
_length:QWORD):Integer; { Number of bytes to dump. }
const
{
* Types for d_flags.
}
D_TAPE=$0001;
D_DISK=$0002;
D_TTY =$0004;
D_MEM =$0008;
D_TYPEMASK=$ffff;
{
* Flags for d_flags which the drivers can set.
}
D_TRACKCLOSE =$00080000; { track all closes }
D_MMAP_ANON =$00100000; { special treatment in vm_mmap.c }
D_PSEUDO =$00200000; { make_dev() can return NULL }
D_NEEDGIANT =$00400000; { driver want Giant }
D_NEEDMINOR =$00800000; { driver uses clone_create() }
D_UNMAPPED_IO=$01000000; { d_strategy can accept unmapped IO }
{
* Version numbers.
}
D_VERSION_00=$20011966;
D_VERSION_01=$17032005; { Add d_uid,gid,mode & kind }
D_VERSION_02=$28042009; { Add d_mmap_single }
D_VERSION_03=$17122009; { d_mmap takes memattr,vm_ooffset_t }
D_VERSION=D_VERSION_03;
{
* Flags used for internal housekeeping
}
D_INIT =$80000000; { cdevsw initialized }
{
* Character device switch table
}
type
pp_cdevsw=^p_cdevsw;
p_cdevsw=^t_cdevsw;
t_cdevsw=packed record
d_version :Integer;
d_flags :DWORD;
d_name :PChar;
d_open :d_open_t;
d_fdopen :d_fdopen_t;
d_close :d_close_t;
d_read :d_read_t;
d_write :d_write_t;
d_ioctl :d_ioctl_t;
d_poll :d_poll_t;
d_mmap :d_mmap_t;
d_strategy :d_strategy_t;
d_dump :dumper_t;
d_kqfilter :d_kqfilter_t;
d_purge :d_purge_t;
d_mmap_single :d_mmap_single_t;
d_mmap_single2:d_mmap_single2_t;
d_spare0:array[0..1] of Integer;
d_spare1:array[0..2] of Pointer;
{ These fields should not be messed with by drivers }
d_devs:Pointer; //cdev
d_spare2:array[0..1] of Integer;
d_gianttrick:p_cdevsw;
d_postfree_list:SLIST_ENTRY; //cdevsw
end;
const
MAKEDEV_REF =$01;
MAKEDEV_WHTOUT =$02;
MAKEDEV_NOWAIT =$04;
MAKEDEV_WAITOK =$08;
MAKEDEV_ETERNAL =$10;
MAKEDEV_CHECKNAME=$20;
UID_ROOT =0;
UID_BIN =3;
UID_UUCP =66;
UID_NOBODY =65534;
GID_WHEEL =0;
GID_KMEM =2;
GID_TTY =4;
GID_OPERATOR=5;
GID_BIN =7;
GID_GAMES =13;
GID_DIALER =68;
GID_NOBODY =65534;
var
devmtx:mtx;
cdevp_free_list:TAILQ_HEAD=(tqh_first:nil;tqh_last:@cdevp_free_list.tqh_first);
cdevsw_gt_post_list:SLIST_HEAD=(slh_first:nil);
type
cdevpriv_dtr_t=Procedure(data:Pointer);
function devfs_get_cdevpriv(datap:PPointer):Integer; external;
function devfs_set_cdevpriv(priv:Pointer;priv_dtr:cdevpriv_dtr_t):Integer; external;
procedure devfs_clear_cdevpriv(); external;
procedure devfs_fpdrop(fp:p_file); external;
type
ino_t=Integer;
function devfs_alloc_cdp_inode():ino_t; external;
procedure devfs_free_cdp_inode(ino:ino_t); external;
procedure dev_lock(); external;
procedure dev_unlock(); external;
procedure dev_ref(dev:p_cdev); external;
procedure dev_refl(dev:p_cdev); external;
procedure dev_rel(dev:p_cdev); external;
function dev_refthread(dev:p_cdev;ref:PInteger):p_cdevsw; external;
function devvn_refthread(vp:p_vnode;devp:pp_cdev;ref:PInteger):p_cdevsw; external;
procedure dev_relthread(dev:p_cdev;ref:Integer); external;
procedure destroy_dev(dev:p_cdev); external;
function dev2unit(d:p_cdev):Integer;
function devtoname(dev:p_cdev):PChar;
function make_dev_credv(flags:Integer;
dres:pp_cdev;
devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):Integer; register; external;
function make_dev(devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register;
function make_dev_cred(devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register;
function make_dev_credf(flags:Integer;
devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register;
function make_dev_p(flags:Integer;
cdev:pp_cdev;
devsw:p_cdevsw;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):Integer; register;
function make_dev_alias_v(flags:Integer;
cdev:pp_cdev;
pdev:p_cdev;
fmt:PChar;
const Args:Array of const):Integer; register; external;
function make_dev_alias(pdev:p_cdev;
fmt:PChar;
const Args:Array of const):p_cdev; register;
function make_dev_alias_p(flags:Integer;
cdev:pp_cdev;
pdev:p_cdev;
fmt:PChar;
const Args:Array of const):Integer; register;
function make_dev_physpath_alias(flags:Integer;
cdev:pp_cdev;
pdev,old_alias:p_cdev;
physpath:PChar):Integer; external;
function _nullop():Integer;
function _eopnotsupp():Integer;
function _enxio():Integer;
function _enodev():Integer;
function _einval():Integer;
implementation
uses
errno;
function dev2unit(d:p_cdev):Integer; inline;
begin
Result:=d^.si_drv0;
end;
function devtoname(dev:p_cdev):PChar; inline;
begin
Result:=dev^.si_name;
end;
function _nullop():Integer;
begin
Exit(0);
end;
function _eopnotsupp():Integer;
begin
Exit(EOPNOTSUPP);
end;
function _enxio():Integer;
begin
Exit(ENXIO);
end;
function _enodev():Integer;
begin
Exit(ENODEV);
end;
function _einval():Integer;
begin
Exit(EINVAL);
end;
function make_dev(devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register; public;
var
dev:p_cdev;
res:Integer;
begin
res:=make_dev_credv(0, @dev, devsw, _unit, uid, gid, mode, fmt, Args);
Assert((res=0) and (dev<>nil),'make_dev: failed make_dev_credv (error=%d)');
if (res=0) then
Exit(dev)
else
Exit(nil);
end;
function make_dev_cred(devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register; public;
var
dev:p_cdev;
res:Integer;
begin
res:=make_dev_credv(0, @dev, devsw, _unit, uid, gid, mode, fmt, Args);
Assert((res=0) and (dev<>nil),'make_dev_cred: failed make_dev_credv (error=%d)');
if (res=0) then
Exit(dev)
else
Exit(nil);
end;
function make_dev_credf(flags:Integer;
devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register; public;
var
dev:p_cdev;
res:Integer;
begin
res:=make_dev_credv(flags, @dev, devsw, _unit, uid, gid, mode, fmt, Args);
Assert((((flags and MAKEDEV_NOWAIT)<>0) and (res=ENOMEM)) or
(((flags and MAKEDEV_CHECKNAME)<>0) and (res<>ENOMEM)) or
(res=0),'make_dev_credf: failed make_dev_credv (error=%d)');
if (res=0) then
Exit(dev)
else
Exit(nil);
end;
function make_dev_p(flags:Integer;
cdev:pp_cdev;
devsw:p_cdevsw;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):Integer; register; public;
var
res:Integer;
begin
res:=make_dev_credv(flags, cdev, devsw, 0, uid, gid, mode, fmt, Args);
Assert((((flags and MAKEDEV_NOWAIT)<>0) and (res=ENOMEM)) or
(((flags and MAKEDEV_CHECKNAME)<>0) and (res<>ENOMEM)) or
(res=0),'make_dev_p: failed make_dev_credv (error=%d)');
Exit(res);
end;
function make_dev_alias(pdev:p_cdev;
fmt:PChar;
const Args:Array of const):p_cdev; register; public;
var
dev:p_cdev;
res:Integer;
begin
res:=make_dev_alias_v(MAKEDEV_WAITOK, @dev, pdev, fmt, Args);
Assert((res=0) and (dev<>nil),'make_dev_alias: failed make_dev_alias_v (error=%d)');
if (res=0) then
Exit(dev)
else
Exit(nil);
end;
function make_dev_alias_p(flags:Integer;
cdev:pp_cdev;
pdev:p_cdev;
fmt:PChar;
const Args:Array of const):Integer; register; public;
var
res:Integer;
begin
res:=make_dev_alias_v(flags, cdev, pdev, fmt, Args);
Exit(res);
end;
end.

View File

@ -6,6 +6,7 @@ unit sys_event;
interface
uses
time,
mqueue;
const
@ -39,6 +40,7 @@ const
EV_DELETE =$0002; // delete event from kq
EV_ENABLE =$0004; // enable event
EV_DISABLE =$0008; // disable event (not reported)
EV_ACTION =EV_ADD or EV_DELETE or EV_ENABLE or EV_DISABLE;
// flags
EV_ONESHOT =$0010; // only report one occurrence
@ -227,6 +229,8 @@ type
end;
{$IF sizeof(t_kevent_copyops)<>24}{$STOP sizeof(t_kevent_copyops)<>24}{$ENDIF}
t_kqueue_wakeup_cb=procedure(data:Pointer);
function knote_alloc():p_knote; external;
procedure knote_free(kn:p_knote); external;
@ -243,6 +247,25 @@ procedure knlist_init_mtx(knl:p_knlist;lock:Pointer); external;
procedure knlist_destroy (knl:p_knlist); external;
procedure knlist_cleardel(knl:p_knlist;islocked,killkn:Integer); external;
function kern_kqueue2(name:PAnsiChar;
w_cb:t_kqueue_wakeup_cb;
data:Pointer):Pointer; external;
procedure kqueue_close2(kq:Pointer); external;
function kern_kevent2(kq :Pointer;
changelist:p_kevent;
nchanges :Integer;
eventlist :p_kevent;
nevents :Integer;
timeout :p_timespec;
p_ncount :PInteger):Integer; external;
function kqueue_add_filteropts(filt:Integer;filtops:p_filterops):Integer; external;
function kqueue_del_filteropts(filt:Integer):Integer; external;
function kqfd_register(fd:Integer;kev:p_kevent):Integer; external;
procedure kqueue_deregister(filter:SmallInt;pid,ident:PtrUint); external;
//
procedure KNOTE_LOCKED (list:p_knlist;hint:QWORD);

View File

@ -44,6 +44,8 @@ type
kq_knhashmask:QWORD; // size of knhash
kq_knhash :p_klist; // hash table for knotes
//kq_task:task;
kq_wakeup :t_kqueue_wakeup_cb;
kq_data :Pointer;
kq_name :t_kq_name;
end;

View File

@ -12,6 +12,9 @@ implementation
uses
init_sysent, //compile spec
kern_rtprio, //compile spec
kern_conf, //compile spec
devfs_vnops, //compile spec
devfs_rule, //compile spec
time,
kern_time,
subr_sleepqueue,
@ -42,7 +45,7 @@ uses
ufs,
kern_descrip,
vfs_mountroot,
kern_conf,
sys_conf,
dev_null,
dev_tty,
dev_dmem,

View File

@ -7,8 +7,8 @@ interface
uses
mqueue,
sys_conf,
kern_param,
sys_event,
vmount,
vfile,
vuio,
@ -18,274 +18,12 @@ uses
sys_vm_object,
kern_mtx;
const
//modeventtype
MOD_LOAD =0;
MOD_UNLOAD =1;
MOD_SHUTDOWN=2;
MOD_QUIESCE =3;
SI_ETERNAL =$0001; { never destroyed }
SI_ALIAS =$0002; { carrier of alias name }
SI_NAMED =$0004; { make_dev _alias has been called }
SI_CHEAPCLONE=$0008; { can be removed_dev'ed when vnode reclaims }
SI_CHILD =$0010; { child of another struct cdev *}
SI_DEVOPEN =$0020; { opened by device }
SI_CONSOPEN =$0040; { opened by console }
SI_DUMPDEV =$0080; { is kernel dumpdev }
SI_CANDELETE =$0100; { can do BIO_DELETE }
SI_CLONELIST =$0200; { on a clone list }
SI_UNMAPPED =$0400; { can handle unmapped I/O }
type
pp_cdev=^p_cdev;
p_cdev=^t_cdev;
t_cdev=packed record
si_mountpt :p_mount;
si_flags :DWORD;
_align1 :Integer;
si_atime :timespec;
si_ctime :timespec;
si_mtime :timespec;
si_uid :uid_t;
si_gid :gid_t;
si_mode :mode_t;
si_drv0 :Integer;
si_refcount :Integer;
_align2 :Integer;
si_list :LIST_ENTRY; //(cdev)
si_clone :LIST_ENTRY; //(cdev)
si_children :LIST_HEAD ; //(cdev)
si_siblings :LIST_ENTRY; //(cdev)
si_parent :p_cdev;
si_name :PChar;
si_drv1 :Pointer;
si_drv2 :Pointer;
si_devsw :Pointer; //cdevsw
si_iosize_max :Integer; { maximum I/O size (for physio &al) }
_align3 :Integer;
si_usecount :QWORD;
si_threadcount:QWORD;
si_snapdata :Pointer; //snapdata
__si_namebuf :array[0..SPECNAMELEN] of AnsiChar;
end;
d_open_t =Function (dev:p_cdev;oflags,devtype:Integer):Integer;
d_fdopen_t =Function (dev:p_cdev;oflags:Integer;fp:p_file):Integer;
d_close_t =Function (dev:p_cdev;fflag,devtype:Integer):Integer;
d_strategy_t =Procedure(bp:Pointer);//bio
d_ioctl_t =Function (dev:p_cdev;cmd:QWORD;data:Pointer;fflag:Integer):Integer;
d_read_t =Function (dev:p_cdev;uio:p_uio;ioflag:Integer):Integer;
d_write_t =Function (dev:p_cdev;uio:p_uio;ioflag:Integer):Integer;
d_poll_t =Function (dev:p_cdev;events:Integer):Integer;
d_kqfilter_t =Function (dev:p_cdev;kn:p_knote):Integer;
d_mmap_t =Function (dev:p_cdev;offset:vm_ooffset_t;paddr:p_vm_paddr_t;nprot:Integer;memattr:p_vm_memattr_t):Integer;
d_mmap_single_t =Function (dev:p_cdev;offset:p_vm_ooffset_t;size:vm_size_t;obj:p_vm_object_t;nprot:Integer):Integer;
d_mmap_single2_t=Function (dev:p_cdev;offset:p_vm_ooffset_t;size:vm_size_t;obj:p_vm_object_t;nprot:Integer;maxprotp:p_vm_prot_t;flagsp:PInteger):Integer;
d_purge_t =Procedure(dev:p_cdev);
dumper_t=Function(
_priv:Pointer ; { Private to the driver. }
_virtual:Pointer ; { Virtual (mapped) address. }
_physical:vm_offset_t; { Physical address of virtual. }
_offset:Int64 ; { Byte-offset to write at. }
_length:QWORD):Integer; { Number of bytes to dump. }
const
{
* Types for d_flags.
}
D_TAPE=$0001;
D_DISK=$0002;
D_TTY =$0004;
D_MEM =$0008;
D_TYPEMASK=$ffff;
{
* Flags for d_flags which the drivers can set.
}
D_TRACKCLOSE =$00080000; { track all closes }
D_MMAP_ANON =$00100000; { special treatment in vm_mmap.c }
D_PSEUDO =$00200000; { make_dev() can return NULL }
D_NEEDGIANT =$00400000; { driver want Giant }
D_NEEDMINOR =$00800000; { driver uses clone_create() }
D_UNMAPPED_IO=$01000000; { d_strategy can accept unmapped IO }
{
* Version numbers.
}
D_VERSION_00=$20011966;
D_VERSION_01=$17032005; { Add d_uid,gid,mode & kind }
D_VERSION_02=$28042009; { Add d_mmap_single }
D_VERSION_03=$17122009; { d_mmap takes memattr,vm_ooffset_t }
D_VERSION=D_VERSION_03;
{
* Flags used for internal housekeeping
}
D_INIT =$80000000; { cdevsw initialized }
{
* Character device switch table
}
type
pp_cdevsw=^p_cdevsw;
p_cdevsw=^t_cdevsw;
t_cdevsw=packed record
d_version :Integer;
d_flags :DWORD;
d_name :PChar;
d_open :d_open_t;
d_fdopen :d_fdopen_t;
d_close :d_close_t;
d_read :d_read_t;
d_write :d_write_t;
d_ioctl :d_ioctl_t;
d_poll :d_poll_t;
d_mmap :d_mmap_t;
d_strategy :d_strategy_t;
d_dump :dumper_t;
d_kqfilter :d_kqfilter_t;
d_purge :d_purge_t;
d_mmap_single :d_mmap_single_t;
d_mmap_single2:d_mmap_single2_t;
d_spare0:array[0..1] of Integer;
d_spare1:array[0..2] of Pointer;
{ These fields should not be messed with by drivers }
d_devs:Pointer; //cdev
d_spare2:array[0..1] of Integer;
d_gianttrick:p_cdevsw;
d_postfree_list:SLIST_ENTRY; //cdevsw
end;
const
MAKEDEV_REF =$01;
MAKEDEV_WHTOUT =$02;
MAKEDEV_NOWAIT =$04;
MAKEDEV_WAITOK =$08;
MAKEDEV_ETERNAL =$10;
MAKEDEV_CHECKNAME=$20;
UID_ROOT =0;
UID_BIN =3;
UID_UUCP =66;
UID_NOBODY =65534;
GID_WHEEL =0;
GID_KMEM =2;
GID_TTY =4;
GID_OPERATOR=5;
GID_BIN =7;
GID_GAMES =13;
GID_DIALER =68;
GID_NOBODY =65534;
function dev2unit(d:p_cdev):Integer; inline;
function devtoname(dev:p_cdev):PChar;
type
cdevpriv_dtr_t=Procedure(data:Pointer);
var
devmtx:mtx;
cdevp_free_list:TAILQ_HEAD=(tqh_first:nil;tqh_last:@cdevp_free_list.tqh_first);
cdevsw_gt_post_list:SLIST_HEAD=(slh_first:nil);
function _nullop():Integer;
function _eopnotsupp():Integer;
function _enxio():Integer;
function _enodev():Integer;
function _einval():Integer;
procedure dev_lock();
procedure dev_unlock();
procedure dev_ref(dev:p_cdev);
procedure dev_refl(dev:p_cdev);
procedure dev_rel(dev:p_cdev);
function dev_refthread(dev:p_cdev;ref:PInteger):p_cdevsw;
function devvn_refthread(vp:p_vnode;devp:pp_cdev;ref:PInteger):p_cdevsw;
procedure dev_relthread(dev:p_cdev;ref:Integer);
procedure destroy_dev(dev:p_cdev);
function make_dev_credv(flags:Integer;
dres:pp_cdev;
devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):Integer; register;
function make_dev(devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register;
function make_dev_cred(devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register;
function make_dev_credf(flags:Integer;
devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register;
function make_dev_p(flags:Integer;
cdev:pp_cdev;
devsw:p_cdevsw;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):Integer; register;
function make_dev_alias_v(flags:Integer;
cdev:pp_cdev;
pdev:p_cdev;
fmt:PChar;
const Args:Array of const):Integer; register;
function make_dev_alias(pdev:p_cdev;
fmt:PChar;
const Args:Array of const):p_cdev; register;
function make_dev_alias_p(flags:Integer;
cdev:pp_cdev;
pdev:p_cdev;
fmt:PChar;
const Args:Array of const):Integer; register;
function make_dev_physpath_alias(flags:Integer;
cdev:pp_cdev;
pdev,old_alias:p_cdev;
physpath:PChar):Integer;
implementation
uses
sysutils,
errno,
devfs,
devfs_vnops,
devfs_int,
vsys_generic,
kern_synch;
@ -304,30 +42,30 @@ begin
Result:=c-ptruint(@p_cdev_priv(nil)^.cdp_c);
end;
procedure dev_lock();
procedure dev_lock(); public;
begin
mtx_lock(devmtx);
end;
procedure dev_unlock();
procedure dev_unlock(); public;
begin
mtx_unlock(devmtx);
end;
procedure dev_ref(dev:p_cdev);
procedure dev_ref(dev:p_cdev); public;
begin
mtx_lock(devmtx);
Inc(dev^.si_refcount);
mtx_unlock(devmtx);
end;
procedure dev_refl(dev:p_cdev);
procedure dev_refl(dev:p_cdev); public;
begin
mtx_assert(devmtx);
Inc(dev^.si_refcount);
end;
procedure dev_rel(dev:p_cdev);
procedure dev_rel(dev:p_cdev); public;
var
flag:Integer;
begin
@ -350,7 +88,7 @@ begin
end;
end;
function dev_refthread(dev:p_cdev;ref:PInteger):p_cdevsw;
function dev_refthread(dev:p_cdev;ref:PInteger):p_cdevsw; public;
var
csw:p_cdevsw;
cdp:p_cdev_priv;
@ -375,7 +113,7 @@ begin
Exit(csw);
end;
function devvn_refthread(vp:p_vnode;devp:pp_cdev;ref:PInteger):p_cdevsw;
function devvn_refthread(vp:p_vnode;devp:pp_cdev;ref:PInteger):p_cdevsw; public;
var
csw:p_cdevsw;
cdp:p_cdev_priv;
@ -418,7 +156,7 @@ begin
Exit(csw);
end;
procedure dev_relthread(dev:p_cdev;ref:Integer);
procedure dev_relthread(dev:p_cdev;ref:Integer); public;
begin
if (ref=0) then Exit;
dev_lock();
@ -486,31 +224,6 @@ begin
SLIST_INSERT_HEAD(@cdevsw_gt_post_list,csw,@csw^.d_postfree_list);
end;
function _nullop():Integer;
begin
Exit(0);
end;
function _eopnotsupp():Integer;
begin
Exit(EOPNOTSUPP);
end;
function _enxio():Integer;
begin
Exit(ENXIO);
end;
function _enodev():Integer;
begin
Exit(ENODEV);
end;
function _einval():Integer;
begin
Exit(EINVAL);
end;
procedure dead_strategy(bp:Pointer);
begin
//biofinish(bp, nil, ENXIO);
@ -1000,7 +713,7 @@ function make_dev_credv(flags:Integer;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):Integer; register;
const Args:Array of const):Integer; register; public name 'make_dev_credv';
var
dev,dev_new:p_cdev;
res:Integer;
@ -1074,92 +787,6 @@ begin
Exit(0);
end;
function make_dev(devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register;
var
dev:p_cdev;
res:Integer;
begin
res:=make_dev_credv(0, @dev, devsw, _unit, uid, gid, mode, fmt, Args);
Assert((res=0) and (dev<>nil),'make_dev: failed make_dev_credv (error=%d)');
if (res=0) then
Exit(dev)
else
Exit(nil);
end;
function make_dev_cred(devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register;
var
dev:p_cdev;
res:Integer;
begin
res:=make_dev_credv(0, @dev, devsw, _unit, uid, gid, mode, fmt, Args);
Assert((res=0) and (dev<>nil),'make_dev_cred: failed make_dev_credv (error=%d)');
if (res=0) then
Exit(dev)
else
Exit(nil);
end;
function make_dev_credf(flags:Integer;
devsw:p_cdevsw;
_unit:Integer;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):p_cdev; register;
var
dev:p_cdev;
res:Integer;
begin
res:=make_dev_credv(flags, @dev, devsw, _unit, uid, gid, mode, fmt, Args);
Assert((((flags and MAKEDEV_NOWAIT)<>0) and (res=ENOMEM)) or
(((flags and MAKEDEV_CHECKNAME)<>0) and (res<>ENOMEM)) or
(res=0),'make_dev_credf: failed make_dev_credv (error=%d)');
if (res=0) then
Exit(dev)
else
Exit(nil);
end;
function make_dev_p(flags:Integer;
cdev:pp_cdev;
devsw:p_cdevsw;
uid:uid_t;
gid:gid_t;
mode:Integer;
fmt:PChar;
const Args:Array of const):Integer; register;
var
res:Integer;
begin
res:=make_dev_credv(flags, cdev, devsw, 0, uid, gid, mode, fmt, Args);
Assert((((flags and MAKEDEV_NOWAIT)<>0) and (res=ENOMEM)) or
(((flags and MAKEDEV_CHECKNAME)<>0) and (res<>ENOMEM)) or
(res=0),'make_dev_p: failed make_dev_credv (error=%d)');
Exit(res);
end;
procedure dev_dependsl(pdev,cdev:p_cdev);
begin
cdev^.si_parent:=pdev;
@ -1178,7 +805,7 @@ function make_dev_alias_v(flags:Integer;
cdev:pp_cdev;
pdev:p_cdev;
fmt:PChar;
const Args:Array of const):Integer; register;
const Args:Array of const):Integer; register; public name 'make_dev_alias_v';
var
dev:p_cdev;
error:Integer;
@ -1217,40 +844,10 @@ begin
Exit(0);
end;
function make_dev_alias(pdev:p_cdev;
fmt:PChar;
const Args:Array of const):p_cdev; register;
var
dev:p_cdev;
res:Integer;
begin
res:=make_dev_alias_v(MAKEDEV_WAITOK, @dev, pdev, fmt, Args);
Assert((res=0) and (dev<>nil),'make_dev_alias: failed make_dev_alias_v (error=%d)');
if (res=0) then
Exit(dev)
else
Exit(nil);
end;
function make_dev_alias_p(flags:Integer;
cdev:pp_cdev;
pdev:p_cdev;
fmt:PChar;
const Args:Array of const):Integer; register;
var
res:Integer;
begin
res:=make_dev_alias_v(flags, cdev, pdev, fmt, Args);
Exit(res);
end;
function make_dev_physpath_alias(flags:Integer;
cdev:pp_cdev;
pdev,old_alias:p_cdev;
physpath:PChar):Integer;
physpath:PChar):Integer; public;
label
_ret,
_out;
@ -1473,7 +1070,7 @@ begin
dev_unlock();
end;
procedure destroy_dev(dev:p_cdev);
procedure destroy_dev(dev:p_cdev); public;
begin
dev_lock();
destroy_devl(dev);

View File

@ -137,7 +137,7 @@ uses
sys_resource,
kern_resource,
kern_mtx,
kern_conf;
sys_conf;
//
@ -809,7 +809,7 @@ begin
Exit(0);
end;
function kern_close(fd:Integer):Integer;
function kern_close(fd:Integer):Integer; public;
var
fp,fp_object:p_file;
begin

View File

@ -193,7 +193,7 @@ uses
sys_vm_object,
vsys_generic,
rtprio,
kern_conf;
sys_conf;
//

View File

@ -23,7 +23,7 @@ uses
errno,
vmparam,
vm_pmap,
kern_conf;
sys_conf;
function OFF_TO_IDX(x:QWORD):DWORD; inline;
begin

View File

@ -66,7 +66,7 @@ uses
vnode,
vfs_subr,
vnode_if,
kern_conf,
sys_conf,
vm_pager;
function vm_mmap_cdev(objsize :vm_size_t;