unit sys_event; {$mode ObjFPC}{$H+} {$CALLING SysV_ABI_CDecl} interface uses time, mqueue; const EVFILT_READ =(-1); EVFILT_WRITE =(-2); EVFILT_AIO =(-3); // attached to aio requests EVFILT_VNODE =(-4); // attached to vnodes EVFILT_PROC =(-5); // attached to struct proc EVFILT_SIGNAL =(-6); // attached to struct proc EVFILT_TIMER =(-7); // timers //EVFILT_NETDEV =(-8); no longer supported EVFILT_FS =(-9); // filesystem events EVFILT_LIO =(-10); // attached to lio requests EVFILT_USER =(-11); // User events EVFILT_POLLING =(-12); EVFILT_DISPLAY =(-13); // dev/dce EVFILT_GRAPHICS_CORE =(-14); // dev/gc EVFILT_HRTIMER =(-15); // High resolution timers EVFILT_UVD_TRAP =(-16); EVFILT_VCE_TRAP =(-17); EVFILT_SDMA_TRAP =(-18); EVFILT_REG_EV =(-19); EVFILT_GPU_EXCEPTION =(-20); EVFILT_GPU_SYSTEM_EXCEPTION=(-21); EVFILT_GPU_DBGGC_EV =(-22); EVFILT_CPUMODE =(-23); EVFILT_SYSCOUNT =(23); // actions EV_ADD =$0001; // add event to kq (implies enable) 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 EV_CLEAR =$0020; // clear event state after reporting EV_RECEIPT =$0040; // force EV_ERROR on success, data=0 EV_DISPATCH =$0080; // disable event after reporting EV_SYSFLAGS =$F000; // reserved by system EV_DROP =$1000; // note should be dropped EV_FLAG1 =$2000; // filter-specific flag // returned values EV_EOF =$8000; // EOF detected EV_ERROR =$4000; // error, data contains errno //data/hint flags/masks for EVFILT_USER, shared with userspace NOTE_FFNOP =$00000000; // ignore input fflags NOTE_FFAND =$40000000; // AND fflags NOTE_FFOR =$80000000; // OR fflags NOTE_FFCOPY =$c0000000; // copy fflags NOTE_FFCTRLMASK=$c0000000; // masks for operations NOTE_FFLAGSMASK=$00ffffff; NOTE_TRIGGER =$01000000; // Cause the event to be triggered for output. //data/hint flags for EVFILT_{READ|WRITE}, shared with userspace NOTE_LOWAT =$0001; // low water mark NOTE_DELETE =$0001; // vnode was removed NOTE_WRITE =$0002; // data contents changed NOTE_EXTEND =$0004; // size increased NOTE_ATTRIB =$0008; // attributes changed NOTE_LINK =$0010; // link count changed NOTE_RENAME =$0020; // vnode was renamed NOTE_REVOKE =$0040; // vnode access was revoked //data/hint flags for EVFILT_PROC, shared with userspace NOTE_EXIT =$80000000; // process exited NOTE_FORK =$40000000; // process forked NOTE_EXEC =$20000000; // process exec'd NOTE_PCTRLMASK=$f0000000; // mask for hint bits NOTE_PDATAMASK=$000fffff; // mask for pid // additional flags for EVFILT_PROC NOTE_TRACK =$00000001; // follow across forks NOTE_TRACKERR=$00000002; // could not track child NOTE_CHILD =$00000004; // am a child process // flags for EVFILT_POLLING NOTE_POLLING_EQUAL=$00000001; // trigger when var == data NOTE_POLLING_LESS =$00000002; // trigger when var < data NOTE_POLLING_NOT =$00000004; // negate trigger condition NOTE_POLLING_COND =$00000007; NOTE_POLLING_64BIT=$00000008; // watch a 64-bit variable //Flags for knote call KNF_LISTLOCKED=$0001; // knlist is locked KNF_NOKQLOCK =$0002; // do not keep KQ_LOCK { * Flag indicating hint is a signal. Used by EVFILT_SIGNAL, and also * shared by EVFILT_PROC (all knotes attached to p->p_klist) } NOTE_SIGNAL=$08000000; //Hint values for the optional f_touch event filter EVENT_REGISTER=1; EVENT_PROCESS =2; //kn_status KN_ACTIVE =$001; // event has been triggered KN_QUEUED =$002; // event is on queue KN_DISABLED =$004; // event is disabled KN_DETACHED =$008; // knote is detached KN_INFLUX =$010; // knote is in flux KN_MARKER =$020; // ignore this knote KN_KQUEUE =$040; // this knote belongs to a kq KN_HASKQLOCK=$080; // for _inevent KN_SCAN =$100; // flux set in kqueue_scan() //sce SCE_KERNEL_EVFILT_TIMER =EVFILT_TIMER ; SCE_KERNEL_EVFILT_READ =EVFILT_READ ; SCE_KERNEL_EVFILT_WRITE =EVFILT_WRITE ; SCE_KERNEL_EVFILT_USER =EVFILT_USER ; SCE_KERNEL_EVFILT_FILE =EVFILT_VNODE ; SCE_KERNEL_EVFILT_GNM =EVFILT_GRAPHICS_CORE; SCE_KERNEL_EVFILT_VIDEO_OUT =EVFILT_DISPLAY ; SCE_KERNEL_EVFILT_HRTIMER =EVFILT_HRTIMER ; SCE_KERNEL_EVNOTE_DELETE =NOTE_DELETE ; SCE_KERNEL_EVNOTE_WRITE =NOTE_WRITE ; SCE_KERNEL_EVNOTE_EXTEND =NOTE_EXTEND ; SCE_KERNEL_EVNOTE_ATTRIB =NOTE_ATTRIB ; SCE_KERNEL_EVNOTE_RENAME =NOTE_RENAME ; SCE_KERNEL_EVNOTE_REVOKE =NOTE_REVOKE ; SCE_KERNEL_EVFLAG_EOF =EV_EOF ; SCE_KERNEL_EVFLAG_ERROR =EV_ERROR ; SCE_VIDEO_OUT_EVENT_FLIP =0; //Flip completion event SCE_VIDEO_OUT_EVENT_VBLANK =1; //Vblank event SCE_VIDEO_OUT_EVENT_PRE_VBLANK_START=2; //PreVblankStart event type p_kevent=^t_kevent; t_kevent=packed record ident :PtrUint; // identifier for this event filter:SmallInt; // filter for event flags :Word; // action flags for kqueue fflags:DWORD; // filter flag value data :Ptrint; // filter data value udata :Pointer; // opaque user data identifier end; {$IF sizeof(t_kevent)<>32}{$STOP sizeof(t_kevent)<>32}{$ENDIF} pSceKernelEvent=^SceKernelEvent; SceKernelEvent=t_kevent; p_knote=^t_knote; p_klist=^t_klist; t_klist =SLIST_HEAD; //knote p_kqlist=^t_kqlist; t_kqlist=SLIST_HEAD; //kqueue p_knlist=^t_knlist; t_knlist=packed record kl_list :t_klist; kl_lock :procedure(arg:Pointer); // lock function kl_unlock :procedure(arg:Pointer); kl_assert_locked :procedure(arg:Pointer); kl_assert_unlocked:procedure(arg:Pointer); kl_lockarg :Pointer; // argument passed to kl_lockf() end; {$IF sizeof(t_knlist)<>48}{$STOP sizeof(t_knlist)<>48}{$ENDIF} p_filterops=^t_filterops; t_filterops=packed object f_isfd :Integer; // true if ident == filedescriptor _align :Integer; f_attach:function (kn:p_knote):Integer; f_detach:procedure(kn:p_knote); f_event :function (kn:p_knote;hint:QWORD):Integer; f_touch :procedure(kn:p_knote;kev:p_kevent;_type:QWORD); end; {$IF sizeof(t_filterops)<>40}{$STOP sizeof(t_filterops)<>40}{$ENDIF} t_knote=packed object kn_link :SLIST_ENTRY; // (knote) for kq kn_selnext:SLIST_ENTRY; // (knote) for struct selinfo kn_knlist :p_knlist; // f_attach populated kn_tqe :TAILQ_ENTRY; // (knote) kn_kq :Pointer; // (kqueue) which queue we are on kn_kevent :t_kevent; kn_status :Integer; // protected by kq lock kn_sfflags:Integer; // saved filter flags kn_sdata :Ptrint; // saved data field kn_ptr :packed record case Byte of 0:(p_fp :Pointer); // (file) file data pointer 1:(p_proc:Pointer); // (proc) proc pointer 2:(p_aio :Pointer); // (aiocblist) AIO job pointer 3:(p_lio :Pointer); // (aioliojob) LIO job pointer end; kn_fop :p_filterops; kn_hook :Pointer; kn_hookid :Integer; _align :Integer; // property kn_id :PtrUint read kn_kevent.ident write kn_kevent.ident ; property kn_filter:SmallInt read kn_kevent.filter write kn_kevent.filter; property kn_flags :Word read kn_kevent.flags write kn_kevent.flags ; property kn_fflags:DWORD read kn_kevent.fflags write kn_kevent.fflags; property kn_data :Ptrint read kn_kevent.data write kn_kevent.data ; property kn_fp :Pointer read kn_ptr.p_fp write kn_ptr.p_fp ; end; {$IF sizeof(t_knote)<>128}{$STOP sizeof(t_knote)<>128}{$ENDIF} p_kevent_copyops=^t_kevent_copyops; t_kevent_copyops=packed record arg :Pointer; k_copyout:function(arg:Pointer;kevp:p_kevent;count:Integer):Integer; k_copyin :function(arg:Pointer;kevp:p_kevent;count:Integer):Integer; 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; procedure knote(list:p_knlist;hint:QWORD;lockflags:Integer); external; procedure knlist_add (knl:p_knlist;kn:p_knote;islocked:Integer); external; procedure knlist_remove(knl:p_knlist;kn:p_knote;islocked:Integer); external; procedure knote_fdclose(fd:Integer); external; procedure knlist_init(knl:p_knlist;lock,kl_lock,kl_unlock,kl_assert_locked,kl_assert_unlocked:Pointer); external; 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); procedure KNOTE_UNLOCKED(list:p_knlist;hint:QWORD); procedure knlist_clear (knl:p_knlist;islocked:Integer); inline; procedure knlist_delete(knl:p_knlist;islocked:Integer); inline; function M_KNLIST_EMPTY(list:p_knlist):Boolean; // procedure EV_SET(kevp:p_kevent;a:PtrUint;b:SmallInt;c:Word;d:DWORD;e:Ptrint;f:Pointer); function EVFILT_NAME(i:Integer):RawByteString; implementation procedure KNOTE_LOCKED(list:p_knlist;hint:QWORD); begin knote(list, hint, KNF_LISTLOCKED); end; procedure KNOTE_UNLOCKED(list:p_knlist;hint:QWORD); begin knote(list, hint, 0); end; procedure knlist_clear(knl:p_knlist;islocked:Integer); inline; begin knlist_cleardel(knl, islocked, 0) end; procedure knlist_delete(knl:p_knlist;islocked:Integer); inline; begin knlist_cleardel(knl, islocked, 1) end; function M_KNLIST_EMPTY(list:p_knlist):Boolean; begin Result:=SLIST_EMPTY(@list^.kl_list); end; procedure EV_SET(kevp:p_kevent;a:PtrUint;b:SmallInt;c:Word;d:DWORD;e:Ptrint;f:Pointer); begin (kevp)^.ident :=(a); (kevp)^.filter:=(b); (kevp)^.flags :=(c); (kevp)^.fflags:=(d); (kevp)^.data :=(e); (kevp)^.udata :=(f); end; function EVFILT_NAME(i:Integer):RawByteString; begin Result:=''; case i of EVFILT_READ :Result:='EVFILT_READ'; EVFILT_WRITE :Result:='EVFILT_WRITE'; EVFILT_AIO :Result:='EVFILT_AIO'; EVFILT_VNODE :Result:='EVFILT_VNODE'; EVFILT_PROC :Result:='EVFILT_PROC'; EVFILT_SIGNAL :Result:='EVFILT_SIGNAL'; EVFILT_TIMER :Result:='EVFILT_TIMER'; EVFILT_FS :Result:='EVFILT_FS'; EVFILT_LIO :Result:='EVFILT_LIO'; EVFILT_USER :Result:='EVFILT_USER'; EVFILT_POLLING :Result:='EVFILT_POLLING'; EVFILT_DISPLAY :Result:='EVFILT_DISPLAY'; EVFILT_GRAPHICS_CORE :Result:='EVFILT_GRAPHICS_CORE'; EVFILT_HRTIMER :Result:='EVFILT_HRTIMER'; EVFILT_UVD_TRAP :Result:='EVFILT_UVD_TRAP'; EVFILT_VCE_TRAP :Result:='EVFILT_VCE_TRAP'; EVFILT_SDMA_TRAP :Result:='EVFILT_SDMA_TRAP'; EVFILT_REG_EV :Result:='EVFILT_REG_EV'; EVFILT_GPU_EXCEPTION :Result:='EVFILT_GPU_EXCEPTION'; EVFILT_GPU_SYSTEM_EXCEPTION:Result:='EVFILT_GPU_SYSTEM_EXCEPTION'; EVFILT_GPU_DBGGC_EV :Result:='EVFILT_GPU_DBGGC_EV'; EVFILT_CPUMODE :Result:='EVFILT_CPUMODE'; else Str(i,Result); end; end; end.