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/kern/kern_refcount.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) 2011 The DragonFly Project.  All rights reserved.
    3  *
    4  * This code is derived from software contributed to The DragonFly Project
    5  * by Matthew Dillon <dillon@backplane.com>
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  *
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in
   15  *    the documentation and/or other materials provided with the
   16  *    distribution.
   17  * 3. Neither the name of The DragonFly Project nor the names of its
   18  *    contributors may be used to endorse or promote products derived
   19  *    from this software without specific, prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
   25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
   27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  */
   34 /*
   35  * Implement helper routines for the refcount inlines in sys/refcount.h.
   36  *
   37  * These helpers implement the refcount_release_wakeup() and refcount_wait()
   38  * APIs for the non-trivial or race case.  The trivial non-race case is
   39  * handled by the inline in sys/refcount.h
   40  */
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/sysctl.h>
   46 #include <sys/thread.h>
   47 #include <sys/refcount.h>
   48 
   49 #include <machine/cpufunc.h>
   50 
   51 #include <sys/thread2.h>
   52 
   53 /*
   54  * Helper function to wait for a reference count to become zero.
   55  * We set REFCNTF_WAITING and sleep if the reference count is not zero.
   56  *
   57  * In the case where REFCNTF_WAITING is already set the atomic op validates
   58  * that it is still set after the tsleep_interlock() call.
   59  *
   60  * Users of this waiting API must use refcount_release_wakeup() to release
   61  * refs instead of refcount_release().  refcount_release() will not wake
   62  * up waiters.
   63  */
   64 void
   65 _refcount_wait(volatile u_int *countp, const char *wstr)
   66 {
   67         u_int n;
   68         int base_ticks = ticks;
   69 
   70         for (;;) {
   71                 n = *countp;
   72                 cpu_ccfence();
   73                 if (n == 0)
   74                         break;
   75                 if ((int)(ticks - base_ticks) >= hz*60 - 1) {
   76                         kprintf("warning: refcount_wait %s: long wait\n",
   77                                 wstr);
   78                         base_ticks = ticks;
   79                 }
   80                 KKASSERT(n != REFCNTF_WAITING); /* impossible state */
   81                 tsleep_interlock(countp, 0);
   82                 if (atomic_cmpset_int(countp, n, n | REFCNTF_WAITING))
   83                         tsleep(countp, PINTERLOCKED, wstr, hz*10);
   84         }
   85 }
   86 
   87 /*
   88  * This helper function implements the release-with-wakeup API.  It is
   89  * executed for the non-trivial case or if the atomic op races.
   90  *
   91  * On the i->0 transition is REFCNTF_WAITING is set it will be cleared
   92  * and a wakeup() will be issued.
   93  *
   94  * On any other transition we simply subtract (i) and leave the
   95  * REFCNTF_WAITING flag intact.
   96  *
   97  * This function returns TRUE(1) on the last release, whether a wakeup
   98  * occured or not, and FALSE(0) otherwise.
   99  *
  100  * NOTE!  (i) cannot be 0
  101  */
  102 int
  103 _refcount_release_wakeup_n(volatile u_int *countp, u_int i)
  104 {
  105         u_int n;
  106 
  107         for (;;) {
  108                 n = *countp;
  109                 cpu_ccfence();
  110                 if (n == (REFCNTF_WAITING | i)) {
  111                         if (atomic_cmpset_int(countp, n, 0)) {
  112                                 wakeup(countp);
  113                                 n = i;
  114                                 break;
  115                         }
  116                 } else {
  117                         KKASSERT(n != REFCNTF_WAITING); /* illegal state */
  118                         if (atomic_cmpset_int(countp, n, n - i))
  119                                 break;
  120                 }
  121         }
  122         return (n == i);
  123 }

Cache object: 1ccf7b5c2744e84879dd36e54f71c2c6


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