/* * Copyright (C) 2013 Philippe Gerum . * * 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 #include static void xnsched_weak_init(struct xnsched *sched) { xnsched_initq(&sched->weak.runnable); } static void xnsched_weak_requeue(struct xnthread *thread) { xnsched_addq(&thread->sched->weak.runnable, thread); } static void xnsched_weak_enqueue(struct xnthread *thread) { xnsched_addq_tail(&thread->sched->weak.runnable, thread); } static void xnsched_weak_dequeue(struct xnthread *thread) { xnsched_delq(&thread->sched->weak.runnable, thread); } static struct xnthread *xnsched_weak_pick(struct xnsched *sched) { return xnsched_getq(&sched->weak.runnable); } static bool xnsched_weak_setparam(struct xnthread *thread, const union xnsched_policy_param *p) { if (!xnthread_test_state(thread, XNBOOST)) xnthread_set_state(thread, XNWEAK); return xnsched_set_effective_priority(thread, p->weak.prio); } static void xnsched_weak_getparam(struct xnthread *thread, union xnsched_policy_param *p) { p->weak.prio = thread->cprio; } static void xnsched_weak_trackprio(struct xnthread *thread, const union xnsched_policy_param *p) { if (p) thread->cprio = p->weak.prio; else thread->cprio = thread->bprio; } static void xnsched_weak_protectprio(struct xnthread *thread, int prio) { if (prio > XNSCHED_WEAK_MAX_PRIO) prio = XNSCHED_WEAK_MAX_PRIO; thread->cprio = prio; } static int xnsched_weak_chkparam(struct xnthread *thread, const union xnsched_policy_param *p) { if (p->weak.prio < XNSCHED_WEAK_MIN_PRIO || p->weak.prio > XNSCHED_WEAK_MAX_PRIO) return -EINVAL; return 0; } #ifdef CONFIG_XENO_OPT_VFILE struct xnvfile_directory sched_weak_vfroot; struct vfile_sched_weak_priv { struct xnthread *curr; }; struct vfile_sched_weak_data { int cpu; pid_t pid; char name[XNOBJECT_NAME_LEN]; int cprio; }; static struct xnvfile_snapshot_ops vfile_sched_weak_ops; static struct xnvfile_snapshot vfile_sched_weak = { .privsz = sizeof(struct vfile_sched_weak_priv), .datasz = sizeof(struct vfile_sched_weak_data), .tag = &nkthreadlist_tag, .ops = &vfile_sched_weak_ops, }; static int vfile_sched_weak_rewind(struct xnvfile_snapshot_iterator *it) { struct vfile_sched_weak_priv *priv = xnvfile_iterator_priv(it); int nrthreads = xnsched_class_weak.nthreads; if (nrthreads == 0) return -ESRCH; priv->curr = list_first_entry(&nkthreadq, struct xnthread, glink); return nrthreads; } static int vfile_sched_weak_next(struct xnvfile_snapshot_iterator *it, void *data) { struct vfile_sched_weak_priv *priv = xnvfile_iterator_priv(it); struct vfile_sched_weak_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_weak) 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; return 1; } static int vfile_sched_weak_show(struct xnvfile_snapshot_iterator *it, void *data) { struct vfile_sched_weak_data *p = data; char pribuf[16]; if (p == NULL) xnvfile_printf(it, "%-3s %-6s %-4s %s\n", "CPU", "PID", "PRI", "NAME"); else { ksformat(pribuf, sizeof(pribuf), "%3d", p->cprio); xnvfile_printf(it, "%3u %-6d %-4s %s\n", p->cpu, p->pid, pribuf, p->name); } return 0; } static struct xnvfile_snapshot_ops vfile_sched_weak_ops = { .rewind = vfile_sched_weak_rewind, .next = vfile_sched_weak_next, .show = vfile_sched_weak_show, }; static int xnsched_weak_init_vfile(struct xnsched_class *schedclass, struct xnvfile_directory *vfroot) { int ret; ret = xnvfile_init_dir(schedclass->name, &sched_weak_vfroot, vfroot); if (ret) return ret; return xnvfile_init_snapshot("threads", &vfile_sched_weak, &sched_weak_vfroot); } static void xnsched_weak_cleanup_vfile(struct xnsched_class *schedclass) { xnvfile_destroy_snapshot(&vfile_sched_weak); xnvfile_destroy_dir(&sched_weak_vfroot); } #endif /* CONFIG_XENO_OPT_VFILE */ struct xnsched_class xnsched_class_weak = { .sched_init = xnsched_weak_init, .sched_enqueue = xnsched_weak_enqueue, .sched_dequeue = xnsched_weak_dequeue, .sched_requeue = xnsched_weak_requeue, .sched_pick = xnsched_weak_pick, .sched_tick = NULL, .sched_rotate = NULL, .sched_forget = NULL, .sched_kick = NULL, .sched_chkparam = xnsched_weak_chkparam, .sched_setparam = xnsched_weak_setparam, .sched_trackprio = xnsched_weak_trackprio, .sched_protectprio = xnsched_weak_protectprio, .sched_getparam = xnsched_weak_getparam, #ifdef CONFIG_XENO_OPT_VFILE .sched_init_vfile = xnsched_weak_init_vfile, .sched_cleanup_vfile = xnsched_weak_cleanup_vfile, #endif .weight = XNSCHED_CLASS_WEIGHT(1), .policy = SCHED_WEAK, .name = "weak" }; EXPORT_SYMBOL_GPL(xnsched_class_weak);