unit kern_rtprio; {$mode ObjFPC}{$H+} {$CALLING SysV_ABI_CDecl} interface uses mqueue, rtprio, kern_thr; function rtp_to_pri(rtp:p_rtprio;td:p_kthread):Integer; procedure pri_to_rtp(td:p_kthread;rtp:p_rtprio); function sys_rtprio_thread(func,tid:Integer;rtp:Pointer):Integer; function sys_rtprio(func,pid:Integer;rtp:Pointer):Integer; implementation uses systm, errno, kern_proc, sched_ule, md_proc; // procedure umtx_pi_adjust(td:p_kthread;oldpri:Integer); external; // function rtp_to_pri(rtp:p_rtprio;td:p_kthread):Integer; public; var oldpri,newpri:Integer; begin Result:=0; Case RTP_PRIO_BASE(rtp^._type) of RTP_PRIO_IDLE: begin newpri:=960; if (rtp^._prio<>960) then Exit(EINVAL); end; RTP_PRIO_NORMAL: begin newpri:=rtp^._prio; if (newpri>959) then Exit(EINVAL); end; PRI_REALTIME: begin newpri:=rtp^._prio; if (newpri>767) then Exit(EINVAL); end; else Exit(EINVAL) end; thread_lock(td); sched_class(td,rtp^._type); oldpri:=td^.td_user_pri; sched_user_prio(td, newpri); if (td^.td_user_pri<>oldpri) then begin sched_prio(td,td^.td_user_pri); if TD_ON_UPILOCK(td) then begin umtx_pi_adjust(td,oldpri) end; end; thread_unlock(td); end; procedure pri_to_rtp(td:p_kthread;rtp:p_rtprio); public; begin thread_lock(td); case PRI_BASE(td^.td_pri_class) of RTP_PRIO_REALTIME, RTP_PRIO_NORMAL, RTP_PRIO_IDLE: begin rtp^._prio:=td^.td_base_user_pri; end; else; end; rtp^._type:=td^.td_pri_class; thread_unlock(td); end; function sys_rtprio_thread(func,tid:Integer;rtp:Pointer):Integer; var td,td1:p_kthread; _rtp:t_rtprio; begin td:=curkthread; if (func=RTP_SET) then begin Result:=copyin(rtp,@_rtp,sizeof(t_rtprio)) end else begin Result:=0; _rtp:=Default(t_rtprio); end; if (tid=0) or (tid=td^.td_tid) then begin td1:=td; thread_inc_ref(td1); end else begin td1:=tdfind(tid); if (td1=nil) then Exit(ESRCH); end; case func of RTP_LOOKUP: begin pri_to_rtp(td1,@_rtp); Result:=copyout(@_rtp,rtp,sizeof(t_rtprio)); end; RTP_SET: begin if (Result<>0) then begin thread_dec_ref(td1); Exit; end; Result:=rtp_to_pri(@_rtp,td1); end; else Result:=EINVAL; end; thread_dec_ref(td1); end; function sys_rtprio(func,pid:Integer;rtp:Pointer):Integer; var td,tdp:p_kthread; rtp1,rtp2:t_rtprio; begin if (pid<>0) and (pid<>p_proc.p_pid) then Exit(ESRCH); td:=curkthread; if (func=RTP_SET) then begin Result:=copyin(rtp,@rtp1,sizeof(t_rtprio)) end else begin Result:=0; rtp1:=Default(t_rtprio); end; case func of RTP_LOOKUP: begin PROC_LOCK; if (pid=0) then begin pri_to_rtp(td,@rtp1); end else begin rtp1._type:=RTP_PRIO_IDLE; rtp1._prio:=RTP_PRIO_MAX; threads_lock; tdp:=TAILQ_FIRST(get_p_threads); while (tdp<>nil) do begin pri_to_rtp(tdp,@rtp2); if (rtp2._type0) then Exit; PROC_LOCK; if (pid=0) then begin Result:=rtp_to_pri(@rtp1,td); end else begin threads_lock; tdp:=TAILQ_FIRST(get_p_threads); while (tdp<>nil) do begin Result:=rtp_to_pri(@rtp1,tdp); if (Result<>0) then Break; tdp:=TAILQ_NEXT(tdp,@tdp^.td_plist) end; threads_unlock; end; PROC_UNLOCK; end; else Result:=EINVAL; end; end; end.