112f43c12SMatthew Dillon /*
212f43c12SMatthew Dillon * Copyright (c) 2011 The DragonFly Project. All rights reserved.
312f43c12SMatthew Dillon *
412f43c12SMatthew Dillon * This code is derived from software contributed to The DragonFly Project
512f43c12SMatthew Dillon * by Matthew Dillon <dillon@backplane.com>
612f43c12SMatthew Dillon *
712f43c12SMatthew Dillon * Redistribution and use in source and binary forms, with or without
812f43c12SMatthew Dillon * modification, are permitted provided that the following conditions
912f43c12SMatthew Dillon * are met:
1012f43c12SMatthew Dillon *
1112f43c12SMatthew Dillon * 1. Redistributions of source code must retain the above copyright
1212f43c12SMatthew Dillon * notice, this list of conditions and the following disclaimer.
1312f43c12SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
1412f43c12SMatthew Dillon * notice, this list of conditions and the following disclaimer in
1512f43c12SMatthew Dillon * the documentation and/or other materials provided with the
1612f43c12SMatthew Dillon * distribution.
1712f43c12SMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its
1812f43c12SMatthew Dillon * contributors may be used to endorse or promote products derived
1912f43c12SMatthew Dillon * from this software without specific, prior written permission.
2012f43c12SMatthew Dillon *
2112f43c12SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2212f43c12SMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2312f43c12SMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2412f43c12SMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2512f43c12SMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2612f43c12SMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
2712f43c12SMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2812f43c12SMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2912f43c12SMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3012f43c12SMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3112f43c12SMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3212f43c12SMatthew Dillon * SUCH DAMAGE.
3312f43c12SMatthew Dillon */
3412f43c12SMatthew Dillon /*
3512f43c12SMatthew Dillon * Implement helper routines for the refcount inlines in sys/refcount.h.
3612f43c12SMatthew Dillon *
3712f43c12SMatthew Dillon * These helpers implement the refcount_release_wakeup() and refcount_wait()
3812f43c12SMatthew Dillon * APIs for the non-trivial or race case. The trivial non-race case is
3912f43c12SMatthew Dillon * handled by the inline in sys/refcount.h
4012f43c12SMatthew Dillon */
4112f43c12SMatthew Dillon
4212f43c12SMatthew Dillon #include <sys/param.h>
4312f43c12SMatthew Dillon #include <sys/systm.h>
4412f43c12SMatthew Dillon #include <sys/kernel.h>
4512f43c12SMatthew Dillon #include <sys/sysctl.h>
4612f43c12SMatthew Dillon #include <sys/thread.h>
4712f43c12SMatthew Dillon #include <sys/refcount.h>
4812f43c12SMatthew Dillon
4912f43c12SMatthew Dillon #include <machine/cpufunc.h>
5012f43c12SMatthew Dillon
5112f43c12SMatthew Dillon /*
52*0486d94aSMatthew Dillon * Interlocked wait against a decrement-to-0 (sans the REFCNTF_WAITING flag).
5312f43c12SMatthew Dillon *
5412f43c12SMatthew Dillon * Users of this waiting API must use refcount_release_wakeup() to release
5512f43c12SMatthew Dillon * refs instead of refcount_release(). refcount_release() will not wake
5612f43c12SMatthew Dillon * up waiters.
5712f43c12SMatthew Dillon */
5812f43c12SMatthew Dillon void
_refcount_wait(volatile u_int * countp,const char * wstr)59ed2fb120SVenkatesh Srinivas _refcount_wait(volatile u_int *countp, const char *wstr)
6012f43c12SMatthew Dillon {
6112f43c12SMatthew Dillon u_int n;
62761f8226SMatthew Dillon int base_ticks = ticks;
6312f43c12SMatthew Dillon
6412f43c12SMatthew Dillon n = *countp;
65*0486d94aSMatthew Dillon for (;;) {
66d69db72bSMatthew Dillon cpu_ccfence();
67*0486d94aSMatthew Dillon if ((n & ~REFCNTF_WAITING) == 0)
6812f43c12SMatthew Dillon break;
69761f8226SMatthew Dillon if ((int)(ticks - base_ticks) >= hz*60 - 1) {
70*0486d94aSMatthew Dillon kprintf("warning: refcount_wait %s: long wait\n", wstr);
71761f8226SMatthew Dillon base_ticks = ticks;
72ed2fb120SVenkatesh Srinivas }
7312f43c12SMatthew Dillon tsleep_interlock(countp, 0);
74*0486d94aSMatthew Dillon if (atomic_fcmpset_int(countp, &n, n | REFCNTF_WAITING))
75ed2fb120SVenkatesh Srinivas tsleep(countp, PINTERLOCKED, wstr, hz*10);
7612f43c12SMatthew Dillon }
7712f43c12SMatthew Dillon }
78