1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  27 /*        All Rights Reserved   */
  28 
  29 
  30 #ifndef _SYS_DISP_H
  31 #define _SYS_DISP_H
  32 
  33 #pragma ident   "%Z%%M% %I%     %E% SMI"        /* SVr4.0 1.11  */
  34 
  35 #include <sys/priocntl.h>
  36 #include <sys/thread.h>
  37 #include <sys/class.h>
  38 
  39 #ifdef  __cplusplus
  40 extern "C" {
  41 #endif
  42 
  43 /*
  44  * The following is the format of a dispatcher queue entry.
  45  */
  46 typedef struct dispq {
  47         kthread_t       *dq_first;      /* first thread on queue or NULL */
  48         kthread_t       *dq_last;       /* last thread on queue or NULL */
  49         int             dq_sruncnt;     /* number of loaded, runnable */
  50                                         /*    threads on queue */
  51 } dispq_t;
  52 
  53 /*
  54  * Dispatch queue structure.
  55  */
  56 typedef struct _disp {
  57         disp_lock_t     disp_lock;      /* protects dispatching fields */
  58         pri_t           disp_npri;      /* # of priority levels in queue */
  59         dispq_t         *disp_q;                /* the dispatch queue */
  60         dispq_t         *disp_q_limit;  /* ptr past end of dispatch queue */
  61         ulong_t         *disp_qactmap;  /* bitmap of active dispatch queues */
  62 
  63         /*
  64          * Priorities:
  65          *      disp_maxrunpri is the maximum run priority of runnable threads
  66          *      on this queue.  It is -1 if nothing is runnable.
  67          *
  68          *      disp_max_unbound_pri is the maximum run priority of threads on
  69          *      this dispatch queue but runnable by any CPU.  This may be left
  70          *      artificially high, then corrected when some CPU tries to take
  71          *      an unbound thread.  It is -1 if nothing is runnable.
  72          */
  73         pri_t           disp_maxrunpri; /* maximum run priority */
  74         pri_t           disp_max_unbound_pri;   /* max pri of unbound threads */
  75 
  76         volatile int    disp_nrunnable; /* runnable threads in cpu dispq */
  77 
  78         struct cpu      *disp_cpu;      /* cpu owning this queue or NULL */
  79         hrtime_t        disp_steal;     /* time when threads become stealable */
  80 } disp_t;
  81 
  82 #if defined(_KERNEL)
  83 
  84 #define MAXCLSYSPRI     99
  85 #define MINCLSYSPRI     60
  86 
  87 
  88 /*
  89  * Global scheduling variables.
  90  *      - See sys/cpuvar.h for CPU-local variables.
  91  */
  92 extern int      nswapped;       /* number of swapped threads */
  93                                 /* nswapped protected by swap_lock */
  94 
  95 extern  pri_t   minclsyspri;    /* minimum level of any system class */
  96 extern  pri_t   maxclsyspri;    /* maximum level of any system class */
  97 extern  pri_t   intr_pri;       /* interrupt thread priority base level */
  98 
  99 /*
 100  * Minimum amount of time that a thread can remain runnable before it can
 101  * be stolen by another CPU (in nanoseconds).
 102  */
 103 extern hrtime_t nosteal_nsec;
 104 
 105 /*
 106  * Kernel preemption occurs if a higher-priority thread is runnable with
 107  * a priority at or above kpreemptpri.
 108  *
 109  * So that other processors can watch for such threads, a separate
 110  * dispatch queue with unbound work above kpreemptpri is maintained.
 111  * This is part of the CPU partition structure (cpupart_t).
 112  */
 113 extern  pri_t   kpreemptpri;    /* level above which preemption takes place */
 114 
 115 extern void             disp_kp_alloc(disp_t *, pri_t); /* allocate kp queue */
 116 extern void             disp_kp_free(disp_t *);         /* free kp queue */
 117 
 118 /*
 119  * Macro for use by scheduling classes to decide whether the thread is about
 120  * to be scheduled or not.  This returns the maximum run priority.
 121  */
 122 #define DISP_MAXRUNPRI(t)       ((t)->t_disp_queue->disp_maxrunpri)
 123 
 124 /*
 125  * Platform callbacks for various dispatcher operations
 126  *
 127  * idle_cpu() is invoked when a cpu goes idle, and has nothing to do.
 128  * disp_enq_thread() is invoked when a thread is placed on a run queue.
 129  */
 130 extern void     (*idle_cpu)();
 131 extern void     (*disp_enq_thread)(struct cpu *, int);
 132 
 133 
 134 extern int              dispdeq(kthread_t *);
 135 extern void             dispinit(void);
 136 extern void             disp_add(sclass_t *);
 137 extern int              intr_active(struct cpu *, int);
 138 extern int              servicing_interrupt(void);
 139 extern void             preempt(void);
 140 extern void             setbackdq(kthread_t *);
 141 extern void             setfrontdq(kthread_t *);
 142 extern void             swtch(void);
 143 extern void             swtch_to(kthread_t *);
 144 extern void             swtch_from_zombie(void)
 145                                 __NORETURN;
 146 extern void             cpu_rechoose(kthread_t *);
 147 extern void             cpu_surrender(kthread_t *);
 148 extern void             kpreempt(int);
 149 extern struct cpu       *disp_lowpri_cpu(struct cpu *, struct lgrp_ld *, pri_t,
 150                             struct cpu *);
 151 extern int              disp_bound_threads(struct cpu *, int);
 152 extern int              disp_bound_anythreads(struct cpu *, int);
 153 extern int              disp_bound_partition(struct cpu *, int);
 154 extern void             disp_cpu_init(struct cpu *);
 155 extern void             disp_cpu_fini(struct cpu *);
 156 extern void             disp_cpu_inactive(struct cpu *);
 157 extern void             disp_adjust_unbound_pri(kthread_t *);
 158 extern void             resume(kthread_t *);
 159 extern void             resume_from_intr(kthread_t *);
 160 extern void             resume_from_zombie(kthread_t *)
 161                                 __NORETURN;
 162 extern void             disp_swapped_enq(kthread_t *);
 163 extern int              disp_anywork(void);
 164 
 165 #define KPREEMPT_SYNC           (-1)
 166 #define kpreempt_disable()                              \
 167         {                                               \
 168                 curthread->t_preempt++;                      \
 169                 ASSERT(curthread->t_preempt >= 1);        \
 170         }
 171 #define kpreempt_enable()                               \
 172         {                                               \
 173                 ASSERT(curthread->t_preempt >= 1);        \
 174                 if (--curthread->t_preempt == 0 &&   \
 175                     CPU->cpu_kprunrun)                       \
 176                         kpreempt(KPREEMPT_SYNC);        \
 177         }
 178 
 179 #endif  /* _KERNEL */
 180 
 181 #ifdef  __cplusplus
 182 }
 183 #endif
 184 
 185 #endif  /* _SYS_DISP_H */