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/sys/sleepq.h

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 /*      $NetBSD: sleepq.h,v 1.15 2008/10/10 09:44:35 pooka Exp $        */
    2 
    3 /*-
    4  * Copyright (c) 2002, 2006, 2007, 2008 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe and Andrew Doran.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #ifndef _SYS_SLEEPQ_H_
   33 #define _SYS_SLEEPQ_H_
   34 
   35 #include <sys/lwp.h>
   36 #include <sys/mutex.h>
   37 #include <sys/pool.h>
   38 #include <sys/queue.h>
   39 #include <sys/sched.h>
   40 #include <sys/syncobj.h>
   41 
   42 /*
   43  * Generic sleep queues.
   44  */
   45 
   46 #define SLEEPTAB_HASH_SHIFT     7
   47 #define SLEEPTAB_HASH_SIZE      (1 << SLEEPTAB_HASH_SHIFT)
   48 #define SLEEPTAB_HASH_MASK      (SLEEPTAB_HASH_SIZE - 1)
   49 #define SLEEPTAB_HASH(wchan)    (((uintptr_t)(wchan) >> 8) & SLEEPTAB_HASH_MASK)
   50 
   51 TAILQ_HEAD(sleepq, lwp);
   52 
   53 typedef struct sleepq sleepq_t;
   54 
   55 #ifdef _LP64
   56 typedef struct sleeptab {
   57         struct {
   58                 kmutex_t        st_mutex;
   59                 sleepq_t        st_queue __aligned(32);
   60         } st_queues[SLEEPTAB_HASH_SIZE];
   61 } __aligned(64) sleeptab_t;
   62 #else   /* _LP64 */
   63 typedef struct sleeptab {
   64         struct {
   65                 kmutex_t        st_mutex;
   66                 sleepq_t        st_queue;
   67         } st_queues[SLEEPTAB_HASH_SIZE];
   68 } __aligned(32) sleeptab_t;
   69 #endif  /* _LP64 */
   70 
   71 void    sleepq_init(sleepq_t *);
   72 int     sleepq_remove(sleepq_t *, lwp_t *);
   73 void    sleepq_enqueue(sleepq_t *, wchan_t, const char *, syncobj_t *);
   74 u_int   sleepq_unsleep(lwp_t *, bool);
   75 void    sleepq_timeout(void *);
   76 lwp_t   *sleepq_wake(sleepq_t *, wchan_t, u_int, kmutex_t *);
   77 int     sleepq_abort(kmutex_t *, int);
   78 void    sleepq_changepri(lwp_t *, pri_t);
   79 void    sleepq_lendpri(lwp_t *, pri_t);
   80 int     sleepq_block(int, bool);
   81 void    sleepq_insert(sleepq_t *, lwp_t *, syncobj_t *);
   82 
   83 void    sleeptab_init(sleeptab_t *);
   84 
   85 extern sleeptab_t       sleeptab;
   86 
   87 /*
   88  * Return non-zero if it is unsafe to sleep.
   89  *
   90  * XXX This only exists because panic() is broken.
   91  */
   92 static inline bool
   93 sleepq_dontsleep(lwp_t *l)
   94 {
   95         extern int cold;
   96 
   97         return cold || (doing_shutdown && (panicstr || CURCPU_IDLE_P()));
   98 }
   99 
  100 /*
  101  * Find the correct sleep queue for the the specified wait channel.  This
  102  * acquires and holds the per-queue interlock.
  103  */
  104 static inline sleepq_t *
  105 sleeptab_lookup(sleeptab_t *st, wchan_t wchan, kmutex_t **mp)
  106 {
  107         sleepq_t *sq;
  108 
  109         sq = &st->st_queues[SLEEPTAB_HASH(wchan)].st_queue;
  110         *mp = &st->st_queues[SLEEPTAB_HASH(wchan)].st_mutex;
  111         mutex_spin_enter(*mp);
  112         return sq;
  113 }
  114 
  115 static inline kmutex_t *
  116 sleepq_hashlock(wchan_t wchan)
  117 {
  118         kmutex_t *mp;
  119 
  120         mp = &sleeptab.st_queues[SLEEPTAB_HASH(wchan)].st_mutex;
  121         mutex_spin_enter(mp);
  122         return mp;
  123 }
  124 
  125 /*
  126  * Prepare to block on a sleep queue, after which any interlock can be
  127  * safely released.
  128  */
  129 static inline void
  130 sleepq_enter(sleepq_t *sq, lwp_t *l, kmutex_t *mp)
  131 {
  132         kmutex_t *omp;
  133 
  134         /*
  135          * Acquire the per-LWP mutex and lend it ours (the sleep queue
  136          * lock).  Once that's done we're interlocked, and so can release
  137          * the kernel lock.
  138          */
  139         omp = l->l_mutex;
  140         mutex_spin_enter(omp);
  141         if (__predict_false(l->l_mutex != omp)) {
  142                 omp = lwp_lock_retry(l, omp);
  143         }
  144         l->l_mutex = mp;
  145         mutex_spin_exit(omp);
  146         KERNEL_UNLOCK_ALL(NULL, &l->l_biglocks);
  147 }
  148 
  149 /*
  150  * Turnstiles, specialized sleep queues for use by kernel locks.
  151  */
  152 
  153 typedef struct turnstile {
  154         LIST_ENTRY(turnstile)   ts_chain;       /* link on hash chain */
  155         struct turnstile        *ts_free;       /* turnstile free list */
  156         wchan_t                 ts_obj;         /* lock object */
  157         sleepq_t                ts_sleepq[2];   /* sleep queues */
  158         u_int                   ts_waiters[2];  /* count of waiters */
  159 
  160         /* priority inheritance */
  161         pri_t                   ts_eprio;
  162         lwp_t                   *ts_inheritor;
  163         SLIST_ENTRY(turnstile)  ts_pichain;
  164 } turnstile_t;
  165 
  166 typedef struct tschain {
  167         kmutex_t                tc_mutex;       /* mutex on structs & queues */
  168         LIST_HEAD(, turnstile)  tc_chain;       /* turnstile chain */
  169 } __aligned(32) tschain_t;
  170 
  171 #define TS_READER_Q     0               /* reader sleep queue */
  172 #define TS_WRITER_Q     1               /* writer sleep queue */
  173 
  174 #define TS_WAITERS(ts, q)                                               \
  175         (ts)->ts_waiters[(q)]
  176 
  177 #define TS_ALL_WAITERS(ts)                                              \
  178         ((ts)->ts_waiters[TS_READER_Q] +                                \
  179          (ts)->ts_waiters[TS_WRITER_Q])
  180 
  181 #define TS_FIRST(ts, q) (TAILQ_FIRST(&(ts)->ts_sleepq[(q)]))
  182 
  183 #ifdef  _KERNEL
  184 
  185 void    turnstile_init(void);
  186 turnstile_t     *turnstile_lookup(wchan_t);
  187 void    turnstile_exit(wchan_t);
  188 void    turnstile_block(turnstile_t *, int, wchan_t, syncobj_t *);
  189 void    turnstile_wakeup(turnstile_t *, int, int, lwp_t *);
  190 void    turnstile_print(volatile void *, void (*)(const char *, ...));
  191 u_int   turnstile_unsleep(lwp_t *, bool);
  192 void    turnstile_changepri(lwp_t *, pri_t);
  193 
  194 extern pool_cache_t turnstile_cache;
  195 extern turnstile_t turnstile0;
  196 
  197 #endif  /* _KERNEL */
  198 
  199 #endif  /* _SYS_SLEEPQ_H_ */

Cache object: 4c333480a9a5c696a1e41734c3d58c28


[ 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.