This commit was manufactured by cvs2svn to create branch 'RELENG_6'.
This commit is contained in:
parent
bd43b633df
commit
c37f50f631
44
etc/rc.d/statd
Normal file
44
etc/rc.d/statd
Normal file
@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# $NetBSD: nfslocking,v 1.6 2002/03/24 15:52:41 lukem Exp $
|
||||
# FreeBSD History: src/etc/rc.d/nfslocking,v 1.11 2004/10/07 13:55:26 mtm Exp
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
# PROVIDE: statd
|
||||
# REQUIRE: nfsserver nfsclient nfsd rpcbind
|
||||
# BEFORE: DAEMON
|
||||
# KEYWORD: nojail
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name="statd"
|
||||
rcvar=rpc_statd_enable
|
||||
command="/usr/sbin/rpc.${name}"
|
||||
start_precmd='statd_precmd'
|
||||
stop_precmd='checkyesno nfs_server_enable || checkyesno nfs_client_enable'
|
||||
status_precmd=$stop_precmd
|
||||
|
||||
# Make sure that we are either an NFS client or server, and that we get
|
||||
# the correct flags from rc.conf(5).
|
||||
#
|
||||
statd_precmd()
|
||||
{
|
||||
local ret
|
||||
ret=0
|
||||
|
||||
if ! checkyesno nfs_server_enable && ! checkyesno nfs_client_enable
|
||||
then
|
||||
ret=1
|
||||
fi
|
||||
if ! checkyesno rpcbind_enable && \
|
||||
! /etc/rc.d/rpcbind forcestatus 1>/dev/null 2>&1
|
||||
then
|
||||
force_depend rpcbind || ret=1
|
||||
fi
|
||||
rc_flags=${rpc_statd_flags}
|
||||
return ${ret}
|
||||
}
|
||||
|
||||
load_rc_config $name
|
||||
run_rc_command $1
|
101
lib/libutil/flopen.3
Normal file
101
lib/libutil/flopen.3
Normal file
@ -0,0 +1,101 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 2007 Dag-Erling Coïdan Smørgrav
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 10, 2007
|
||||
.Dt FLOPEN 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm flopen
|
||||
.Nd "Reliably open and lock a file"
|
||||
.Sh LIBRARY
|
||||
.Lb libutil
|
||||
.Sh SYNOPSIS
|
||||
.In sys/fcntl.h
|
||||
.In libutil.h
|
||||
.Ft int
|
||||
.Fn flopen "const char *path" "int flags"
|
||||
.Ft int
|
||||
.Fn flopen "const char *path" "int flags" "mode_t mode"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn flopen
|
||||
function opens or creates a file and acquires an exclusive lock on it.
|
||||
It is essentially equivalent with calling
|
||||
.Fn open
|
||||
with the same parameters followed by
|
||||
.Fn flock
|
||||
with an
|
||||
.Va operation
|
||||
argument of
|
||||
.Dv LOCK_EX ,
|
||||
except that
|
||||
.Fn flopen
|
||||
will attempt to detect and handle races that may occur between opening
|
||||
/ creating the file and locking it.
|
||||
Thus, it is well suited for opening lock files, PID files, spool
|
||||
files, mailboxes and other kinds of files which are used for
|
||||
synchronization between processes.
|
||||
.Pp
|
||||
If
|
||||
.Va flags
|
||||
includes
|
||||
.Dv O_NONBLOCK
|
||||
and the file is already locked,
|
||||
.Fn flopen
|
||||
will fail and set
|
||||
.Va errno
|
||||
to
|
||||
.Dv EWOULDBLOCK .
|
||||
.Pp
|
||||
As with
|
||||
.Fn open ,
|
||||
the additional
|
||||
.Va mode
|
||||
argument is required if
|
||||
.Va flags
|
||||
includes
|
||||
.Dv O_CREAT .
|
||||
.Sh RETURN VALUES
|
||||
If successful,
|
||||
.Fn flopen
|
||||
returns a valid file descriptor.
|
||||
Otherwise, it returns -1, and sets
|
||||
.Va errno
|
||||
as described in
|
||||
.Xr flock 2
|
||||
and
|
||||
.Xr open 2 .
|
||||
.Sh SEE ALSO
|
||||
.Xr errno 2 ,
|
||||
.Xr flock 2 ,
|
||||
.Xr open 2
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The
|
||||
.Nm
|
||||
function and this manual page were written by
|
||||
.An Dag-Erling Sm\(/orgrav Aq des@FreeBSD.org .
|
106
lib/libutil/flopen.c
Normal file
106
lib/libutil/flopen.c
Normal file
@ -0,0 +1,106 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Dag-Erling Coïdan Smørgrav
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer
|
||||
* in this position and unchanged.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libutil.h>
|
||||
|
||||
int
|
||||
flopen(const char *path, int flags, ...)
|
||||
{
|
||||
int fd, operation, serrno, trunc;
|
||||
struct stat sb, fsb;
|
||||
mode_t mode;
|
||||
|
||||
#ifdef O_EXLOCK
|
||||
flags &= ~O_EXLOCK;
|
||||
#endif
|
||||
|
||||
mode = 0;
|
||||
if (flags & O_CREAT) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, flags);
|
||||
mode = va_arg(ap, int); /* mode_t promoted to int */
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
operation = LOCK_EX;
|
||||
if (flags & O_NONBLOCK)
|
||||
operation |= LOCK_NB;
|
||||
|
||||
trunc = (flags & O_TRUNC);
|
||||
flags &= ~O_TRUNC;
|
||||
|
||||
for (;;) {
|
||||
if ((fd = open(path, flags, mode)) == -1)
|
||||
/* non-existent or no access */
|
||||
return (-1);
|
||||
if (flock(fd, operation) == -1) {
|
||||
/* unsupported or interrupted */
|
||||
serrno = errno;
|
||||
close(fd);
|
||||
errno = serrno;
|
||||
return (-1);
|
||||
}
|
||||
if (stat(path, &sb) == -1) {
|
||||
/* disappeared from under our feet */
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
if (fstat(fd, &fsb) == -1) {
|
||||
/* can't happen [tm] */
|
||||
serrno = errno;
|
||||
close(fd);
|
||||
errno = serrno;
|
||||
return (-1);
|
||||
}
|
||||
if (sb.st_dev != fsb.st_dev ||
|
||||
sb.st_ino != fsb.st_ino) {
|
||||
/* changed under our feet */
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
if (trunc && ftruncate(fd, 0) != 0) {
|
||||
/* can't happen [tm] */
|
||||
serrno = errno;
|
||||
close(fd);
|
||||
errno = serrno;
|
||||
return (-1);
|
||||
}
|
||||
return (fd);
|
||||
}
|
||||
}
|
103
share/man/man5/boot.config.5
Normal file
103
share/man/man5/boot.config.5
Normal file
@ -0,0 +1,103 @@
|
||||
.\" Copyright (c) 2007 Daniel Gerzo <danger@FreeBSD.org>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.Dd May 13, 2007
|
||||
.Dt BOOT.CONFIG 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm boot.config
|
||||
.Nd "Configuration file for the boot blocks"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
file contains options for the
|
||||
.Fx
|
||||
boot block code.
|
||||
.Pp
|
||||
When the
|
||||
.Fx
|
||||
boot loader runs, it searches the
|
||||
.Dq Li a
|
||||
slice of the boot partition for a
|
||||
.Nm
|
||||
file (as a result, slices which are missing an
|
||||
.Dq Li a
|
||||
partition require user intervention during the boot process).
|
||||
If the
|
||||
.Nm
|
||||
file is found, its contents are used as the default configuration
|
||||
options for the boot block code and are echoed to the system console.
|
||||
.Pp
|
||||
A valid format of this file is to put BIOS drive number, a controller
|
||||
type, a unit number, a partition, a kernel file name, and any other
|
||||
valid
|
||||
.Xr boot 8
|
||||
option on a single line, as it is done at the
|
||||
.Dq Li "boot:"
|
||||
prompt.
|
||||
.Pp
|
||||
The options related to the boot image selection described below and all
|
||||
the other options available for
|
||||
.Nm
|
||||
are documented in detail in the
|
||||
.Xr boot 8
|
||||
manual page.
|
||||
.Sh EXAMPLES
|
||||
The command:
|
||||
.Bd -literal -offset indent
|
||||
# echo "-P" > /boot.config
|
||||
.Ed
|
||||
.Pp
|
||||
will activate the serial console of
|
||||
.Fx .
|
||||
.Pp
|
||||
The command:
|
||||
.Bd -literal -offset indent
|
||||
# echo "1:ad(1,a)/boot/loader" > /boot.config
|
||||
.Ed
|
||||
.Pp
|
||||
will instruct the second boot stage of
|
||||
.Xr loader 8
|
||||
on the first disk to boot with the third boot stage of
|
||||
.Xr loader 8
|
||||
from the second disk.
|
||||
.Pp
|
||||
The command:
|
||||
.Bd -literal -offset indent
|
||||
# echo "1:ad(1,a)/boot/loader -P" > /boot.config
|
||||
.Ed
|
||||
.Pp
|
||||
will do both of the above.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /boot.config -compact
|
||||
.It Pa /boot.config
|
||||
parameters for the boot blocks (optional)
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr boot 8 ,
|
||||
.Xr loader 8
|
||||
.Sh AUTHORS
|
||||
This manual page was written by
|
||||
.An Daniel Gerzo Aq danger@FreeBSD.org .
|
46
sys/dev/cxgb/t3b_protocol_sram-1.1.0.bin.gz.uu
Normal file
46
sys/dev/cxgb/t3b_protocol_sram-1.1.0.bin.gz.uu
Normal file
@ -0,0 +1,46 @@
|
||||
/**************************************************************************
|
||||
|
||||
Copyright (c) 2007, Chelsio Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Neither the name of the Chelsio Corporation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
$FreeBSD$
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
begin 644 t3b_protocol_sram-1.1.0.bin.gz
|
||||
M'XL(".):ED8``W0S8E]P<F]T;V-O;%]S<F%M+3$N,2XP+F)I;@#EECU+PT`8
|
||||
MQY]<VAA*D?@R:%4(%$L4!X,5<2NZ.91^A([2*?@%3%L<%(6`XN"NLQ_A?"O%
|
||||
MJ3B(DX-"$:>S=K!5J,]=J20Q@U#:#AXD>>[/O?SRSSUW:;5:7]`NLKA+$K3\
|
||||
M&I9_J'U6DG+53LRON[0/L$1(\,J70@/G>[*-N;B;3P&R(MU0&#L*Y4MA2V@%
|
||||
M(,J*K`:-1W0;\@?UGO`UKDT,C(6B2V-IB\P`\F&1+B8&ZM\;!?R^AA$/:$?0
|
||||
M/R2T!LG7U)+`(=P:RP(HNJP27(;,GCUQ>N%+V21*!,@:5O-V6VN43;D4.9YW
|
||||
M:RQD<KZ0AT\_%R'W3[J8]/C'BP2@=<O'\('SIF`SJO/QN`<-:EY5(9%+N>9H
|
||||
M:G6!XLG?;$85L175._XQ171*!?$18U^S=VC7S('OD?ZMX9HDCZ#$.$S!6:9]
|
||||
MRX5;\^HR<ISS>)7.C*].WU"_][WV)4A[OUV*WP_[^'`9*'K%^WVATJE!T3'[
|
||||
MYA_R/?OY&&1B&BSZ^'`OQOSEQTC#&=GK1?[^>7^FF:DSN//PL120(4P!OK^\
|
||||
M.,F-0?)A_A(5J)>O$V_MEQ\.=T7NLX(C.O:;CP5H-:SJD!CU>RIK6O_/MX#_
|
||||
6EYJ:)(M`PS_MK-?3[6^9;',3!`H`````
|
||||
`
|
||||
end
|
46
sys/dev/cxgb/t3b_tp_eeprom-1.1.0.bin.gz.uu
Normal file
46
sys/dev/cxgb/t3b_tp_eeprom-1.1.0.bin.gz.uu
Normal file
@ -0,0 +1,46 @@
|
||||
/**************************************************************************
|
||||
|
||||
Copyright (c) 2007, Chelsio Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Neither the name of the Chelsio Corporation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
$FreeBSD$
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
begin 644 t3b_tp_eeprom-1.1.0.bin.gz
|
||||
M'XL(".):ED8``W0S8E]T<%]E97!R;VTM,2XQ+C`N8FEN`-V5,4O#0!3'_[FK
|
||||
M[;5634&PZ(&I%8VBT(J@A5J#=7`JW43H$!W$T8\0+8@.@DXBN+4(^0#N410<
|
||||
M'(I?0'%0W%W<O*MI(@41(77P$=Z1X\][O[R\=P=%@32*3XN[:\9='7?])X+B
|
||||
MY)CU3&<;W3!,S@#M<SMB_2%#>D*WGIH,JR9?,7(**GP[#=-G8'0N3+#+8#PD
|
||||
M&=A(\`S5*5WX['445H(W=RKQ1@HOH>!2_%P'71?_`HZ"`<`P<JG@4_PL$-T?
|
||||
MPJP:L]<(ZP/&K0PVQ'XXD!36CG!+!+$PR=[*.4O*EJMOV&9>K9YY$4*2(2O\
|
||||
M28+[=>@F4`$%OOV>X4A&T.);,&0*:8H,"M0WB5G@U&,H$NG?W#I<(2)?+73M
|
||||
M>0Q&<Q%U42J,7>YWH"==04GT(IU@$G(=C],`#SR%+ZAOVEJ>U_P4S@W/]9=+
|
||||
MK.TS\6V$(!A>S8696KXE*)*&%A9_BX'3'/,R]UB=9BA\9<A`'2P#=E(Y[9,'
|
||||
MI)@+3;9$YQC:!45RC_.ALA.UE^E!KYA-T7O;6JN1_XK!`2-B+J+'\P>'=WH$
|
||||
M;4:;S]$NOHL0'*278G2=8,:[NZ1`52F1,]XQAM:]V3J.,F6A31M5;?C]8O$#
|
||||
(X@X'9$0(````
|
||||
`
|
||||
end
|
442
sys/dev/cxgb/t3fw-4.5.0.bin.gz.uu
Normal file
442
sys/dev/cxgb/t3fw-4.5.0.bin.gz.uu
Normal file
@ -0,0 +1,442 @@
|
||||
/**************************************************************************
|
||||
|
||||
Copyright (c) 2007, Chelsio Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Neither the name of the Chelsio Corporation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
$FreeBSD$
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
begin 644 t3fw-4.5.0.bin.gz
|
||||
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
|
||||
M#!2BHUCHFEP:@3HE`RW$>-%>JP#,S8T0L#CJMBS5=IP_'KQJ%J]_5&Q6
|
||||
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
|
||||
*%P!M0DW?O%L`````
|
||||
`
|
||||
end
|
47
sys/dev/mxge/mxge_eth_z8e.c
Normal file
47
sys/dev/mxge/mxge_eth_z8e.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* from: FreeBSD: src/sys/tools/fw_stub.awk,v 1.6 2007/03/02 11:42:53 flz
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/firmware.h>
|
||||
#include <sys/systm.h>
|
||||
#include <dev/mxge/eth_z8e.h>
|
||||
|
||||
static int
|
||||
mxge_eth_z8e_fw_modevent(module_t mod, int type, void *unused)
|
||||
{
|
||||
const struct firmware *fp, *parent;
|
||||
int error;
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
|
||||
fp = firmware_register("mxge_eth_z8e", eth_z8e,
|
||||
(size_t)eth_z8e_length,
|
||||
eth_z8e_uncompressed_length, NULL);
|
||||
if (fp == NULL)
|
||||
goto fail_0;
|
||||
parent = fp;
|
||||
return (0);
|
||||
fail_0:
|
||||
return (ENXIO);
|
||||
case MOD_UNLOAD:
|
||||
error = firmware_unregister("mxge_eth_z8e");
|
||||
return (error);
|
||||
}
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static moduledata_t mxge_eth_z8e_fw_mod = {
|
||||
"mxge_eth_z8e_fw",
|
||||
mxge_eth_z8e_fw_modevent,
|
||||
0
|
||||
};
|
||||
DECLARE_MODULE(mxge_eth_z8e_fw, mxge_eth_z8e_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
|
||||
MODULE_VERSION(mxge_eth_z8e_fw, 1);
|
||||
MODULE_DEPEND(mxge_eth_z8e_fw, firmware, 1, 1, 1);
|
||||
|
47
sys/dev/mxge/mxge_ethp_z8e.c
Normal file
47
sys/dev/mxge/mxge_ethp_z8e.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* from: FreeBSD: src/sys/tools/fw_stub.awk,v 1.6 2007/03/02 11:42:53 flz
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/firmware.h>
|
||||
#include <sys/systm.h>
|
||||
#include <dev/mxge/ethp_z8e.h>
|
||||
|
||||
static int
|
||||
mxge_ethp_z8e_fw_modevent(module_t mod, int type, void *unused)
|
||||
{
|
||||
const struct firmware *fp, *parent;
|
||||
int error;
|
||||
switch (type) {
|
||||
case MOD_LOAD:
|
||||
|
||||
fp = firmware_register("mxge_ethp_z8e", ethp_z8e,
|
||||
(size_t)ethp_z8e_length,
|
||||
ethp_z8e_uncompressed_length, NULL);
|
||||
if (fp == NULL)
|
||||
goto fail_0;
|
||||
parent = fp;
|
||||
return (0);
|
||||
fail_0:
|
||||
return (ENXIO);
|
||||
case MOD_UNLOAD:
|
||||
error = firmware_unregister("mxge_ethp_z8e");
|
||||
return (error);
|
||||
}
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
static moduledata_t mxge_ethp_z8e_fw_mod = {
|
||||
"mxge_ethp_z8e_fw",
|
||||
mxge_ethp_z8e_fw_modevent,
|
||||
0
|
||||
};
|
||||
DECLARE_MODULE(mxge_ethp_z8e_fw, mxge_ethp_z8e_fw_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);
|
||||
MODULE_VERSION(mxge_ethp_z8e_fw, 1);
|
||||
MODULE_DEPEND(mxge_ethp_z8e_fw, firmware, 1, 1, 1);
|
||||
|
991
sys/kern/kern_rwlock.c
Normal file
991
sys/kern/kern_rwlock.c
Normal file
@ -0,0 +1,991 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 John Baldwin <jhb@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Machine independent bits of reader/writer lock implementation.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_no_adaptive_rwlocks.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/ktr.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/rwlock.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/turnstile.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
|
||||
CTASSERT((RW_RECURSE & LO_CLASSFLAGS) == RW_RECURSE);
|
||||
|
||||
#if defined(SMP) && !defined(NO_ADAPTIVE_RWLOCKS)
|
||||
#define ADAPTIVE_RWLOCKS
|
||||
#endif
|
||||
|
||||
#ifdef DDB
|
||||
#include <ddb/ddb.h>
|
||||
|
||||
static void db_show_rwlock(struct lock_object *lock);
|
||||
#endif
|
||||
static void lock_rw(struct lock_object *lock, int how);
|
||||
static int unlock_rw(struct lock_object *lock);
|
||||
|
||||
struct lock_class lock_class_rw = {
|
||||
.lc_name = "rw",
|
||||
.lc_flags = LC_SLEEPLOCK | LC_RECURSABLE | LC_UPGRADABLE,
|
||||
#ifdef DDB
|
||||
.lc_ddb_show = db_show_rwlock,
|
||||
#endif
|
||||
.lc_lock = lock_rw,
|
||||
.lc_unlock = unlock_rw,
|
||||
};
|
||||
|
||||
/*
|
||||
* Return a pointer to the owning thread if the lock is write-locked or
|
||||
* NULL if the lock is unlocked or read-locked.
|
||||
*/
|
||||
#define rw_wowner(rw) \
|
||||
((rw)->rw_lock & RW_LOCK_READ ? NULL : \
|
||||
(struct thread *)RW_OWNER((rw)->rw_lock))
|
||||
|
||||
/*
|
||||
* Returns if a write owner is recursed. Write ownership is not assured
|
||||
* here and should be previously checked.
|
||||
*/
|
||||
#define rw_recursed(rw) ((rw)->rw_recurse != 0)
|
||||
|
||||
/*
|
||||
* Return true if curthread helds the lock.
|
||||
*/
|
||||
#define rw_wlocked(rw) (rw_wowner((rw)) == curthread)
|
||||
|
||||
/*
|
||||
* Return a pointer to the owning thread for this lock who should receive
|
||||
* any priority lent by threads that block on this lock. Currently this
|
||||
* is identical to rw_wowner().
|
||||
*/
|
||||
#define rw_owner(rw) rw_wowner(rw)
|
||||
|
||||
#ifndef INVARIANTS
|
||||
#define _rw_assert(rw, what, file, line)
|
||||
#endif
|
||||
|
||||
void
|
||||
lock_rw(struct lock_object *lock, int how)
|
||||
{
|
||||
struct rwlock *rw;
|
||||
|
||||
rw = (struct rwlock *)lock;
|
||||
if (how)
|
||||
rw_wlock(rw);
|
||||
else
|
||||
rw_rlock(rw);
|
||||
}
|
||||
|
||||
int
|
||||
unlock_rw(struct lock_object *lock)
|
||||
{
|
||||
struct rwlock *rw;
|
||||
|
||||
rw = (struct rwlock *)lock;
|
||||
rw_assert(rw, RA_LOCKED | LA_NOTRECURSED);
|
||||
if (rw->rw_lock & RW_LOCK_READ) {
|
||||
rw_runlock(rw);
|
||||
return (0);
|
||||
} else {
|
||||
rw_wunlock(rw);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rw_init_flags(struct rwlock *rw, const char *name, int opts)
|
||||
{
|
||||
int flags;
|
||||
|
||||
MPASS((opts & ~(RW_DUPOK | RW_NOPROFILE | RW_NOWITNESS | RW_QUIET |
|
||||
RW_RECURSE)) == 0);
|
||||
|
||||
flags = LO_UPGRADABLE | LO_RECURSABLE;
|
||||
if (opts & RW_DUPOK)
|
||||
flags |= LO_DUPOK;
|
||||
if (opts & RW_NOPROFILE)
|
||||
flags |= LO_NOPROFILE;
|
||||
if (!(opts & RW_NOWITNESS))
|
||||
flags |= LO_WITNESS;
|
||||
if (opts & RW_QUIET)
|
||||
flags |= LO_QUIET;
|
||||
flags |= opts & RW_RECURSE;
|
||||
|
||||
rw->rw_lock = RW_UNLOCKED;
|
||||
rw->rw_recurse = 0;
|
||||
lock_init(&rw->lock_object, &lock_class_rw, name, NULL, flags);
|
||||
}
|
||||
|
||||
void
|
||||
rw_destroy(struct rwlock *rw)
|
||||
{
|
||||
|
||||
KASSERT(rw->rw_lock == RW_UNLOCKED, ("rw lock not unlocked"));
|
||||
KASSERT(rw->rw_recurse == 0, ("rw lock still recursed"));
|
||||
rw->rw_lock = RW_DESTROYED;
|
||||
lock_destroy(&rw->lock_object);
|
||||
}
|
||||
|
||||
void
|
||||
rw_sysinit(void *arg)
|
||||
{
|
||||
struct rw_args *args = arg;
|
||||
|
||||
rw_init(args->ra_rw, args->ra_desc);
|
||||
}
|
||||
|
||||
int
|
||||
rw_wowned(struct rwlock *rw)
|
||||
{
|
||||
|
||||
return (rw_wowner(rw) == curthread);
|
||||
}
|
||||
|
||||
void
|
||||
_rw_wlock(struct rwlock *rw, const char *file, int line)
|
||||
{
|
||||
|
||||
MPASS(curthread != NULL);
|
||||
KASSERT(rw->rw_lock != RW_DESTROYED,
|
||||
("rw_wlock() of destroyed rwlock @ %s:%d", file, line));
|
||||
KASSERT(rw_wowner(rw) != curthread,
|
||||
("%s (%s): wlock already held @ %s:%d", __func__,
|
||||
rw->lock_object.lo_name, file, line));
|
||||
WITNESS_CHECKORDER(&rw->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, file,
|
||||
line);
|
||||
__rw_wlock(rw, curthread, file, line);
|
||||
LOCK_LOG_LOCK("WLOCK", &rw->lock_object, 0, rw->rw_recurse, file, line);
|
||||
WITNESS_LOCK(&rw->lock_object, LOP_EXCLUSIVE, file, line);
|
||||
curthread->td_locks++;
|
||||
}
|
||||
|
||||
void
|
||||
_rw_wunlock(struct rwlock *rw, const char *file, int line)
|
||||
{
|
||||
|
||||
MPASS(curthread != NULL);
|
||||
KASSERT(rw->rw_lock != RW_DESTROYED,
|
||||
("rw_wunlock() of destroyed rwlock @ %s:%d", file, line));
|
||||
_rw_assert(rw, RA_WLOCKED, file, line);
|
||||
curthread->td_locks--;
|
||||
WITNESS_UNLOCK(&rw->lock_object, LOP_EXCLUSIVE, file, line);
|
||||
LOCK_LOG_LOCK("WUNLOCK", &rw->lock_object, 0, rw->rw_recurse, file,
|
||||
line);
|
||||
if (!rw_recursed(rw))
|
||||
lock_profile_release_lock(&rw->lock_object);
|
||||
__rw_wunlock(rw, curthread, file, line);
|
||||
}
|
||||
|
||||
void
|
||||
_rw_rlock(struct rwlock *rw, const char *file, int line)
|
||||
{
|
||||
struct turnstile *ts;
|
||||
#ifdef ADAPTIVE_RWLOCKS
|
||||
volatile struct thread *owner;
|
||||
#endif
|
||||
#ifdef LOCK_PROFILING_SHARED
|
||||
uint64_t waittime = 0;
|
||||
int contested = 0;
|
||||
#endif
|
||||
uintptr_t x;
|
||||
|
||||
KASSERT(rw->rw_lock != RW_DESTROYED,
|
||||
("rw_rlock() of destroyed rwlock @ %s:%d", file, line));
|
||||
KASSERT(rw_wowner(rw) != curthread,
|
||||
("%s (%s): wlock already held @ %s:%d", __func__,
|
||||
rw->lock_object.lo_name, file, line));
|
||||
WITNESS_CHECKORDER(&rw->lock_object, LOP_NEWORDER, file, line);
|
||||
|
||||
/*
|
||||
* Note that we don't make any attempt to try to block read
|
||||
* locks once a writer has blocked on the lock. The reason is
|
||||
* that we currently allow for read locks to recurse and we
|
||||
* don't keep track of all the holders of read locks. Thus, if
|
||||
* we were to block readers once a writer blocked and a reader
|
||||
* tried to recurse on their reader lock after a writer had
|
||||
* blocked we would end up in a deadlock since the reader would
|
||||
* be blocked on the writer, and the writer would be blocked
|
||||
* waiting for the reader to release its original read lock.
|
||||
*/
|
||||
for (;;) {
|
||||
/*
|
||||
* Handle the easy case. If no other thread has a write
|
||||
* lock, then try to bump up the count of read locks. Note
|
||||
* that we have to preserve the current state of the
|
||||
* RW_LOCK_WRITE_WAITERS flag. If we fail to acquire a
|
||||
* read lock, then rw_lock must have changed, so restart
|
||||
* the loop. Note that this handles the case of a
|
||||
* completely unlocked rwlock since such a lock is encoded
|
||||
* as a read lock with no waiters.
|
||||
*/
|
||||
x = rw->rw_lock;
|
||||
if (x & RW_LOCK_READ) {
|
||||
|
||||
/*
|
||||
* The RW_LOCK_READ_WAITERS flag should only be set
|
||||
* if another thread currently holds a write lock,
|
||||
* and in that case RW_LOCK_READ should be clear.
|
||||
*/
|
||||
MPASS((x & RW_LOCK_READ_WAITERS) == 0);
|
||||
if (atomic_cmpset_acq_ptr(&rw->rw_lock, x,
|
||||
x + RW_ONE_READER)) {
|
||||
#ifdef LOCK_PROFILING_SHARED
|
||||
if (RW_READERS(x) == 0)
|
||||
lock_profile_obtain_lock_success(
|
||||
&rw->lock_object, contested,
|
||||
waittime, file, line);
|
||||
#endif
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR4(KTR_LOCK,
|
||||
"%s: %p succeed %p -> %p", __func__,
|
||||
rw, (void *)x,
|
||||
(void *)(x + RW_ONE_READER));
|
||||
break;
|
||||
}
|
||||
cpu_spinwait();
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Okay, now it's the hard case. Some other thread already
|
||||
* has a write lock, so acquire the turnstile lock so we can
|
||||
* begin the process of blocking.
|
||||
*/
|
||||
ts = turnstile_trywait(&rw->lock_object);
|
||||
|
||||
/*
|
||||
* The lock might have been released while we spun, so
|
||||
* recheck its state and restart the loop if there is no
|
||||
* longer a write lock.
|
||||
*/
|
||||
x = rw->rw_lock;
|
||||
if (x & RW_LOCK_READ) {
|
||||
turnstile_cancel(ts);
|
||||
cpu_spinwait();
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ok, it's still a write lock. If the RW_LOCK_READ_WAITERS
|
||||
* flag is already set, then we can go ahead and block. If
|
||||
* it is not set then try to set it. If we fail to set it
|
||||
* drop the turnstile lock and restart the loop.
|
||||
*/
|
||||
if (!(x & RW_LOCK_READ_WAITERS)) {
|
||||
if (!atomic_cmpset_ptr(&rw->rw_lock, x,
|
||||
x | RW_LOCK_READ_WAITERS)) {
|
||||
turnstile_cancel(ts);
|
||||
cpu_spinwait();
|
||||
continue;
|
||||
}
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p set read waiters flag",
|
||||
__func__, rw);
|
||||
}
|
||||
|
||||
#ifdef ADAPTIVE_RWLOCKS
|
||||
/*
|
||||
* If the owner is running on another CPU, spin until
|
||||
* the owner stops running or the state of the lock
|
||||
* changes.
|
||||
*/
|
||||
owner = (struct thread *)RW_OWNER(x);
|
||||
if (TD_IS_RUNNING(owner)) {
|
||||
turnstile_cancel(ts);
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
|
||||
__func__, rw, owner);
|
||||
#ifdef LOCK_PROFILING_SHARED
|
||||
lock_profile_obtain_lock_failed(&rw->lock_object,
|
||||
&contested, &waittime);
|
||||
#endif
|
||||
while ((struct thread*)RW_OWNER(rw->rw_lock)== owner &&
|
||||
TD_IS_RUNNING(owner))
|
||||
cpu_spinwait();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We were unable to acquire the lock and the read waiters
|
||||
* flag is set, so we must block on the turnstile.
|
||||
*/
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p blocking on turnstile", __func__,
|
||||
rw);
|
||||
#ifdef LOCK_PROFILING_SHARED
|
||||
lock_profile_obtain_lock_failed(&rw->lock_object, &contested,
|
||||
&waittime);
|
||||
#endif
|
||||
turnstile_wait(ts, rw_owner(rw), TS_SHARED_QUEUE);
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p resuming from turnstile",
|
||||
__func__, rw);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: acquire "owner of record" here. Here be turnstile dragons
|
||||
* however. turnstiles don't like owners changing between calls to
|
||||
* turnstile_wait() currently.
|
||||
*/
|
||||
|
||||
LOCK_LOG_LOCK("RLOCK", &rw->lock_object, 0, 0, file, line);
|
||||
WITNESS_LOCK(&rw->lock_object, 0, file, line);
|
||||
curthread->td_locks++;
|
||||
}
|
||||
|
||||
void
|
||||
_rw_runlock(struct rwlock *rw, const char *file, int line)
|
||||
{
|
||||
struct turnstile *ts;
|
||||
uintptr_t x;
|
||||
|
||||
KASSERT(rw->rw_lock != RW_DESTROYED,
|
||||
("rw_runlock() of destroyed rwlock @ %s:%d", file, line));
|
||||
_rw_assert(rw, RA_RLOCKED, file, line);
|
||||
curthread->td_locks--;
|
||||
WITNESS_UNLOCK(&rw->lock_object, 0, file, line);
|
||||
LOCK_LOG_LOCK("RUNLOCK", &rw->lock_object, 0, 0, file, line);
|
||||
|
||||
/* TODO: drop "owner of record" here. */
|
||||
|
||||
for (;;) {
|
||||
/*
|
||||
* See if there is more than one read lock held. If so,
|
||||
* just drop one and return.
|
||||
*/
|
||||
x = rw->rw_lock;
|
||||
if (RW_READERS(x) > 1) {
|
||||
if (atomic_cmpset_ptr(&rw->rw_lock, x,
|
||||
x - RW_ONE_READER)) {
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR4(KTR_LOCK,
|
||||
"%s: %p succeeded %p -> %p",
|
||||
__func__, rw, (void *)x,
|
||||
(void *)(x - RW_ONE_READER));
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* We should never have read waiters while at least one
|
||||
* thread holds a read lock. (See note above)
|
||||
*/
|
||||
KASSERT(!(x & RW_LOCK_READ_WAITERS),
|
||||
("%s: waiting readers", __func__));
|
||||
#ifdef LOCK_PROFILING_SHARED
|
||||
lock_profile_release_lock(&rw->lock_object);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If there aren't any waiters for a write lock, then try
|
||||
* to drop it quickly.
|
||||
*/
|
||||
if (!(x & RW_LOCK_WRITE_WAITERS)) {
|
||||
|
||||
/*
|
||||
* There shouldn't be any flags set and we should
|
||||
* be the only read lock. If we fail to release
|
||||
* the single read lock, then another thread might
|
||||
* have just acquired a read lock, so go back up
|
||||
* to the multiple read locks case.
|
||||
*/
|
||||
MPASS(x == RW_READERS_LOCK(1));
|
||||
if (atomic_cmpset_ptr(&rw->rw_lock, RW_READERS_LOCK(1),
|
||||
RW_UNLOCKED)) {
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p last succeeded",
|
||||
__func__, rw);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* There should just be one reader with one or more
|
||||
* writers waiting.
|
||||
*/
|
||||
MPASS(x == (RW_READERS_LOCK(1) | RW_LOCK_WRITE_WAITERS));
|
||||
|
||||
/*
|
||||
* Ok, we know we have a waiting writer and we think we
|
||||
* are the last reader, so grab the turnstile lock.
|
||||
*/
|
||||
turnstile_chain_lock(&rw->lock_object);
|
||||
|
||||
/*
|
||||
* Try to drop our lock leaving the lock in a unlocked
|
||||
* state.
|
||||
*
|
||||
* If you wanted to do explicit lock handoff you'd have to
|
||||
* do it here. You'd also want to use turnstile_signal()
|
||||
* and you'd have to handle the race where a higher
|
||||
* priority thread blocks on the write lock before the
|
||||
* thread you wakeup actually runs and have the new thread
|
||||
* "steal" the lock. For now it's a lot simpler to just
|
||||
* wakeup all of the waiters.
|
||||
*
|
||||
* As above, if we fail, then another thread might have
|
||||
* acquired a read lock, so drop the turnstile lock and
|
||||
* restart.
|
||||
*/
|
||||
if (!atomic_cmpset_ptr(&rw->rw_lock,
|
||||
RW_READERS_LOCK(1) | RW_LOCK_WRITE_WAITERS, RW_UNLOCKED)) {
|
||||
turnstile_chain_unlock(&rw->lock_object);
|
||||
continue;
|
||||
}
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p last succeeded with waiters",
|
||||
__func__, rw);
|
||||
|
||||
/*
|
||||
* Ok. The lock is released and all that's left is to
|
||||
* wake up the waiters. Note that the lock might not be
|
||||
* free anymore, but in that case the writers will just
|
||||
* block again if they run before the new lock holder(s)
|
||||
* release the lock.
|
||||
*/
|
||||
ts = turnstile_lookup(&rw->lock_object);
|
||||
MPASS(ts != NULL);
|
||||
turnstile_broadcast(ts, TS_EXCLUSIVE_QUEUE);
|
||||
turnstile_unpend(ts, TS_SHARED_LOCK);
|
||||
turnstile_chain_unlock(&rw->lock_object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when we are unable to obtain a write lock on the
|
||||
* first try. This means that at least one other thread holds either a
|
||||
* read or write lock.
|
||||
*/
|
||||
void
|
||||
_rw_wlock_hard(struct rwlock *rw, uintptr_t tid, const char *file, int line)
|
||||
{
|
||||
struct turnstile *ts;
|
||||
#ifdef ADAPTIVE_RWLOCKS
|
||||
volatile struct thread *owner;
|
||||
#endif
|
||||
uint64_t waittime = 0;
|
||||
uintptr_t v;
|
||||
int contested = 0;
|
||||
|
||||
if (rw_wlocked(rw)) {
|
||||
KASSERT(rw->lock_object.lo_flags & RW_RECURSE,
|
||||
("%s: recursing but non-recursive rw %s @ %s:%d\n",
|
||||
__func__, rw->lock_object.lo_name, file, line));
|
||||
rw->rw_recurse++;
|
||||
atomic_set_ptr(&rw->rw_lock, RW_LOCK_RECURSED);
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p recursing", __func__, rw);
|
||||
return;
|
||||
}
|
||||
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR5(KTR_LOCK, "%s: %s contested (lock=%p) at %s:%d", __func__,
|
||||
rw->lock_object.lo_name, (void *)rw->rw_lock, file, line);
|
||||
|
||||
while (!_rw_write_lock(rw, tid)) {
|
||||
ts = turnstile_trywait(&rw->lock_object);
|
||||
v = rw->rw_lock;
|
||||
|
||||
/*
|
||||
* If the lock was released while spinning on the
|
||||
* turnstile chain lock, try again.
|
||||
*/
|
||||
if (v == RW_UNLOCKED) {
|
||||
turnstile_cancel(ts);
|
||||
cpu_spinwait();
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the lock was released by a writer with both readers
|
||||
* and writers waiting and a reader hasn't woken up and
|
||||
* acquired the lock yet, rw_lock will be set to the
|
||||
* value RW_UNLOCKED | RW_LOCK_WRITE_WAITERS. If we see
|
||||
* that value, try to acquire it once. Note that we have
|
||||
* to preserve the RW_LOCK_WRITE_WAITERS flag as there are
|
||||
* other writers waiting still. If we fail, restart the
|
||||
* loop.
|
||||
*/
|
||||
if (v == (RW_UNLOCKED | RW_LOCK_WRITE_WAITERS)) {
|
||||
if (atomic_cmpset_acq_ptr(&rw->rw_lock,
|
||||
RW_UNLOCKED | RW_LOCK_WRITE_WAITERS,
|
||||
tid | RW_LOCK_WRITE_WAITERS)) {
|
||||
turnstile_claim(ts);
|
||||
CTR2(KTR_LOCK, "%s: %p claimed by new writer",
|
||||
__func__, rw);
|
||||
break;
|
||||
}
|
||||
turnstile_cancel(ts);
|
||||
cpu_spinwait();
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the RW_LOCK_WRITE_WAITERS flag isn't set, then try to
|
||||
* set it. If we fail to set it, then loop back and try
|
||||
* again.
|
||||
*/
|
||||
if (!(v & RW_LOCK_WRITE_WAITERS)) {
|
||||
if (!atomic_cmpset_ptr(&rw->rw_lock, v,
|
||||
v | RW_LOCK_WRITE_WAITERS)) {
|
||||
turnstile_cancel(ts);
|
||||
cpu_spinwait();
|
||||
continue;
|
||||
}
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p set write waiters flag",
|
||||
__func__, rw);
|
||||
}
|
||||
|
||||
#ifdef ADAPTIVE_RWLOCKS
|
||||
/*
|
||||
* If the lock is write locked and the owner is
|
||||
* running on another CPU, spin until the owner stops
|
||||
* running or the state of the lock changes.
|
||||
*/
|
||||
owner = (struct thread *)RW_OWNER(v);
|
||||
if (!(v & RW_LOCK_READ) && TD_IS_RUNNING(owner)) {
|
||||
turnstile_cancel(ts);
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
|
||||
__func__, rw, owner);
|
||||
lock_profile_obtain_lock_failed(&rw->lock_object,
|
||||
&contested, &waittime);
|
||||
while ((struct thread*)RW_OWNER(rw->rw_lock)== owner &&
|
||||
TD_IS_RUNNING(owner))
|
||||
cpu_spinwait();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We were unable to acquire the lock and the write waiters
|
||||
* flag is set, so we must block on the turnstile.
|
||||
*/
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p blocking on turnstile", __func__,
|
||||
rw);
|
||||
lock_profile_obtain_lock_failed(&rw->lock_object, &contested,
|
||||
&waittime);
|
||||
turnstile_wait(ts, rw_owner(rw), TS_EXCLUSIVE_QUEUE);
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p resuming from turnstile",
|
||||
__func__, rw);
|
||||
}
|
||||
lock_profile_obtain_lock_success(&rw->lock_object, contested, waittime,
|
||||
file, line);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called if the first try at releasing a write lock failed.
|
||||
* This means that one of the 2 waiter bits must be set indicating that at
|
||||
* least one thread is waiting on this lock.
|
||||
*/
|
||||
void
|
||||
_rw_wunlock_hard(struct rwlock *rw, uintptr_t tid, const char *file, int line)
|
||||
{
|
||||
struct turnstile *ts;
|
||||
uintptr_t v;
|
||||
int queue;
|
||||
|
||||
if (rw_wlocked(rw) && rw_recursed(rw)) {
|
||||
if ((--rw->rw_recurse) == 0)
|
||||
atomic_clear_ptr(&rw->rw_lock, RW_LOCK_RECURSED);
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p unrecursing", __func__, rw);
|
||||
return;
|
||||
}
|
||||
|
||||
KASSERT(rw->rw_lock & (RW_LOCK_READ_WAITERS | RW_LOCK_WRITE_WAITERS),
|
||||
("%s: neither of the waiter flags are set", __func__));
|
||||
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p contested", __func__, rw);
|
||||
|
||||
turnstile_chain_lock(&rw->lock_object);
|
||||
ts = turnstile_lookup(&rw->lock_object);
|
||||
|
||||
#ifdef ADAPTIVE_RWLOCKS
|
||||
/*
|
||||
* There might not be a turnstile for this lock if all of
|
||||
* the waiters are adaptively spinning. In that case, just
|
||||
* reset the lock to the unlocked state and return.
|
||||
*/
|
||||
if (ts == NULL) {
|
||||
atomic_store_rel_ptr(&rw->rw_lock, RW_UNLOCKED);
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p no sleepers", __func__, rw);
|
||||
turnstile_chain_unlock(&rw->lock_object);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
MPASS(ts != NULL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Use the same algo as sx locks for now. Prefer waking up shared
|
||||
* waiters if we have any over writers. This is probably not ideal.
|
||||
*
|
||||
* 'v' is the value we are going to write back to rw_lock. If we
|
||||
* have waiters on both queues, we need to preserve the state of
|
||||
* the waiter flag for the queue we don't wake up. For now this is
|
||||
* hardcoded for the algorithm mentioned above.
|
||||
*
|
||||
* In the case of both readers and writers waiting we wakeup the
|
||||
* readers but leave the RW_LOCK_WRITE_WAITERS flag set. If a
|
||||
* new writer comes in before a reader it will claim the lock up
|
||||
* above. There is probably a potential priority inversion in
|
||||
* there that could be worked around either by waking both queues
|
||||
* of waiters or doing some complicated lock handoff gymnastics.
|
||||
*
|
||||
* Note that in the ADAPTIVE_RWLOCKS case, if both flags are
|
||||
* set, there might not be any actual writers on the turnstile
|
||||
* as they might all be spinning. In that case, we don't want
|
||||
* to preserve the RW_LOCK_WRITE_WAITERS flag as the turnstile
|
||||
* is going to go away once we wakeup all the readers.
|
||||
*/
|
||||
v = RW_UNLOCKED;
|
||||
if (rw->rw_lock & RW_LOCK_READ_WAITERS) {
|
||||
queue = TS_SHARED_QUEUE;
|
||||
#ifdef ADAPTIVE_RWLOCKS
|
||||
if (rw->rw_lock & RW_LOCK_WRITE_WAITERS &&
|
||||
!turnstile_empty(ts, TS_EXCLUSIVE_QUEUE))
|
||||
v |= RW_LOCK_WRITE_WAITERS;
|
||||
#else
|
||||
v |= (rw->rw_lock & RW_LOCK_WRITE_WAITERS);
|
||||
#endif
|
||||
} else
|
||||
queue = TS_EXCLUSIVE_QUEUE;
|
||||
|
||||
#ifdef ADAPTIVE_RWLOCKS
|
||||
/*
|
||||
* We have to make sure that we actually have waiters to
|
||||
* wakeup. If they are all spinning, then we just need to
|
||||
* disown the turnstile and return.
|
||||
*/
|
||||
if (turnstile_empty(ts, queue)) {
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR2(KTR_LOCK, "%s: %p no sleepers 2", __func__, rw);
|
||||
atomic_store_rel_ptr(&rw->rw_lock, v);
|
||||
turnstile_disown(ts);
|
||||
turnstile_chain_unlock(&rw->lock_object);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Wake up all waiters for the specific queue. */
|
||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||
CTR3(KTR_LOCK, "%s: %p waking up %s waiters", __func__, rw,
|
||||
queue == TS_SHARED_QUEUE ? "read" : "write");
|
||||
turnstile_broadcast(ts, queue);
|
||||
atomic_store_rel_ptr(&rw->rw_lock, v);
|
||||
turnstile_unpend(ts, TS_EXCLUSIVE_LOCK);
|
||||
turnstile_chain_unlock(&rw->lock_object);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to do a non-blocking upgrade from a read lock to a write
|
||||
* lock. This will only succeed if this thread holds a single read
|
||||
* lock. Returns true if the upgrade succeeded and false otherwise.
|
||||
*/
|
||||
int
|
||||
_rw_try_upgrade(struct rwlock *rw, const char *file, int line)
|
||||
{
|
||||
uintptr_t v, tid;
|
||||
struct turnstile *ts;
|
||||
int success;
|
||||
|
||||
KASSERT(rw->rw_lock != RW_DESTROYED,
|
||||
("rw_try_upgrade() of destroyed rwlock @ %s:%d", file, line));
|
||||
_rw_assert(rw, RA_RLOCKED, file, line);
|
||||
|
||||
/*
|
||||
* Attempt to switch from one reader to a writer. If there
|
||||
* are any write waiters, then we will have to lock the
|
||||
* turnstile first to prevent races with another writer
|
||||
* calling turnstile_wait() before we have claimed this
|
||||
* turnstile. So, do the simple case of no waiters first.
|
||||
*/
|
||||
tid = (uintptr_t)curthread;
|
||||
if (!(rw->rw_lock & RW_LOCK_WRITE_WAITERS)) {
|
||||
success = atomic_cmpset_ptr(&rw->rw_lock, RW_READERS_LOCK(1),
|
||||
tid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ok, we think we have write waiters, so lock the
|
||||
* turnstile.
|
||||
*/
|
||||
ts = turnstile_trywait(&rw->lock_object);
|
||||
|
||||
/*
|
||||
* Try to switch from one reader to a writer again. This time
|
||||
* we honor the current state of the RW_LOCK_WRITE_WAITERS
|
||||
* flag. If we obtain the lock with the flag set, then claim
|
||||
* ownership of the turnstile. In the ADAPTIVE_RWLOCKS case
|
||||
* it is possible for there to not be an associated turnstile
|
||||
* even though there are waiters if all of the waiters are
|
||||
* spinning.
|
||||
*/
|
||||
v = rw->rw_lock & RW_LOCK_WRITE_WAITERS;
|
||||
success = atomic_cmpset_ptr(&rw->rw_lock, RW_READERS_LOCK(1) | v,
|
||||
tid | v);
|
||||
#ifdef ADAPTIVE_RWLOCKS
|
||||
if (success && v && turnstile_lookup(&rw->lock_object) != NULL)
|
||||
#else
|
||||
if (success && v)
|
||||
#endif
|
||||
turnstile_claim(ts);
|
||||
else
|
||||
turnstile_cancel(ts);
|
||||
out:
|
||||
LOCK_LOG_TRY("WUPGRADE", &rw->lock_object, 0, success, file, line);
|
||||
if (success)
|
||||
WITNESS_UPGRADE(&rw->lock_object, LOP_EXCLUSIVE | LOP_TRYLOCK,
|
||||
file, line);
|
||||
return (success);
|
||||
}
|
||||
|
||||
/*
|
||||
* Downgrade a write lock into a single read lock.
|
||||
*/
|
||||
void
|
||||
_rw_downgrade(struct rwlock *rw, const char *file, int line)
|
||||
{
|
||||
struct turnstile *ts;
|
||||
uintptr_t tid, v;
|
||||
|
||||
KASSERT(rw->rw_lock != RW_DESTROYED,
|
||||
("rw_downgrade() of destroyed rwlock @ %s:%d", file, line));
|
||||
_rw_assert(rw, RA_WLOCKED | RA_NOTRECURSED, file, line);
|
||||
#ifndef INVARIANTS
|
||||
if (rw_recursed(rw))
|
||||
panic("downgrade of a recursed lock");
|
||||
#endif
|
||||
|
||||
WITNESS_DOWNGRADE(&rw->lock_object, 0, file, line);
|
||||
|
||||
/*
|
||||
* Convert from a writer to a single reader. First we handle
|
||||
* the easy case with no waiters. If there are any waiters, we
|
||||
* lock the turnstile, "disown" the lock, and awaken any read
|
||||
* waiters.
|
||||
*/
|
||||
tid = (uintptr_t)curthread;
|
||||
if (atomic_cmpset_rel_ptr(&rw->rw_lock, tid, RW_READERS_LOCK(1)))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Ok, we think we have waiters, so lock the turnstile so we can
|
||||
* read the waiter flags without any races.
|
||||
*/
|
||||
turnstile_chain_lock(&rw->lock_object);
|
||||
v = rw->rw_lock;
|
||||
MPASS(v & (RW_LOCK_READ_WAITERS | RW_LOCK_WRITE_WAITERS));
|
||||
|
||||
/*
|
||||
* Downgrade from a write lock while preserving
|
||||
* RW_LOCK_WRITE_WAITERS and give up ownership of the
|
||||
* turnstile. If there are any read waiters, wake them up.
|
||||
*
|
||||
* For ADAPTIVE_RWLOCKS, we have to allow for the fact that
|
||||
* all of the read waiters might be spinning. In that case,
|
||||
* act as if RW_LOCK_READ_WAITERS is not set. Also, only
|
||||
* preserve the RW_LOCK_WRITE_WAITERS flag if at least one
|
||||
* writer is blocked on the turnstile.
|
||||
*/
|
||||
ts = turnstile_lookup(&rw->lock_object);
|
||||
#ifdef ADAPTIVE_RWLOCKS
|
||||
if (ts == NULL)
|
||||
v &= ~(RW_LOCK_READ_WAITERS | RW_LOCK_WRITE_WAITERS);
|
||||
else if (v & RW_LOCK_READ_WAITERS &&
|
||||
turnstile_empty(ts, TS_SHARED_QUEUE))
|
||||
v &= ~RW_LOCK_READ_WAITERS;
|
||||
else if (v & RW_LOCK_WRITE_WAITERS &&
|
||||
turnstile_empty(ts, TS_EXCLUSIVE_QUEUE))
|
||||
v &= ~RW_LOCK_WRITE_WAITERS;
|
||||
#else
|
||||
MPASS(ts != NULL);
|
||||
#endif
|
||||
if (v & RW_LOCK_READ_WAITERS)
|
||||
turnstile_broadcast(ts, TS_SHARED_QUEUE);
|
||||
atomic_store_rel_ptr(&rw->rw_lock, RW_READERS_LOCK(1) |
|
||||
(v & RW_LOCK_WRITE_WAITERS));
|
||||
if (v & RW_LOCK_READ_WAITERS)
|
||||
turnstile_unpend(ts, TS_EXCLUSIVE_LOCK);
|
||||
else if (ts)
|
||||
turnstile_disown(ts);
|
||||
turnstile_chain_unlock(&rw->lock_object);
|
||||
out:
|
||||
LOCK_LOG_LOCK("WDOWNGRADE", &rw->lock_object, 0, 0, file, line);
|
||||
}
|
||||
|
||||
#ifdef INVARIANT_SUPPORT
|
||||
#ifndef INVARIANTS
|
||||
#undef _rw_assert
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In the non-WITNESS case, rw_assert() can only detect that at least
|
||||
* *some* thread owns an rlock, but it cannot guarantee that *this*
|
||||
* thread owns an rlock.
|
||||
*/
|
||||
void
|
||||
_rw_assert(struct rwlock *rw, int what, const char *file, int line)
|
||||
{
|
||||
|
||||
if (panicstr != NULL)
|
||||
return;
|
||||
switch (what) {
|
||||
case RA_LOCKED:
|
||||
case RA_LOCKED | RA_RECURSED:
|
||||
case RA_LOCKED | RA_NOTRECURSED:
|
||||
case RA_RLOCKED:
|
||||
#ifdef WITNESS
|
||||
witness_assert(&rw->lock_object, what, file, line);
|
||||
#else
|
||||
/*
|
||||
* If some other thread has a write lock or we have one
|
||||
* and are asserting a read lock, fail. Also, if no one
|
||||
* has a lock at all, fail.
|
||||
*/
|
||||
if (rw->rw_lock == RW_UNLOCKED ||
|
||||
(!(rw->rw_lock & RW_LOCK_READ) && (what == RA_RLOCKED ||
|
||||
rw_wowner(rw) != curthread)))
|
||||
panic("Lock %s not %slocked @ %s:%d\n",
|
||||
rw->lock_object.lo_name, (what == RA_RLOCKED) ?
|
||||
"read " : "", file, line);
|
||||
|
||||
if (!(rw->rw_lock & RW_LOCK_READ)) {
|
||||
if (rw_recursed(rw)) {
|
||||
if (what & RA_NOTRECURSED)
|
||||
panic("Lock %s recursed @ %s:%d\n",
|
||||
rw->lock_object.lo_name, file,
|
||||
line);
|
||||
} else if (what & RA_RECURSED)
|
||||
panic("Lock %s not recursed @ %s:%d\n",
|
||||
rw->lock_object.lo_name, file, line);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case RA_WLOCKED:
|
||||
case RA_WLOCKED | RA_RECURSED:
|
||||
case RA_WLOCKED | RA_NOTRECURSED:
|
||||
if (rw_wowner(rw) != curthread)
|
||||
panic("Lock %s not exclusively locked @ %s:%d\n",
|
||||
rw->lock_object.lo_name, file, line);
|
||||
if (rw_recursed(rw)) {
|
||||
if (what & RA_NOTRECURSED)
|
||||
panic("Lock %s recursed @ %s:%d\n",
|
||||
rw->lock_object.lo_name, file, line);
|
||||
} else if (what & RA_RECURSED)
|
||||
panic("Lock %s not recursed @ %s:%d\n",
|
||||
rw->lock_object.lo_name, file, line);
|
||||
break;
|
||||
case RA_UNLOCKED:
|
||||
#ifdef WITNESS
|
||||
witness_assert(&rw->lock_object, what, file, line);
|
||||
#else
|
||||
/*
|
||||
* If we hold a write lock fail. We can't reliably check
|
||||
* to see if we hold a read lock or not.
|
||||
*/
|
||||
if (rw_wowner(rw) == curthread)
|
||||
panic("Lock %s exclusively locked @ %s:%d\n",
|
||||
rw->lock_object.lo_name, file, line);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
panic("Unknown rw lock assertion: %d @ %s:%d", what, file,
|
||||
line);
|
||||
}
|
||||
}
|
||||
#endif /* INVARIANT_SUPPORT */
|
||||
|
||||
#ifdef DDB
|
||||
void
|
||||
db_show_rwlock(struct lock_object *lock)
|
||||
{
|
||||
struct rwlock *rw;
|
||||
struct thread *td;
|
||||
|
||||
rw = (struct rwlock *)lock;
|
||||
|
||||
db_printf(" state: ");
|
||||
if (rw->rw_lock == RW_UNLOCKED)
|
||||
db_printf("UNLOCKED\n");
|
||||
else if (rw->rw_lock == RW_DESTROYED) {
|
||||
db_printf("DESTROYED\n");
|
||||
return;
|
||||
} else if (rw->rw_lock & RW_LOCK_READ)
|
||||
db_printf("RLOCK: %ju locks\n",
|
||||
(uintmax_t)(RW_READERS(rw->rw_lock)));
|
||||
else {
|
||||
td = rw_wowner(rw);
|
||||
db_printf("WLOCK: %p (tid %d, pid %d, \"%s\")\n", td,
|
||||
td->td_tid, td->td_proc->p_pid, td->td_proc->p_comm);
|
||||
if (rw_recursed(rw))
|
||||
db_printf(" recursed: %u\n", rw->rw_recurse);
|
||||
}
|
||||
db_printf(" waiters: ");
|
||||
switch (rw->rw_lock & (RW_LOCK_READ_WAITERS | RW_LOCK_WRITE_WAITERS)) {
|
||||
case RW_LOCK_READ_WAITERS:
|
||||
db_printf("readers\n");
|
||||
break;
|
||||
case RW_LOCK_WRITE_WAITERS:
|
||||
db_printf("writers\n");
|
||||
break;
|
||||
case RW_LOCK_READ_WAITERS | RW_LOCK_WRITE_WAITERS:
|
||||
db_printf("readers and writers\n");
|
||||
break;
|
||||
default:
|
||||
db_printf("none\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
8
sys/modules/coretemp/Makefile
Normal file
8
sys/modules/coretemp/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../dev/coretemp
|
||||
|
||||
KMOD= coretemp
|
||||
SRCS= coretemp.c bus_if.h device_if.h
|
||||
|
||||
.include <bsd.kmod.mk>
|
167
sys/sys/lock_profile.h
Normal file
167
sys/sys/lock_profile.h
Normal file
@ -0,0 +1,167 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 Kip Macy kmacy@FreeBSD.org
|
||||
* Copyright (c) 2006 Kris Kennaway kris@FreeBSD.org
|
||||
* Copyright (c) 2006 Dag-Erling Smorgrav des@des.no
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHAL THE AUTHORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SYS_LOCK_PROFILE_H_
|
||||
#define _SYS_LOCK_PROFILE_H_
|
||||
|
||||
#ifdef LOCK_PROFILING
|
||||
#include <sys/stdint.h>
|
||||
#include <sys/ktr.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <machine/atomic.h>
|
||||
#include <machine/cpufunc.h>
|
||||
|
||||
#ifndef LPROF_HASH_SIZE
|
||||
#define LPROF_HASH_SIZE 4096
|
||||
#define LPROF_HASH_MASK (LPROF_HASH_SIZE - 1)
|
||||
#endif
|
||||
|
||||
#ifndef USE_CPU_NANOSECONDS
|
||||
u_int64_t nanoseconds(void);
|
||||
#endif
|
||||
|
||||
struct lock_prof {
|
||||
const char *name;
|
||||
const char *type;
|
||||
const char *file;
|
||||
u_int namehash;
|
||||
int line;
|
||||
uintmax_t cnt_max;
|
||||
uintmax_t cnt_tot;
|
||||
uintmax_t cnt_wait;
|
||||
uintmax_t cnt_cur;
|
||||
uintmax_t cnt_contest_holding;
|
||||
uintmax_t cnt_contest_locking;
|
||||
};
|
||||
|
||||
extern struct lock_prof lprof_buf[LPROF_HASH_SIZE];
|
||||
#define LPROF_SBUF_SIZE 256 * 400
|
||||
|
||||
/* We keep a smaller pool of spin mutexes for protecting the lprof hash entries */
|
||||
#define LPROF_LOCK_SIZE 16
|
||||
#define LPROF_LOCK_MASK (LPROF_LOCK_SIZE - 1)
|
||||
#define LPROF_LHASH(hash) ((hash) & LPROF_LOCK_MASK)
|
||||
|
||||
#define LPROF_LOCK(hash) mtx_lock_spin(&lprof_locks[LPROF_LHASH(hash)])
|
||||
#define LPROF_UNLOCK(hash) mtx_unlock_spin(&lprof_locks[LPROF_LHASH(hash)])
|
||||
|
||||
#ifdef _KERNEL
|
||||
extern struct mtx lprof_locks[LPROF_LOCK_SIZE];
|
||||
extern int lock_prof_enable;
|
||||
|
||||
void _lock_profile_obtain_lock_success(struct lock_object *lo, int contested, uint64_t waittime, const char *file, int line);
|
||||
void _lock_profile_update_wait(struct lock_object *lo, uint64_t waitstart);
|
||||
void _lock_profile_release_lock(struct lock_object *lo);
|
||||
|
||||
static inline void lock_profile_object_init(struct lock_object *lo, struct lock_class *class, const char *name) {
|
||||
const char *p;
|
||||
u_int hash = 0;
|
||||
struct lock_profile_object *l = &lo->lo_profile_obj;
|
||||
|
||||
l->lpo_acqtime = 0;
|
||||
l->lpo_waittime = 0;
|
||||
l->lpo_filename = NULL;
|
||||
l->lpo_lineno = 0;
|
||||
l->lpo_contest_holding = 0;
|
||||
l->lpo_contest_locking = 0;
|
||||
l->lpo_type = class->lc_name;
|
||||
|
||||
/* Hash the mutex name to an int so we don't have to strcmp() it repeatedly */
|
||||
for (p = name; *p != '\0'; p++)
|
||||
hash = 31 * hash + *p;
|
||||
l->lpo_namehash = hash;
|
||||
#if 0
|
||||
if (opts & MTX_PROFILE)
|
||||
l->lpo_stack = stack_create();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
lock_profile_object_destroy(struct lock_object *lo)
|
||||
{
|
||||
#if 0
|
||||
struct lock_profile_object *l = &lo->lo_profile_obj;
|
||||
if (lo->lo_flags & LO_PROFILE)
|
||||
stack_destroy(l->lpo_stack);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void lock_profile_obtain_lock_failed(struct lock_object *lo, int *contested,
|
||||
uint64_t *waittime)
|
||||
{
|
||||
struct lock_profile_object *l = &lo->lo_profile_obj;
|
||||
|
||||
if (lock_prof_enable && *contested == 0) {
|
||||
*waittime = nanoseconds();
|
||||
atomic_add_int(&l->lpo_contest_holding, 1);
|
||||
*contested = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void lock_profile_obtain_lock_success(struct lock_object *lo, int contested, uint64_t waittime, const char *file, int line)
|
||||
{
|
||||
|
||||
/* don't reset the timer when/if recursing */
|
||||
if (lock_prof_enable && lo->lo_profile_obj.lpo_acqtime == 0) {
|
||||
#ifdef LOCK_PROFILING_FAST
|
||||
if (contested == 0)
|
||||
return;
|
||||
#endif
|
||||
_lock_profile_obtain_lock_success(lo, contested, waittime, file, line);
|
||||
}
|
||||
}
|
||||
static inline void lock_profile_release_lock(struct lock_object *lo)
|
||||
{
|
||||
struct lock_profile_object *l = &lo->lo_profile_obj;
|
||||
|
||||
if (l->lpo_acqtime)
|
||||
_lock_profile_release_lock(lo);
|
||||
}
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#else /* !LOCK_PROFILING */
|
||||
|
||||
#ifdef _KERNEL
|
||||
static inline void lock_profile_update_wait(struct lock_object *lo, uint64_t waitstart) {;}
|
||||
static inline void lock_profile_update_contest_locking(struct lock_object *lo, int contested) {;}
|
||||
static inline void lock_profile_release_lock(struct lock_object *lo) {;}
|
||||
static inline void lock_profile_obtain_lock_failed(struct lock_object *lo, int *contested, uint64_t *waittime) {;}
|
||||
static inline void lock_profile_obtain_lock_success(struct lock_object *lo, int contested, uint64_t waittime,
|
||||
const char *file, int line) {;}
|
||||
static inline void lock_profile_object_destroy(struct lock_object *lo) {;}
|
||||
static inline void lock_profile_object_init(struct lock_object *lo, struct lock_class *class, const char *name) {;}
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !LOCK_PROFILING */
|
||||
|
||||
#endif /* _SYS_LOCK_PROFILE_H_ */
|
219
sys/sys/rwlock.h
Normal file
219
sys/sys/rwlock.h
Normal file
@ -0,0 +1,219 @@
|
||||
/*-
|
||||
* Copyright (c) 2006 John Baldwin <jhb@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the author nor the names of any co-contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _SYS_RWLOCK_H_
|
||||
#define _SYS_RWLOCK_H_
|
||||
|
||||
#include <sys/_lock.h>
|
||||
#include <sys/_rwlock.h>
|
||||
#include <sys/lock_profile.h>
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <sys/pcpu.h>
|
||||
#include <machine/atomic.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The rw_lock field consists of several fields. The low bit indicates
|
||||
* if the lock is locked with a read (shared) or write (exclusive) lock.
|
||||
* A value of 0 indicates a write lock, and a value of 1 indicates a read
|
||||
* lock. Bit 1 is a boolean indicating if there are any threads waiting
|
||||
* for a read lock. Bit 2 is a boolean indicating if there are any threads
|
||||
* waiting for a write lock. The rest of the variable's definition is
|
||||
* dependent on the value of the first bit. For a write lock, it is a
|
||||
* pointer to the thread holding the lock, similar to the mtx_lock field of
|
||||
* mutexes. For read locks, it is a count of read locks that are held.
|
||||
*
|
||||
* When the lock is not locked by any thread, it is encoded as a read lock
|
||||
* with zero waiters.
|
||||
*
|
||||
* A note about memory barriers. Write locks need to use the same memory
|
||||
* barriers as mutexes: _acq when acquiring a write lock and _rel when
|
||||
* releasing a write lock. Read locks also need to use an _acq barrier when
|
||||
* acquiring a read lock. However, since read locks do not update any
|
||||
* locked data (modulo bugs of course), no memory barrier is needed when
|
||||
* releasing a read lock.
|
||||
*/
|
||||
|
||||
#define RW_LOCK_READ 0x01
|
||||
#define RW_LOCK_READ_WAITERS 0x02
|
||||
#define RW_LOCK_WRITE_WAITERS 0x04
|
||||
#define RW_LOCK_RECURSED 0x08
|
||||
#define RW_LOCK_FLAGMASK \
|
||||
(RW_LOCK_READ | RW_LOCK_READ_WAITERS | RW_LOCK_WRITE_WAITERS | \
|
||||
RW_LOCK_RECURSED)
|
||||
|
||||
#define RW_OWNER(x) ((x) & ~RW_LOCK_FLAGMASK)
|
||||
#define RW_READERS_SHIFT 4
|
||||
#define RW_READERS(x) (RW_OWNER((x)) >> RW_READERS_SHIFT)
|
||||
#define RW_READERS_LOCK(x) ((x) << RW_READERS_SHIFT | RW_LOCK_READ)
|
||||
#define RW_ONE_READER (1 << RW_READERS_SHIFT)
|
||||
|
||||
#define RW_UNLOCKED RW_READERS_LOCK(0)
|
||||
#define RW_DESTROYED (RW_LOCK_READ_WAITERS | RW_LOCK_WRITE_WAITERS)
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
/* Very simple operations on rw_lock. */
|
||||
|
||||
/* Try to obtain a write lock once. */
|
||||
#define _rw_write_lock(rw, tid) \
|
||||
atomic_cmpset_acq_ptr(&(rw)->rw_lock, RW_UNLOCKED, (tid))
|
||||
|
||||
/* Release a write lock quickly if there are no waiters. */
|
||||
#define _rw_write_unlock(rw, tid) \
|
||||
atomic_cmpset_rel_ptr(&(rw)->rw_lock, (tid), RW_UNLOCKED)
|
||||
|
||||
/*
|
||||
* Full lock operations that are suitable to be inlined in non-debug
|
||||
* kernels. If the lock cannot be acquired or released trivially then
|
||||
* the work is deferred to another function.
|
||||
*/
|
||||
|
||||
/* Acquire a write lock. */
|
||||
#define __rw_wlock(rw, tid, file, line) do { \
|
||||
uintptr_t _tid = (uintptr_t)(tid); \
|
||||
\
|
||||
if (!_rw_write_lock((rw), _tid)) \
|
||||
_rw_wlock_hard((rw), _tid, (file), (line)); \
|
||||
else \
|
||||
lock_profile_obtain_lock_success(&(rw)->lock_object, 0, \
|
||||
0, (file), (line)); \
|
||||
} while (0)
|
||||
|
||||
/* Release a write lock. */
|
||||
#define __rw_wunlock(rw, tid, file, line) do { \
|
||||
uintptr_t _tid = (uintptr_t)(tid); \
|
||||
\
|
||||
if (!_rw_write_unlock((rw), _tid)) \
|
||||
_rw_wunlock_hard((rw), _tid, (file), (line)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Function prototypes. Routines that start with _ are not part of the
|
||||
* external API and should not be called directly. Wrapper macros should
|
||||
* be used instead.
|
||||
*/
|
||||
|
||||
#define rw_init(rw, name) rw_init_flags((rw), (name), 0)
|
||||
void rw_init_flags(struct rwlock *rw, const char *name, int opts);
|
||||
void rw_destroy(struct rwlock *rw);
|
||||
void rw_sysinit(void *arg);
|
||||
int rw_wowned(struct rwlock *rw);
|
||||
void _rw_wlock(struct rwlock *rw, const char *file, int line);
|
||||
void _rw_wunlock(struct rwlock *rw, const char *file, int line);
|
||||
void _rw_rlock(struct rwlock *rw, const char *file, int line);
|
||||
void _rw_runlock(struct rwlock *rw, const char *file, int line);
|
||||
void _rw_wlock_hard(struct rwlock *rw, uintptr_t tid, const char *file,
|
||||
int line);
|
||||
void _rw_wunlock_hard(struct rwlock *rw, uintptr_t tid, const char *file,
|
||||
int line);
|
||||
int _rw_try_upgrade(struct rwlock *rw, const char *file, int line);
|
||||
void _rw_downgrade(struct rwlock *rw, const char *file, int line);
|
||||
#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
|
||||
void _rw_assert(struct rwlock *rw, int what, const char *file, int line);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Public interface for lock operations.
|
||||
*
|
||||
* XXX: Missing try locks.
|
||||
*/
|
||||
|
||||
#ifndef LOCK_DEBUG
|
||||
#error LOCK_DEBUG not defined, include <sys/lock.h> before <sys/rwlock.h>
|
||||
#endif
|
||||
#if LOCK_DEBUG > 0 || defined(RWLOCK_NOINLINE)
|
||||
#define rw_wlock(rw) _rw_wlock((rw), LOCK_FILE, LOCK_LINE)
|
||||
#define rw_wunlock(rw) _rw_wunlock((rw), LOCK_FILE, LOCK_LINE)
|
||||
#else
|
||||
#define rw_wlock(rw) \
|
||||
__rw_wlock((rw), curthread, LOCK_FILE, LOCK_LINE)
|
||||
#define rw_wunlock(rw) \
|
||||
__rw_wunlock((rw), curthread, LOCK_FILE, LOCK_LINE)
|
||||
#endif
|
||||
#define rw_rlock(rw) _rw_rlock((rw), LOCK_FILE, LOCK_LINE)
|
||||
#define rw_runlock(rw) _rw_runlock((rw), LOCK_FILE, LOCK_LINE)
|
||||
#define rw_try_upgrade(rw) _rw_try_upgrade((rw), LOCK_FILE, LOCK_LINE)
|
||||
#define rw_downgrade(rw) _rw_downgrade((rw), LOCK_FILE, LOCK_LINE)
|
||||
#define rw_sleep(chan, rw, pri, wmesg, timo) \
|
||||
_sleep((chan), &(rw)->lock_object, (pri), (wmesg), (timo))
|
||||
|
||||
#define rw_initialized(rw) lock_initalized(&(rw)->lock_object)
|
||||
|
||||
struct rw_args {
|
||||
struct rwlock *ra_rw;
|
||||
const char *ra_desc;
|
||||
};
|
||||
|
||||
#define RW_SYSINIT(name, rw, desc) \
|
||||
static struct rw_args name##_args = { \
|
||||
(rw), \
|
||||
(desc), \
|
||||
}; \
|
||||
SYSINIT(name##_rw_sysinit, SI_SUB_LOCK, SI_ORDER_MIDDLE, \
|
||||
rw_sysinit, &name##_args); \
|
||||
SYSUNINIT(name##_rw_sysuninit, SI_SUB_LOCK, SI_ORDER_MIDDLE, \
|
||||
rw_destroy, (rw))
|
||||
|
||||
/*
|
||||
* Options passed to rw_init_flags().
|
||||
*/
|
||||
#define RW_DUPOK 0x01
|
||||
#define RW_NOPROFILE 0x02
|
||||
#define RW_NOWITNESS 0x04
|
||||
#define RW_QUIET 0x08
|
||||
#define RW_RECURSE 0x10
|
||||
|
||||
/*
|
||||
* The INVARIANTS-enabled rw_assert() functionality.
|
||||
*
|
||||
* The constants need to be defined for INVARIANT_SUPPORT infrastructure
|
||||
* support as _rw_assert() itself uses them and the latter implies that
|
||||
* _rw_assert() must build.
|
||||
*/
|
||||
#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
|
||||
#define RA_LOCKED LA_LOCKED
|
||||
#define RA_RLOCKED LA_SLOCKED
|
||||
#define RA_WLOCKED LA_XLOCKED
|
||||
#define RA_UNLOCKED LA_UNLOCKED
|
||||
#define RA_RECURSED LA_RECURSED
|
||||
#define RA_NOTRECURSED LA_NOTRECURSED
|
||||
#endif
|
||||
|
||||
#ifdef INVARIANTS
|
||||
#define rw_assert(rw, what) _rw_assert((rw), (what), LOCK_FILE, LOCK_LINE)
|
||||
#else
|
||||
#define rw_assert(rw, what)
|
||||
#endif
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif /* !_SYS_RWLOCK_H_ */
|
Loading…
x
Reference in New Issue
Block a user