hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
 * Copyright (C) 2008 Philippe Gerum <rpm@xenomai.org>.
 *
 * Xenomai is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 *
 * Xenomai is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Xenomai; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */
#include <cobalt/kernel/sched.h>
 
static void xnsched_rt_init(struct xnsched *sched)
{
   xnsched_initq(&sched->rt.runnable);
}
 
static void xnsched_rt_requeue(struct xnthread *thread)
{
   /*
    * Put back at same place: i.e. requeue to head of current
    * priority group (i.e. LIFO, used for preemption handling).
    */
   __xnsched_rt_requeue(thread);
}
 
static void xnsched_rt_enqueue(struct xnthread *thread)
{
   /*
    * Enqueue for next pick: i.e. move to end of current priority
    * group (i.e. FIFO).
    */
   __xnsched_rt_enqueue(thread);
}
 
static void xnsched_rt_dequeue(struct xnthread *thread)
{
   /*
    * Pull from the runnable thread queue.
    */
   __xnsched_rt_dequeue(thread);
}
 
static void xnsched_rt_rotate(struct xnsched *sched,
                 const union xnsched_policy_param *p)
{
   struct xnthread *thread, *curr;
 
   if (xnsched_emptyq_p(&sched->rt.runnable))
       return;    /* No runnable thread in this class. */
 
   curr = sched->curr;
 
   if (p->rt.prio == XNSCHED_RUNPRIO)
       thread = curr;
   else {
       thread = xnsched_findq(&sched->rt.runnable, p->rt.prio);
       if (thread == NULL)
           return;
   }
 
   /*
    * In case we picked the current thread, we have to make sure
    * not to move it back to the run queue if it was blocked
    * before we were called. The same goes if the current thread
    * holds the scheduler lock.
    */
   if (thread != curr ||
       (!xnthread_test_state(curr, XNTHREAD_BLOCK_BITS) &&
        curr->lock_count == 0))
       xnsched_putback(thread);
}
 
void xnsched_rt_tick(struct xnsched *sched)
{
   /*
    * The round-robin time credit is only consumed by a running
    * thread that neither holds the scheduler lock nor was
    * blocked before entering this callback. As the time slice is
    * exhausted for the running thread, move it back to the
    * run queue at the end of its priority group.
    */
   xnsched_putback(sched->curr);
}
 
static bool xnsched_rt_setparam(struct xnthread *thread,
               const union xnsched_policy_param *p)
{
   return __xnsched_rt_setparam(thread, p);
}
 
static void xnsched_rt_getparam(struct xnthread *thread,
               union xnsched_policy_param *p)
{
   __xnsched_rt_getparam(thread, p);
}
 
static void xnsched_rt_trackprio(struct xnthread *thread,
                const union xnsched_policy_param *p)
{
   __xnsched_rt_trackprio(thread, p);
}
 
static void xnsched_rt_protectprio(struct xnthread *thread, int prio)
{
   __xnsched_rt_protectprio(thread, prio);
}
 
#ifdef CONFIG_XENO_OPT_VFILE
 
struct xnvfile_directory sched_rt_vfroot;
 
struct vfile_sched_rt_priv {
   struct xnthread *curr;
};
 
struct vfile_sched_rt_data {
   int cpu;
   pid_t pid;
   char name[XNOBJECT_NAME_LEN];
   xnticks_t period;
   int cprio;
};
 
static struct xnvfile_snapshot_ops vfile_sched_rt_ops;
 
static struct xnvfile_snapshot vfile_sched_rt = {
   .privsz = sizeof(struct vfile_sched_rt_priv),
   .datasz = sizeof(struct vfile_sched_rt_data),
   .tag = &nkthreadlist_tag,
   .ops = &vfile_sched_rt_ops,
};
 
static int vfile_sched_rt_rewind(struct xnvfile_snapshot_iterator *it)
{
   struct vfile_sched_rt_priv *priv = xnvfile_iterator_priv(it);
   int nrthreads = xnsched_class_rt.nthreads;
 
   if (nrthreads == 0)
       return -ESRCH;
 
   priv->curr = list_first_entry(&nkthreadq, struct xnthread, glink);
 
   return nrthreads;
}
 
static int vfile_sched_rt_next(struct xnvfile_snapshot_iterator *it,
                  void *data)
{
   struct vfile_sched_rt_priv *priv = xnvfile_iterator_priv(it);
   struct vfile_sched_rt_data *p = data;
   struct xnthread *thread;
 
   if (priv->curr == NULL)
       return 0;    /* All done. */
 
   thread = priv->curr;
   if (list_is_last(&thread->glink, &nkthreadq))
       priv->curr = NULL;
   else
       priv->curr = list_next_entry(thread, glink);
 
   if (thread->base_class != &xnsched_class_rt ||
       xnthread_test_state(thread, XNWEAK))
       return VFILE_SEQ_SKIP;
 
   p->cpu = xnsched_cpu(thread->sched);
   p->pid = xnthread_host_pid(thread);
   memcpy(p->name, thread->name, sizeof(p->name));
   p->cprio = thread->cprio;
   p->period = xnthread_get_period(thread);
 
   return 1;
}
 
static int vfile_sched_rt_show(struct xnvfile_snapshot_iterator *it,
                  void *data)
{
   struct vfile_sched_rt_data *p = data;
   char pribuf[16], ptbuf[16];
 
   if (p == NULL)
       xnvfile_printf(it, "%-3s  %-6s %-8s %-10s %s\n",
                  "CPU", "PID", "PRI", "PERIOD", "NAME");
   else {
       ksformat(pribuf, sizeof(pribuf), "%3d", p->cprio);
       xntimer_format_time(p->period, ptbuf, sizeof(ptbuf));
       xnvfile_printf(it, "%3u  %-6d %-8s %-10s %s\n",
                  p->cpu,
                  p->pid,
                  pribuf,
                  ptbuf,
                  p->name);
   }
 
   return 0;
}
 
static struct xnvfile_snapshot_ops vfile_sched_rt_ops = {
   .rewind = vfile_sched_rt_rewind,
   .next = vfile_sched_rt_next,
   .show = vfile_sched_rt_show,
};
 
static int xnsched_rt_init_vfile(struct xnsched_class *schedclass,
                struct xnvfile_directory *vfroot)
{
   int ret;
 
   ret = xnvfile_init_dir(schedclass->name, &sched_rt_vfroot, vfroot);
   if (ret)
       return ret;
 
   return xnvfile_init_snapshot("threads", &vfile_sched_rt,
                    &sched_rt_vfroot);
}
 
static void xnsched_rt_cleanup_vfile(struct xnsched_class *schedclass)
{
   xnvfile_destroy_snapshot(&vfile_sched_rt);
   xnvfile_destroy_dir(&sched_rt_vfroot);
}
 
#endif /* CONFIG_XENO_OPT_VFILE */
 
struct xnsched_class xnsched_class_rt = {
   .sched_init        =    xnsched_rt_init,
   .sched_enqueue        =    xnsched_rt_enqueue,
   .sched_dequeue        =    xnsched_rt_dequeue,
   .sched_requeue        =    xnsched_rt_requeue,
   .sched_pick        =    xnsched_rt_pick,
   .sched_tick        =    xnsched_rt_tick,
   .sched_rotate        =    xnsched_rt_rotate,
   .sched_forget        =    NULL,
   .sched_kick        =    NULL,
   .sched_declare        =    NULL,
   .sched_setparam        =    xnsched_rt_setparam,
   .sched_trackprio    =    xnsched_rt_trackprio,
   .sched_protectprio    =    xnsched_rt_protectprio,
   .sched_getparam        =    xnsched_rt_getparam,
#ifdef CONFIG_XENO_OPT_VFILE
   .sched_init_vfile    =    xnsched_rt_init_vfile,
   .sched_cleanup_vfile    =    xnsched_rt_cleanup_vfile,
#endif
   .weight            =    XNSCHED_CLASS_WEIGHT(4),
   .policy            =    SCHED_FIFO,
   .name            =    "rt"
};
EXPORT_SYMBOL_GPL(xnsched_class_rt);