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 #include <sys/priocntl.h>
  34 #include <sys/thread.h>
  35 #include <sys/class.h>
  36 
  37 #ifdef  __cplusplus
  38 extern "C" {
  39 #endif
  40 
  41 /*
  42  * The following is the format of a dispatcher queue entry.
  43  */
  44 typedef struct dispq {
  45         kthread_t       *dq_first;      /* first thread on queue or NULL */
  46         kthread_t       *dq_last;       /* last thread on queue or NULL */
  47         int             dq_sruncnt;     /* number of loaded, runnable */
  48                                         /*    threads on queue */
  49 } dispq_t;
  50 
  51 /*
  52  * Dispatch queue structure.
  53  */
  54 typedef struct _disp {
  55         disp_lock_t     disp_lock;      /* protects dispatching fields */
  56         pri_t           disp_npri;      /* # of priority levels in queue */
  57         dispq_t         *disp_q;                /* the dispatch queue */
  58         dispq_t         *disp_q_limit;  /* ptr past end of dispatch queue */
  59         ulong_t         *disp_qactmap;  /* bitmap of active dispatch queues */
  60 
  61         /*
  62          * Priorities:
  63          *      disp_maxrunpri is the maximum run priority of runnable threads
  64          *      on this queue.  It is -1 if nothing is runnable.
  65          *
  66          *      disp_max_unbound_pri is the maximum run priority of threads on
  67          *      this dispatch queue but runnable by any CPU.  This may be left
  68          *      artificially high, then corrected when some CPU tries to take
  69          *      an unbound thread.  It is -1 if nothing is runnable.
  70          */
  71         pri_t           disp_maxrunpri; /* maximum run priority */
  72         pri_t           disp_max_unbound_pri;   /* max pri of unbound threads */
  73 
  74         volatile int    disp_nrunnable; /* runnable threads in cpu dispq */
  75 
  76         struct cpu      *disp_cpu;      /* cpu owning this queue or NULL */
  77         hrtime_t        disp_steal;     /* time when threads become stealable */
  78 } disp_t;
  79 
  80 #if defined(_KERNEL)
  81 
  82 #define MAXCLSYSPRI     99
  83 #define MINCLSYSPRI     60
  84 
  85 
  86 /*
  87  * Global scheduling variables.
  88  *      - See sys/cpuvar.h for CPU-local variables.
  89  */
  90 extern int      nswapped;       /* number of swapped threads */
  91                                 /* nswapped protected by swap_lock */
  92 
  93 extern  pri_t   minclsyspri;    /* minimum level of any system class */
  94 extern  pri_t   maxclsyspri;    /* maximum level of any system class */
  95 extern  pri_t   intr_pri;       /* interrupt thread priority base level */
  96 
  97 /*
  98  * Minimum amount of time that a thread can remain runnable before it can
  99  * be stolen by another CPU (in nanoseconds).
 100  */
 101 extern hrtime_t nosteal_nsec;
 102 
 103 /*
 104  * Kernel preemption occurs if a higher-priority thread is runnable with
 105  * a priority at or above kpreemptpri.
 106  *
 107  * So that other processors can watch for such threads, a separate
 108  * dispatch queue with unbound work above kpreemptpri is maintained.
 109  * This is part of the CPU partition structure (cpupart_t).
 110  */
 111 extern  pri_t   kpreemptpri;    /* level above which preemption takes place */
 112 
 113 extern void             disp_kp_alloc(disp_t *, pri_t); /* allocate kp queue */
 114 extern void             disp_kp_free(disp_t *);         /* free kp queue */
 115 
 116 /*
 117  * Macro for use by scheduling classes to decide whether the thread is about
 118  * to be scheduled or not.  This returns the maximum run priority.
 119  */
 120 #define DISP_MAXRUNPRI(t)       ((t)->t_disp_queue->disp_maxrunpri)
 121 
 122 /*
 123  * Platform callbacks for various dispatcher operations
 124  *
 125  * idle_cpu() is invoked when a cpu goes idle, and has nothing to do.
 126  * disp_enq_thread() is invoked when a thread is placed on a run queue.
 127  */
 128 extern void     (*idle_cpu)();
 129 extern void     (*disp_enq_thread)(struct cpu *, int);
 130 
 131 
 132 extern int              dispdeq(kthread_t *);
 133 extern void             dispinit(void);
 134 extern void             disp_add(sclass_t *);
 135 extern int              intr_active(struct cpu *, int);
 136 extern int              servicing_interrupt(void);
 137 extern void             preempt(void);
 138 extern void             setbackdq(kthread_t *);
 139 extern void             setfrontdq(kthread_t *);
 140 extern void             swtch(void);
 141 extern void             swtch_to(kthread_t *);
 142 extern void             swtch_from_zombie(void)
 143                                 __NORETURN;
 144 extern void             cpu_rechoose(kthread_t *);
 145 extern void             cpu_surrender(kthread_t *);
 146 extern void             kpreempt(int);
 147 extern struct cpu       *disp_lowpri_cpu(struct cpu *, struct lgrp_ld *, pri_t,
 148                             struct cpu *);
 149 extern int              disp_bound_threads(struct cpu *, int);
 150 extern int              disp_bound_anythreads(struct cpu *, int);
 151 extern int              disp_bound_partition(struct cpu *, int);
 152 extern void             disp_cpu_init(struct cpu *);
 153 extern void             disp_cpu_fini(struct cpu *);
 154 extern void             disp_cpu_inactive(struct cpu *);
 155 extern void             disp_adjust_unbound_pri(kthread_t *);
 156 extern void             resume(kthread_t *);
 157 extern void             resume_from_intr(kthread_t *);
 158 extern void             resume_from_zombie(kthread_t *)
 159                                 __NORETURN;
 160 extern void             disp_swapped_enq(kthread_t *);
 161 extern int              disp_anywork(void);
 162 
 163 #define KPREEMPT_SYNC           (-1)
 164 #define kpreempt_disable()                              \
 165         {                                               \
 166                 curthread->t_preempt++;                      \
 167                 ASSERT(curthread->t_preempt >= 1);        \
 168         }
 169 #define kpreempt_enable()                               \
 170         {                                               \
 171                 ASSERT(curthread->t_preempt >= 1);        \
 172                 if (--curthread->t_preempt == 0 &&   \
 173                     CPU->cpu_kprunrun)                       \
 174                         kpreempt(KPREEMPT_SYNC);        \
 175         }
 176 
 177 #endif  /* _KERNEL */
 178 
 179 #ifdef  __cplusplus
 180 }
 181 #endif
 182 
 183 #endif  /* _SYS_DISP_H */