The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/posix4/ksched.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1996, 1997
    3  *      HD Associates, Inc.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by HD Associates, Inc
   16  * 4. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * $FreeBSD: releng/5.0/sys/posix4/ksched.c 106969 2002-11-15 22:55:06Z alfred $
   33  */
   34 
   35 /* ksched: Soft real time scheduling based on "rtprio".
   36  */
   37 
   38 #include "opt_posix.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/systm.h>
   42 #include <sys/lock.h>
   43 #include <sys/mutex.h>
   44 #include <sys/proc.h>
   45 #include <sys/resource.h>
   46 #include <sys/sched.h>
   47 
   48 #include <posix4/posix4.h>
   49 
   50 /* ksched: Real-time extension to support POSIX priority scheduling.
   51  */
   52 
   53 struct ksched {
   54         struct timespec rr_interval;
   55 };
   56 
   57 int ksched_attach(struct ksched **p)
   58 {
   59         struct ksched *ksched= p31b_malloc(sizeof(*ksched));
   60 
   61         ksched->rr_interval.tv_sec = 0;
   62         ksched->rr_interval.tv_nsec = 1000000000L / sched_rr_interval();
   63 
   64         *p = ksched;
   65         return 0;
   66 }
   67 
   68 int ksched_detach(struct ksched *ks)
   69 {
   70         p31b_free(ks);
   71 
   72         return 0;
   73 }
   74 
   75 /*
   76  * XXX About priorities
   77  *
   78  *      POSIX 1003.1b requires that numerically higher priorities be of
   79  *      higher priority.  It also permits sched_setparam to be
   80  *      implementation defined for SCHED_OTHER.  I don't like
   81  *      the notion of inverted priorites for normal processes when
   82  *  you can use "setpriority" for that.
   83  *
   84  *      I'm rejecting sched_setparam for SCHED_OTHER with EINVAL.
   85  */
   86 
   87 /* Macros to convert between the unix (lower numerically is higher priority)
   88  * and POSIX 1003.1b (higher numerically is higher priority)
   89  */
   90 
   91 #define p4prio_to_rtpprio(P) (RTP_PRIO_MAX - (P))
   92 #define rtpprio_to_p4prio(P) (RTP_PRIO_MAX - (P))
   93 
   94 /* These improve readability a bit for me:
   95  */
   96 #define P1B_PRIO_MIN rtpprio_to_p4prio(RTP_PRIO_MAX)
   97 #define P1B_PRIO_MAX rtpprio_to_p4prio(RTP_PRIO_MIN)
   98 
   99 static __inline int
  100 getscheduler(register_t *ret, struct ksched *ksched, struct thread *td)
  101 {
  102         struct rtprio rtp;
  103         int e = 0;
  104 
  105         mtx_lock_spin(&sched_lock);
  106         pri_to_rtp(td->td_ksegrp, &rtp);
  107         mtx_unlock_spin(&sched_lock);
  108         switch (rtp.type)
  109         {
  110                 case RTP_PRIO_FIFO:
  111                 *ret = SCHED_FIFO;
  112                 break;
  113 
  114                 case RTP_PRIO_REALTIME:
  115                 *ret = SCHED_RR;
  116                 break;
  117 
  118                 default:
  119                 *ret = SCHED_OTHER;
  120                 break;
  121         }
  122 
  123         return e;
  124 }
  125 
  126 int ksched_setparam(register_t *ret, struct ksched *ksched,
  127         struct thread *td, const struct sched_param *param)
  128 {
  129         register_t policy;
  130         int e;
  131 
  132         e = getscheduler(&policy, ksched, td);
  133 
  134         if (e == 0)
  135         {
  136                 if (policy == SCHED_OTHER)
  137                         e = EINVAL;
  138                 else
  139                         e = ksched_setscheduler(ret, ksched, td, policy, param);
  140         }
  141 
  142         return e;
  143 }
  144 
  145 int ksched_getparam(register_t *ret, struct ksched *ksched,
  146         struct thread *td, struct sched_param *param)
  147 {
  148         struct rtprio rtp;
  149 
  150         mtx_lock_spin(&sched_lock);
  151         pri_to_rtp(td->td_ksegrp, &rtp);
  152         mtx_unlock_spin(&sched_lock);
  153         if (RTP_PRIO_IS_REALTIME(rtp.type))
  154                 param->sched_priority = rtpprio_to_p4prio(rtp.prio);
  155 
  156         return 0;
  157 }
  158 
  159 /*
  160  * XXX The priority and scheduler modifications should
  161  *     be moved into published interfaces in kern/kern_sync.
  162  *
  163  * The permissions to modify process p were checked in "p31b_proc()".
  164  *
  165  */
  166 int ksched_setscheduler(register_t *ret, struct ksched *ksched,
  167         struct thread *td, int policy, const struct sched_param *param)
  168 {
  169         int e = 0;
  170         struct rtprio rtp;
  171         struct ksegrp *kg = td->td_ksegrp;
  172 
  173         switch(policy)
  174         {
  175                 case SCHED_RR:
  176                 case SCHED_FIFO:
  177 
  178                 if (param->sched_priority >= P1B_PRIO_MIN &&
  179                 param->sched_priority <= P1B_PRIO_MAX)
  180                 {
  181                         rtp.prio = p4prio_to_rtpprio(param->sched_priority);
  182                         rtp.type = (policy == SCHED_FIFO)
  183                                 ? RTP_PRIO_FIFO : RTP_PRIO_REALTIME;
  184 
  185                         mtx_lock_spin(&sched_lock);
  186                         rtp_to_pri(&rtp, kg);
  187                         FOREACH_THREAD_IN_GROUP(kg, td) { /* XXXKSE */
  188                                 if (TD_IS_RUNNING(td)) {
  189                                         td->td_kse->ke_flags |= KEF_NEEDRESCHED;
  190                                 } else if (TD_ON_RUNQ(td)) {
  191                                         if (td->td_priority > kg->kg_user_pri) {
  192                                                 sched_prio(td, kg->kg_user_pri);
  193                                         }
  194                                 }
  195                         }
  196                         mtx_unlock_spin(&sched_lock);
  197                 }
  198                 else
  199                         e = EPERM;
  200 
  201 
  202                 break;
  203 
  204                 case SCHED_OTHER:
  205                 {
  206                         rtp.type = RTP_PRIO_NORMAL;
  207                         rtp.prio = p4prio_to_rtpprio(param->sched_priority);
  208                         mtx_lock_spin(&sched_lock);
  209                         rtp_to_pri(&rtp, kg);
  210 
  211                         /* XXX Simply revert to whatever we had for last
  212                          *     normal scheduler priorities.
  213                          *     This puts a requirement
  214                          *     on the scheduling code: You must leave the
  215                          *     scheduling info alone.
  216                          */
  217                         FOREACH_THREAD_IN_GROUP(kg, td) {
  218                                 if (TD_IS_RUNNING(td)) {
  219                                         td->td_kse->ke_flags |= KEF_NEEDRESCHED;
  220                                 } else if (TD_ON_RUNQ(td)) {
  221                                         if (td->td_priority > kg->kg_user_pri) {
  222                                                 sched_prio(td, kg->kg_user_pri);
  223                                         }
  224                                 }
  225                                 
  226                         }
  227                         mtx_unlock_spin(&sched_lock);
  228                 }
  229                 break;
  230         }
  231 
  232         return e;
  233 }
  234 
  235 int ksched_getscheduler(register_t *ret, struct ksched *ksched, struct thread *td)
  236 {
  237         return getscheduler(ret, ksched, td);
  238 }
  239 
  240 /* ksched_yield: Yield the CPU.
  241  */
  242 int ksched_yield(register_t *ret, struct ksched *ksched)
  243 {
  244         mtx_lock_spin(&sched_lock);
  245         curthread->td_kse->ke_flags |= KEF_NEEDRESCHED;
  246         mtx_unlock_spin(&sched_lock);
  247         return 0;
  248 }
  249 
  250 int ksched_get_priority_max(register_t*ret, struct ksched *ksched, int policy)
  251 {
  252         int e = 0;
  253 
  254         switch (policy)
  255         {
  256                 case SCHED_FIFO:
  257                 case SCHED_RR:
  258                 *ret = RTP_PRIO_MAX;
  259                 break;
  260 
  261                 case SCHED_OTHER:
  262                 *ret =  PRIO_MAX;
  263                 break;
  264 
  265                 default:
  266                 e = EINVAL;
  267         }
  268 
  269         return e;
  270 }
  271 
  272 int ksched_get_priority_min(register_t *ret, struct ksched *ksched, int policy)
  273 {
  274         int e = 0;
  275 
  276         switch (policy)
  277         {
  278                 case SCHED_FIFO:
  279                 case SCHED_RR:
  280                 *ret = P1B_PRIO_MIN;
  281                 break;
  282 
  283                 case SCHED_OTHER:
  284                 *ret =  PRIO_MIN;
  285                 break;
  286 
  287                 default:
  288                 e = EINVAL;
  289         }
  290 
  291         return e;
  292 }
  293 
  294 int ksched_rr_get_interval(register_t *ret, struct ksched *ksched,
  295         struct thread *td, struct timespec *timespec)
  296 {
  297         *timespec = ksched->rr_interval;
  298 
  299         return 0;
  300 }

Cache object: 4e132e4bf41f53dc35f83199a94e6755


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.