114 static int rt_enterclass(kthread_t *, id_t, void *, cred_t *, void *);
115 static int rt_fork(kthread_t *, kthread_t *, void *);
116 static int rt_getclinfo(void *);
117 static int rt_getclpri(pcpri_t *);
118 static int rt_parmsin(void *);
119 static int rt_parmsout(void *, pc_vaparms_t *);
120 static int rt_vaparmsin(void *, pc_vaparms_t *);
121 static int rt_vaparmsout(void *, pc_vaparms_t *);
122 static int rt_parmsset(kthread_t *, void *, id_t, cred_t *);
123 static int rt_donice(kthread_t *, cred_t *, int, int *);
124 static int rt_doprio(kthread_t *, cred_t *, int, int *);
125 static void rt_exitclass(void *);
126 static int rt_canexit(kthread_t *, cred_t *);
127 static void rt_forkret(kthread_t *, kthread_t *);
128 static void rt_nullsys();
129 static void rt_parmsget(kthread_t *, void *);
130 static void rt_preempt(kthread_t *);
131 static void rt_setrun(kthread_t *);
132 static void rt_tick(kthread_t *);
133 static void rt_wakeup(kthread_t *);
134 static pri_t rt_swapin(kthread_t *, int);
135 static pri_t rt_swapout(kthread_t *, int);
136 static pri_t rt_globpri(kthread_t *);
137 static void rt_yield(kthread_t *);
138 static int rt_alloc(void **, int);
139 static void rt_free(void *);
140
141 static void rt_change_priority(kthread_t *, rtproc_t *);
142
143 static id_t rt_cid; /* real-time class ID */
144 static rtproc_t rt_plisthead; /* dummy rtproc at head of rtproc list */
145 static kmutex_t rt_dptblock; /* protects realtime dispatch table */
146 static kmutex_t rt_list_lock; /* protects RT thread list */
147
148 extern rtdpent_t *rt_getdptbl(void);
149
150 static struct classfuncs rt_classfuncs = {
151 /* class ops */
152 rt_admin,
153 rt_getclinfo,
154 rt_parmsin,
155 rt_parmsout,
156 rt_vaparmsin,
157 rt_vaparmsout,
158 rt_getclpri,
159 rt_alloc,
160 rt_free,
161 /* thread ops */
162 rt_enterclass,
163 rt_exitclass,
164 rt_canexit,
165 rt_fork,
166 rt_forkret,
167 rt_parmsget,
168 rt_parmsset,
169 rt_nullsys, /* stop */
170 rt_nullsys, /* exit */
171 rt_nullsys, /* active */
172 rt_nullsys, /* inactive */
173 rt_swapin,
174 rt_swapout,
175 rt_nullsys, /* trapret */
176 rt_preempt,
177 rt_setrun,
178 rt_nullsys, /* sleep */
179 rt_tick,
180 rt_wakeup,
181 rt_donice,
182 rt_globpri,
183 rt_nullsys, /* set_process_group */
184 rt_yield,
185 rt_doprio,
186 };
187
188 /*
189 * Real-time class initialization. Called by dispinit() at boot time.
190 * We can ignore the clparmsz argument since we know that the smallest
191 * possible parameter buffer is big enough for us.
192 */
193 /* ARGSUSED */
194 pri_t
885 else if ((rtkprmsp->rt_cflags & RT_DOTQ) != 0)
886 rtpp->rt_timeleft = rtpp->rt_pquantum = rtkprmsp->rt_tqntm;
887
888 if ((rtkprmsp->rt_cflags & RT_DOSIG) != 0)
889 rtpp->rt_tqsignal = rtkprmsp->rt_tqsig;
890
891 thread_unlock(tx);
892 return (0);
893 }
894
895
896 /*
897 * Arrange for thread to be placed in appropriate location
898 * on dispatcher queue. Runs at splhi() since the clock
899 * interrupt can cause RTBACKQ to be set.
900 */
901 static void
902 rt_preempt(kthread_t *t)
903 {
904 rtproc_t *rtpp = (rtproc_t *)(t->t_cldata);
905 klwp_t *lwp;
906
907 ASSERT(THREAD_LOCK_HELD(t));
908
909 /*
910 * If the state is user I allow swapping because I know I won't
911 * be holding any locks.
912 */
913 if ((lwp = curthread->t_lwp) != NULL && lwp->lwp_state == LWP_USER)
914 t->t_schedflag &= ~TS_DONT_SWAP;
915 if ((rtpp->rt_flags & RTBACKQ) != 0) {
916 rtpp->rt_timeleft = rtpp->rt_pquantum;
917 rtpp->rt_flags &= ~RTBACKQ;
918 setbackdq(t);
919 } else
920 setfrontdq(t);
921
922 }
923
924 /*
925 * Return the global priority associated with this rt_pri.
926 */
927 static pri_t
928 rt_globpri(kthread_t *t)
929 {
930 rtproc_t *rtprocp = (rtproc_t *)t->t_cldata;
931 return (rt_dptbl[rtprocp->rt_pri].rt_globpri);
932 }
933
934 static void
935 rt_setrun(kthread_t *t)
936 {
937 rtproc_t *rtpp = (rtproc_t *)(t->t_cldata);
938
939 ASSERT(THREAD_LOCK_HELD(t));
940
941 rtpp->rt_timeleft = rtpp->rt_pquantum;
942 rtpp->rt_flags &= ~RTBACKQ;
943 setbackdq(t);
944 }
945
946 /*
947 * Returns the priority of the thread, -1 if the thread is loaded or ineligible
948 * for swapin.
949 *
950 * FX and RT threads are designed so that they don't swapout; however, it
951 * is possible that while the thread is swapped out and in another class, it
952 * can be changed to FX or RT. Since these threads should be swapped in as
953 * soon as they're runnable, rt_swapin returns SHRT_MAX, and fx_swapin
954 * returns SHRT_MAX - 1, so that it gives deference to any swapped out RT
955 * threads.
956 */
957 /* ARGSUSED */
958 static pri_t
959 rt_swapin(kthread_t *t, int flags)
960 {
961 pri_t tpri = -1;
962
963 ASSERT(THREAD_LOCK_HELD(t));
964
965 if (t->t_state == TS_RUN && (t->t_schedflag & TS_LOAD) == 0) {
966 tpri = (pri_t)SHRT_MAX;
967 }
968
969 return (tpri);
970 }
971
972 /*
973 * Return an effective priority for swapout.
974 */
975 /* ARGSUSED */
976 static pri_t
977 rt_swapout(kthread_t *t, int flags)
978 {
979 ASSERT(THREAD_LOCK_HELD(t));
980
981 return (-1);
982 }
983
984 /*
985 * Check for time slice expiration (unless thread has infinite time
986 * slice). If time slice has expired arrange for thread to be preempted
987 * and placed on back of queue.
988 */
989 static void
990 rt_tick(kthread_t *t)
991 {
992 rtproc_t *rtpp = (rtproc_t *)(t->t_cldata);
993
994 ASSERT(MUTEX_HELD(&(ttoproc(t))->p_lock));
995
996 thread_lock(t);
997 if ((rtpp->rt_pquantum != RT_TQINF && --rtpp->rt_timeleft == 0) ||
998 (t->t_state == TS_ONPROC && DISP_MUST_SURRENDER(t))) {
999 if (rtpp->rt_timeleft == 0 && rtpp->rt_tqsignal) {
1000 thread_unlock(t);
1001 sigtoproc(ttoproc(t), t, rtpp->rt_tqsignal);
|
114 static int rt_enterclass(kthread_t *, id_t, void *, cred_t *, void *);
115 static int rt_fork(kthread_t *, kthread_t *, void *);
116 static int rt_getclinfo(void *);
117 static int rt_getclpri(pcpri_t *);
118 static int rt_parmsin(void *);
119 static int rt_parmsout(void *, pc_vaparms_t *);
120 static int rt_vaparmsin(void *, pc_vaparms_t *);
121 static int rt_vaparmsout(void *, pc_vaparms_t *);
122 static int rt_parmsset(kthread_t *, void *, id_t, cred_t *);
123 static int rt_donice(kthread_t *, cred_t *, int, int *);
124 static int rt_doprio(kthread_t *, cred_t *, int, int *);
125 static void rt_exitclass(void *);
126 static int rt_canexit(kthread_t *, cred_t *);
127 static void rt_forkret(kthread_t *, kthread_t *);
128 static void rt_nullsys();
129 static void rt_parmsget(kthread_t *, void *);
130 static void rt_preempt(kthread_t *);
131 static void rt_setrun(kthread_t *);
132 static void rt_tick(kthread_t *);
133 static void rt_wakeup(kthread_t *);
134 static pri_t rt_globpri(kthread_t *);
135 static void rt_yield(kthread_t *);
136 static int rt_alloc(void **, int);
137 static void rt_free(void *);
138
139 static void rt_change_priority(kthread_t *, rtproc_t *);
140
141 static id_t rt_cid; /* real-time class ID */
142 static rtproc_t rt_plisthead; /* dummy rtproc at head of rtproc list */
143 static kmutex_t rt_dptblock; /* protects realtime dispatch table */
144 static kmutex_t rt_list_lock; /* protects RT thread list */
145
146 extern rtdpent_t *rt_getdptbl(void);
147
148 static struct classfuncs rt_classfuncs = {
149 /* class ops */
150 rt_admin,
151 rt_getclinfo,
152 rt_parmsin,
153 rt_parmsout,
154 rt_vaparmsin,
155 rt_vaparmsout,
156 rt_getclpri,
157 rt_alloc,
158 rt_free,
159 /* thread ops */
160 rt_enterclass,
161 rt_exitclass,
162 rt_canexit,
163 rt_fork,
164 rt_forkret,
165 rt_parmsget,
166 rt_parmsset,
167 rt_nullsys, /* stop */
168 rt_nullsys, /* exit */
169 rt_nullsys, /* active */
170 rt_nullsys, /* inactive */
171 rt_nullsys, /* trapret */
172 rt_preempt,
173 rt_setrun,
174 rt_nullsys, /* sleep */
175 rt_tick,
176 rt_wakeup,
177 rt_donice,
178 rt_globpri,
179 rt_nullsys, /* set_process_group */
180 rt_yield,
181 rt_doprio,
182 };
183
184 /*
185 * Real-time class initialization. Called by dispinit() at boot time.
186 * We can ignore the clparmsz argument since we know that the smallest
187 * possible parameter buffer is big enough for us.
188 */
189 /* ARGSUSED */
190 pri_t
881 else if ((rtkprmsp->rt_cflags & RT_DOTQ) != 0)
882 rtpp->rt_timeleft = rtpp->rt_pquantum = rtkprmsp->rt_tqntm;
883
884 if ((rtkprmsp->rt_cflags & RT_DOSIG) != 0)
885 rtpp->rt_tqsignal = rtkprmsp->rt_tqsig;
886
887 thread_unlock(tx);
888 return (0);
889 }
890
891
892 /*
893 * Arrange for thread to be placed in appropriate location
894 * on dispatcher queue. Runs at splhi() since the clock
895 * interrupt can cause RTBACKQ to be set.
896 */
897 static void
898 rt_preempt(kthread_t *t)
899 {
900 rtproc_t *rtpp = (rtproc_t *)(t->t_cldata);
901
902 ASSERT(THREAD_LOCK_HELD(t));
903
904 if ((rtpp->rt_flags & RTBACKQ) != 0) {
905 rtpp->rt_timeleft = rtpp->rt_pquantum;
906 rtpp->rt_flags &= ~RTBACKQ;
907 setbackdq(t);
908 } else
909 setfrontdq(t);
910
911 }
912
913 /*
914 * Return the global priority associated with this rt_pri.
915 */
916 static pri_t
917 rt_globpri(kthread_t *t)
918 {
919 rtproc_t *rtprocp = (rtproc_t *)t->t_cldata;
920 return (rt_dptbl[rtprocp->rt_pri].rt_globpri);
921 }
922
923 static void
924 rt_setrun(kthread_t *t)
925 {
926 rtproc_t *rtpp = (rtproc_t *)(t->t_cldata);
927
928 ASSERT(THREAD_LOCK_HELD(t));
929
930 rtpp->rt_timeleft = rtpp->rt_pquantum;
931 rtpp->rt_flags &= ~RTBACKQ;
932 setbackdq(t);
933 }
934
935 /*
936 * Check for time slice expiration (unless thread has infinite time
937 * slice). If time slice has expired arrange for thread to be preempted
938 * and placed on back of queue.
939 */
940 static void
941 rt_tick(kthread_t *t)
942 {
943 rtproc_t *rtpp = (rtproc_t *)(t->t_cldata);
944
945 ASSERT(MUTEX_HELD(&(ttoproc(t))->p_lock));
946
947 thread_lock(t);
948 if ((rtpp->rt_pquantum != RT_TQINF && --rtpp->rt_timeleft == 0) ||
949 (t->t_state == TS_ONPROC && DISP_MUST_SURRENDER(t))) {
950 if (rtpp->rt_timeleft == 0 && rtpp->rt_tqsignal) {
951 thread_unlock(t);
952 sigtoproc(ttoproc(t), t, rtpp->rt_tqsignal);
|