various bug fixes

This commit is contained in:
rsc 2004-05-14 15:14:21 +00:00
parent a796abef16
commit 1a8f27c350
14 changed files with 1236 additions and 9 deletions

148
man/man1/graph.1 Normal file
View file

@ -0,0 +1,148 @@
.TH GRAPH 1
.CT 1 numbers graphics
.SH NAME
graph \- draw a graph
.SH SYNOPSIS
.B graph
[
.I option ...
]
.SH DESCRIPTION
.I Graph
with no options takes pairs of numbers from the
standard input as abscissas
.RI ( x -values)
and ordinates
.RI ( y -values)
of a graph.
Successive points are connected by straight lines.
The graph is encoded on the standard output
for display by
.IR plot (1)
filters.
.PP
If an ordinate is followed by
a nonnumeric string, that string is printed as a
label beginning on the point.
Labels may be surrounded with quotes
.L
" "
in which case they may be empty or contain blanks
and numbers;
labels never contain newlines.
.PP
The following options are recognized,
each as a separate argument.
.TP
.B -a
Supply abscissas automatically; no
.IR x -values
appear in the input.
Spacing is given by the next
argument (default 1).
A second optional argument is the starting point for
automatic abscissas (default 0, or 1
with a log scale in
.IR x ,
or the lower limit given by
.BR -x ).
.TP
.B -b
Break (disconnect) the graph after each label in the input.
.TP
.B -c
Character string given by next argument
is default label for each point.
.TP
.B -g
Next argument is grid style,
0 no grid, 1 frame with ticks, 2 full grid (default).
.TP
.B -l
Next argument is a legend to title the graph.
Grid ranges
are automatically printed as part
of the title unless a
.B -s
option is present.
.TP
.B -m
Next argument is mode (style)
of connecting lines:
0 disconnected, 1 connected.
Some devices give distinguishable line styles
for other small integers.
Mode \-1 (default) begins with style 1 and
rotates styles for successive curves under option
.BR -o .
.TP
.B -o
(Overlay.)
The ordinates for
.I n
superposed curves appear in the input
with each abscissa value.
The next argument is
.IR n .
.TP
.B -s
Save screen; no new page for this graph.
.TP
.B -x l
If
.B l
is present,
.IR x -axis
is logarithmic.
Next 1 (or 2) arguments are lower (and upper)
.I x
limits.
Third argument, if present, is grid spacing on
.I x
axis.
Normally these quantities are determined automatically.
.TP
.B -y l
Similarly for
.IR y .
.TP
.B -e
Make automatically determined
.I x
and
.I y
scales equal.
.TP
.B -h
Next argument is fraction of space for height.
.TP
.B -w
Similarly for width.
.TP
.B -r
Next argument is fraction of space to move right before plotting.
.TP
.B -u
Similarly to move up before plotting.
.TP
.B -t
Transpose horizontal and vertical axes.
(Option
.B -a
now applies to the vertical axis.)
.PP
If a specified lower limit exceeds the upper limit,
the axis
is reversed.
.SH SOURCE
.B /sys/src/cmd/graph
.SH "SEE ALSO"
.IR plot (1),
.IR grap (1)
.SH BUGS
Segments that run out of bounds are dropped, not windowed.
Logarithmic axes may not be reversed.
Option
.B -e
actually makes automatic limits, rather than automatic scaling,
equal.

61
man/man1/plot.1 Normal file
View file

@ -0,0 +1,61 @@
.TH PLOT 1
.SH NAME
plot \- graphics filter
.SH SYNOPSIS
.B plot
[
.I file ...
]
.SH DESCRIPTION
.I Plot
interprets plotting instructions (see
.IR plot (6))
from the
.I files
or standard input,
drawing the results in a newly created
.IR rio (1)
window.
Plot persists until a newline is typed in the window.
Various options may be interspersed with the
.I file
arguments; they take effect at the given point in processing.
Options are:
.TP "\w'\fL-g \fIgrade\fLXX'u"
.B -d
Double buffer: accumulate the plot off-screen and write to the screen all at once
when an erase command is encountered or at end of file.
.TP
.B -e
Erase the screen.
.TP
.BI -c " col"
Set the foreground color (see
.IR plot (6)
for color names).
.TP
.BI -f " fill"
Set the background color.
.TP
.BI -g " grade"
Set the quality factor for arcs.
Higher grades give better quality.
.TP
.BI -p " col"
Set the pen color.
.TP
.BI -w
Pause until a newline is typed on standard input.
.TP
.B -C
Close the current plot.
.TP
.B -W " x0,y0,x1,y1"
Specify the bounding rectangle of plot's window.
By default it uses a 512×512 window in the
middle of the screen.
.SH SOURCE
.B /sys/src/cmd/plot
.SH "SEE ALSO"
.IR rio (1),
.IR plot (6)

87
man/man5/venti.conf.5 Normal file
View file

@ -0,0 +1,87 @@
.TH VENTI.CONF 6
.SH NAME
venti.conf \- a venti configuration file
.SH DESCRIPTION
A venti configuration file enumerates the various index sections and
arenas that constitute a venti system.
The components are indicated by the name of the file, typically
a disk partition, in which they reside. The configuration
file is the only location that file names are used. Internally,
venti uses the names assigned when the components were formatted
with
.I fmtarenas
or
.I fmtisect
(see
.IR ventiaux (8)).
In particular, by changing the configuration a
component can be copied to a different file.
.PP
The configuration file consists of lines in the form described below.
Lines starting with
.B #
are comments.
.TP
.BI index " name
Names the index for the system.
.TP
.BI arenas " file
.I File
contains a collection of arenas, formatted using
.IR fmtarenas .
.TP
.BI isect " file
.I File
contains an index section, formatted using
.IR fmtisect .
.PP
After formatting a venti system using
.IR fmtindex ,
the order of arenas and index sections should not be changed.
Additional arenas can be appended to the configuration.
.PP
The configuration file optionally holds configuration parameters
for the venti server itself.
These are:
.TP
.BI mem " cachesize
.TP
.BI bcmem " blockcachesize
.TP
.BI icmem " indexcachesize
.TP
.BI addr " ventiaddress
.TP
.BI httpaddr " httpaddress
.TP
.B queuewrites
.PD
See
.IR venti (8)
for descriptions of these variables.
.SH EXAMPLE
.EX
# a sample venti configuration file
#
# formatted with
# venti/fmtarenas arena. /tmp/disks/arenas
# venti/fmtisect isect0 /tmp/disks/isect0
# venti/fmtisect isect1 /tmp/disks/isect1
# venti/fmtindex venti.conf
#
# server is started with
# venti/venti
# the name of the index
index main
# the index sections
isect /tmp/disks/isect0
isect /tmp/disks/isect1
# the arenas
arenas /tmp/disks/arenas
.EE
.SH "SEE ALSO"
.IR venti (8),
.IR ventiaux (8)

232
man/man8/venti.8 Normal file
View file

@ -0,0 +1,232 @@
.TH VENTI 8
.SH NAME
venti \- an archival block storage server
.SH SYNOPSIS
.B venti/venti
[
.B -dsw
]
[
.B -a
.I ventiaddress
]
[
.B -B
.I blockcachesize
]
[
.B -c
.I config
]
[
.B -C
.I cachesize
]
[
.B -h
.I httpaddress
]
[
.B -I
.I icachesize
]
.PP
.B venti/sync
[
.B -h
.I host
]
.SH DESCRIPTION
.I Venti
is a block storage server intended for archival data.
In a Venti server,
the SHA1 hash of a block's contents acts as the block
identifier for read and write operations.
This approach enforces a write-once policy, preventing accidental or
malicious destruction of data. In addition, duplicate copies of a
block are coalesced, reducing the consumption of storage and
simplifying the implementation of clients.
.PP
Storage for
.I venti
consists of a data log and an index, both of which
can be spread across multiple files.
The files containing the data log are themselves divided into self-contained sections called arenas.
Each arena contains a large number of data blocks and is sized to
facilitate operations such as copying to removable media.
The index provides a mapping between the a Sha1 fingerprint and
the location of the corresponding block in the data log.
.PP
The index and data log are typically stored on raw disk partitions.
To improve the robustness, the data log should be stored on
a device that provides RAID functionality. The index does
not require such protection, since if necessary, it can
can be regenerated from the data log.
The performance of
.I venti
is typically limited to the random access performance
of the index. This performance can be improved by spreading the
index accross multiple disks.
.PP
The storage for
.I venti
is initialized using
.IR fmtarenas ,
.IR fmtisect ,
and
.I fmtindex
(see
.IR ventiaux (8)).
A configuration file,
.IR venti.conf (6),
ties the index sections and data arenas together.
.PP
A Venti
server is accessed via an undocumented network protocol.
Two client applications are included in this distribution:
.IR vac (1)
and
.IR vacfs (4).
.I Vac
copies files from a Plan 9 file system to Venti, creating an
archive and returning the fingerprint of the root.
This archive can be mounted in Plan 9 using
.IR vacfs .
These two commands enable a rudimentary backup system.
A future release will include a Plan 9 file system that uses
Venti as a replacement for the WORM device of
.IR fs (4).
.PP
The
.I venti
server provides rudimentary status information via
a built-in http server. The URL files it serves are:
.TP
.B stats
Various internal statistics.
.TP
.B index
An enumeration of the index sections and all non empty arenas, including various statistics.
.TP
.B storage
A summary of the state of the data log.
.TP
.B xindex
An enumeration of the index sections and all non empty arenas, in XML format.
.PP
Several auxiliary utilities (see
.IR ventiaux (8))
aid in maintaining the storage for Venti.
With the exception of
.I rdarena ,
these utilities should generally be run after killing the
.I venti
server.
The utilities are:
.TP
.I checkarenas
Check the integrity, and optionally fix, Venti arenas.
.TP
.I checkindex
Check the integrity, and optionally fix, a Venti index.
.TP
.I buildindex
Rebuild a Venti index from scratch.
.TP
.I rdarena
Extract a Venti arena and write to standard output.
.PD
.PP
Options to
.I venti
are:
.TP
.BI -a " ventiaddress
The network address on which the server listens for incoming connections.
The default is
.LR tcp!*!venti .
.TP
.BI -B " blockcachesize
The size, in bytes, of memory allocated to caching raw disk blocks.
.TP
.BI -c " config
Specifies the
Venti
configuration file.
Defaults to
.LR venti.conf .
.TP
.BI -C " cachesize
The size, in bytes, of memory allocated to caching
Venti
blocks.
.TP
.BI -d
Produce various debugging information on standard error.
.TP
.BI -h " httpaddress
The network address of Venti's built-in
http
server.
The default is
.LR tcp!*!http .
.TP
.BI -I " icachesize
The size, in bytes, of memory allocated to caching the index mapping fingerprints
to locations in
.IR venti 's
data log.
.TP
.B -s
Do not run in the background.
Normally,
the foreground process will exit once the Venti server
is initialized and ready for connections.
.TP
.B -w
Enable write buffering. This option increase the performance of writes to
.I venti
at the cost of returning success to the client application before the
data has been written to disk.
The server implements a
.I sync
rpc that waits for completion of all the writes buffered at the time
the rpc was received.
Applications such as
.IR vac (1)
and the
.I sync
command described below
use this rpc to make sure that the data is correctly written to disk.
Use of this option is recommended.
.PD
.PP
The units for the various cache sizes above can be specified by appending a
.LR k ,
.LR m ,
or
.LR g
to indicate kilobytes, megabytes, or gigabytes respectively.
The command line options override options found in the
.IR venti.conf (6)
file.
.PP
.I Sync
connects to a running Venti server and executes a sync rpc
(described with the
.B -w
option above).
If sync exits successfully, it means that all writes buffered at the
time the command was issued are now on disk.
.SH SOURCE
.B /sys/src/cmd/venti
.SH "SEE ALSO"
.IR venti.conf (6),
.IR ventiaux (8),
.IR vac (1),
.IR vacfs (4).
.br
Sean Quinlan and Sean Dorward,
``Venti: a new approach to archival storage'',
.I "Usenix Conference on File and Storage Technologies" ,
2002.

504
man/man8/ventiaux.8 Normal file
View file

@ -0,0 +1,504 @@
.TH VENTIAUX 8
.SH NAME
buildindex,
checkarenas,
checkindex,
conf,
copy,
fmtarenas,
fmtindex,
fmtisect,
rdarena,
rdarenablocks,
read,
wrarenablocks,
write \- Venti maintenance and debugging commands
.SH SYNOPSIS
.B venti/buildindex
[
.B -B
.I blockcachesize
]
[
.B -Z
]
.I venti.config
.I tmp
.PP
.B venti/checkarenas
[
.B -afv
]
.I file
.PP
.B venti/checkindex
[
.B -f
]
[
.B -B
.I blockcachesize
]
.I venti.config
.I tmp
.PP
.B venti/conf
[
.B -w
]
.I partition
[
.I configfile
]
.PP
.B venti/copy
[
.B -f
]
.I src
.I dst
.I score
[
.I type
]
.PP
.B venti/fmtarenas
[
.B -Z
]
[
.B -a
.I arenasize
]
[
.B -b
.I blocksize
]
.I name
.I file
.PP
.B venti/fmtindex
[
.B -a
]
.I venti.config
.PP
.B venti/fmtisect
[
.B -Z
]
[
.B -b
.I blocksize
]
.I name
.I file
.PP
.B venti/rdarena
[
.B -v
]
.I arenapart
.I arenaname
.PP
.B venti/read
[
.B -h
.I host
]
.I score
[
.I type
]
.PP
.B venti/wrarena
[
.B -o
.I fileoffset
]
[
.B -h
.I host
]
.I arenafile
[
.I clumpoffset
]
.PP
.B venti/write
[
.B -h
.I host
]
[
.B -t
.I type
]
[
.B -z
]
.SH DESCRIPTION
These commands aid in the setup, maintenance, and debugging of
Venti servers.
See
.IR venti (8)
and
.IR venti.conf (6)
for an overview of the data structures stored by Venti.
.PP
Note that the units for the various sizes in the following
commands can be specified by appending
.LR k ,
.LR m ,
or
.LR g
to indicate kilobytes, megabytes, or gigabytes respectively.
.PP
.I Buildindex
populates the index for the Venti system described in
.IR venti.config .
The index must have previously been formatted using
.IR fmtindex .
This command is typically used to build a new index for a Venti
system when the old index becomes too small, or to rebuild
an index after media failure.
Small errors in an index can usually be fixed with
.IR checkindex .
.PP
The
.I tmp
file, usually a disk partition, must be large enough to store a copy of the index.
This temporary space is used to perform a merge sort of index entries
generated by reading the arenas.
.PP
Options to
.I buildindex
are:
.TP
.BI -B " blockcachesize
The amount of memory, in bytes, to use for caching raw disk accesses while running
.IR buildindex .
(This is not a property of the created index.)
The default is 8k.
.TP
.B -Z
Do not zero the index.
This option should only be used when it is known that the index was already zeroed.
.PD
.PP
.I Checkarenas
examines the Venti arenas contained in the given
.IR file .
The program detects various error conditions, and optionally attempts
to fix any errors that are found.
.PP
Options to
.I checkarenas
are:
.TP
.B -a
For each arena, scan the entire data section.
If this option is omitted, only the end section of
the arena is examined.
.TP
.B -f
Attempt to fix any errors that are found.
.TP
.B -v
Increase the verbosity of output.
.PD
.PP
.I Checkindex
examines the Venti index described in
.IR venti.config .
The program detects various error conditions including:
blocks that are not indexed, index entries for blocks that do not exist,
and duplicate index entries.
If requested, an attempt can be made to fix errors that are found.
.PP
The
.I tmp
file, usually a disk partition, must be large enough to store a copy of the index.
This temporary space is used to perform a merge sort of index entries
generated by reading the arenas.
.PP
Options to
.I checkindex
are:
.TP
.BI -B " blockcachesize
The amount of memory, in bytes, to use for caching raw disk accesses while running
.IR checkindex .
The default is 8k.
.TP
.B -f
Attempt to fix any errors that are found.
.PD
.PP
.I Fmtarenas
formats the given
.IR file ,
typically a disk partition, into a number of
Venti
arenas.
The arenas are given names of the form
.IR name%d ,
where
.I %d
is replaced with a sequential number starting at 0.
.PP
Options to
.I fmtarenas
are:
.TP
.BI -a " arenasize
The arenas are of
.I arenasize
bytes. The default is 512 megabytes, which was selected to provide a balance
between the number of arenas and the ability to copy an arena to external
media such as recordable CDs and tapes.
.TP
.BI -b " blocksize
The size, in bytes, for read and write operations to the file.
The size is recorded in the file, and is used by applications that access the arenas.
The default is 8k.
.TP
.B -Z
Do not zero the data sections of the arenas.
Using this option reduces the formatting time
but should only be used when it is known that the file was already zeroed.
.PD
.I Fmtindex
takes the
.IR venti.conf (6)
file
.I venti.config
and initializes the index sections to form a usable index structure.
The arena files and index sections must have previously been formatted
using
.I fmtarenas
and
.I fmtisect
respectively.
.PP
The function of a Venti index is to map a SHA1 fingerprint to a location
in the data section of one of the arenas. The index is composed of
blocks, each of which contains the mapping for a fixed range of possible
fingerprint values.
.I Fmtindex
determines the mapping between SHA1 values and the blocks
of the collection of index sections. Once this mapping has been determined,
it cannot be changed without rebuilding the index.
The basic assumption in the current implementation is that the index
structure is sufficiently empty that individual blocks of the index will rarely
overflow. The total size of the index should be about 2% to 10% of
the total size of the arenas, but the exact depends both the index block size
and the compressed size of block stored to Venti.
.PP
.I Fmtindex
also computes a mapping between a linear address space and
the data section of the collection of arenas. The
.B -a
option can be used to add additional arenas to an index.
To use this feature,
add the new arenas to
.I venti.config
after the existing arenas and then run
.I fmtindex
.BR -a .
.PP
A copy of the above mappings is stored in the header for each of the index sections.
These copies enable
.I buildindex
to restore a single index section without rebuilding the entire index.
.PP
.I Fmtisect
formats the given
.IR file ,
typically a disk partition, as a Venti index section with the specified
.IR name .
One or more formatted index sections are combined into a Venti
index using
.IR fmtindex .
Each of the index sections within an index must have a unique name.
.PP
Options to
.I fmtisect
are:
.TP
.BI -b " blocksize
The size, in bytes, for read and write operations to the file.
All the index sections within a index must have the same block size.
The default is 8k.
.TP
.B -Z
Do not zero the index.
Using this option reduces the formatting time
but should only be used when it is known that the file was already zeroed.
.PD
.PP
.I Rdarena
extracts the named
.I arena
from the arena partition
.I arenapart
and writes this arena to standard output.
This command is typically used to back up an arena to external media.
The
.B -v
option generates more verbose output on standard error.
.PP
.I Wrarena
writes the blocks contained in the arena
.I arenafile
(typically, the output of
.IR rdarena )
to a Venti server.
It is typically used to reinitialize a Venti server from backups of the arenas.
For example,
.IP
.EX
venti/rdarena /dev/sdC0/arenas arena.0 >external.media
venti/wrarena -h venti2 external.media
.EE
.LP
writes the blocks contained in
.B arena.0
to the Venti server
.B venti2
(typically not the one using
.BR /dev/sdC0/arenas ).
.PP
The
.B -o
option specifies that the arena starts at byte
.I fileoffset
(default
.BR 0 )
in
.I arenafile .
This is useful for reading directly from
the Venti arena partition:
.IP
.EX
venti/wrarena -h venti2 -o 335872 /dev/sdC0/arenas
.EE
.LP
(In this example, 335872 is the offset shown in the Venti
server's index list (344064) minus one block (8192).
You will need to substitute your own arena offsets
and block size.)
.PP
Finally, the optional
.I offset
argument specifies that the writing should begin with the
clump starting at
.I offset
within the arena.
.I Wrarena
prints the offset it stopped at (because there were no more data blocks).
This could be used to incrementally back up a Venti server
to another Venti server:
.IP
.EX
last=`{cat last}
venti/wrarena -h venti2 -o 335872 /dev/sdC0/arenas $last >output
awk '/^end offset/ { print $3 }' offset >last
.EE
.LP
Of course, one would need to add wrapper code to keep track
of which arenas have been processed.
See
.B /sys/src/cmd/venti/backup.example
for a version that does this.
.PP
.I Read
and
.I write
read and write blocks from a running Venti server.
They are intended to ease debugging of the server.
The default
.I host
is the environment variable
.BR $venti ,
followed by the network metaname
.BR $venti .
The
.I type
is the decimal type of block to be read or written.
If no
.I type
is specified for
.I read ,
all types are tried, and a command-line is printed to
show the type that eventually worked.
If no
.I type
is specified for
.I write ,
.B VtDataType
(13)
is used.
.I Read
reads the block named by
.I score
(a SHA1 hash)
from the Venti server and writes it to standard output.
.I Write
reads a block from standard input and attempts to write
it to the Venti server.
If successful, it prints the score of the block on the server.
.PP
.I Copy
walks the entire tree of blocks rooted at
.I score ,
copying all the blocks visited during the walk from
the Venti server at network address
.I src
to the Venti server at network address
.I dst .
If
.I type
(a decimal block type for
.IR score )
is omitted, all types will be tried in sequence
until one is found that works.
The
.B -f
flag runs the copy in ``fast'' mode: if a block is already on
.IR dst ,
the walk does not descend below it, on the assumption that all its
children are also already on
.IR dst .
Without this flag, the copy often transfers many times more
data than necessary.
.PP
To make it easier to bootstrap servers, the configuration
file can be stored at the beginning of any Venti partitions using
.IR conf .
A partition so branded with a configuration file can
be used in place of a configuration file when invoking any
of the venti commands.
By default,
.I conf
prints the configuration stored in
.IR partition .
When invoked with the
.B -w
flag,
.I conf
reads a configuration file from
.I configfile
(or else standard input)
and stores it in
.IR partition .
.SH SOURCE
.B /sys/src/cmd/venti
.SH "SEE ALSO"
.IR venti (8),
.IR venti.conf (6)
.SH BUGS
.I Buildindex
should allow an individual index section to be rebuilt.
The merge sort could be performed in the space used to store the
index rather than requiring a temporary file.

2
sky/.cvsignore Normal file
View file

@ -0,0 +1,2 @@
*.scat
constelnames

View file

@ -1308,7 +1308,7 @@ runproc(void *argvp)
name[e-t] = 0;
e = utfrrune(name, '/');
if(e)
strcpy(name, e+1);
memmove(name, e+1, strlen(e+1)+1); /* strcpy but overlaps */
strcat(name, " "); /* add blank here for ease in waittask */
c->name = bytetorune(name, &c->nname);
free(name);

View file

@ -663,12 +663,12 @@ rowload(Row *row, char *file, int initing)
break;
wincleartag(w);
textinsert(&w->tag, w->tag.file->b.nc, r+n+1, nr-(n+1), TRUE);
free(r);
if(ndumped >= 0){
/* simplest thing is to put it in a file and load that */
sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser());
fd = create(buf, OWRITE|ORCLOSE, 0600);
if(fd < 0){
free(r);
warning(nil, "can't create temp file: %r\n");
goto Rescue2;
}
@ -679,6 +679,7 @@ rowload(Row *row, char *file, int initing)
if(rune == '\n')
line++;
if(rune == (Rune)Beof){
free(r);
Bterm(bout);
free(bout);
close(fd);
@ -696,6 +697,7 @@ rowload(Row *row, char *file, int initing)
winsettag(w);
}else if(dumpid==0 && r[ns+1]!='+' && r[ns+1]!='-')
get(&w->body, nil, nil, FALSE, XXX, nil, 0);
free(r);
if(fontr){
fontx(&w->body, nil, nil, 0, 0, fontr, nfontr);
free(fontr);

View file

@ -963,8 +963,11 @@ textshow(Text *t, uint q0, uint q1, int doselect)
int nl;
uint q;
if(t->what != Body)
if(t->what != Body){
if(doselect)
textsetselect(t, q0, q1);
return;
}
if(t->w!=nil && t->fr.maxlines==0)
colgrow(t->col, t->w, 1);
if(doselect)

167
src/lib9/rendez-futex.c Normal file
View file

@ -0,0 +1,167 @@
/*
NAME
rendezvous - user level process synchronization
SYNOPSIS
ulong rendezvous(ulong tag, ulong value)
DESCRIPTION
The rendezvous system call allows two processes to synchro-
nize and exchange a value. In conjunction with the shared
memory system calls (see segattach(2) and fork(2)), it
enables parallel programs to control their scheduling.
Two processes wishing to synchronize call rendezvous with a
common tag, typically an address in memory they share. One
process will arrive at the rendezvous first; it suspends
execution until a second arrives. When a second process
meets the rendezvous the value arguments are exchanged
between the processes and returned as the result of the
respective rendezvous system calls. Both processes are
awakened when the rendezvous succeeds.
The set of tag values which two processes may use to
rendezvous-their tag space-is inherited when a process
forks, unless RFREND is set in the argument to rfork; see
fork(2).
If a rendezvous is interrupted the return value is ~0, so
that value should not be used in normal communication.
* This simulates rendezvous with shared memory, pause, and SIGUSR1.
*/
#include <u.h>
typedef u32int u32;
#include <errno.h>
#include <sys/time.h>
#define __user
#include <linux/linkage.h>
#include <linux/futex.h>
#include <libc.h>
enum
{
VOUSHASH = 257,
};
typedef struct Vous Vous;
struct Vous
{
Vous *link;
Lock lk;
int pid;
ulong val;
ulong tag;
};
static Vous vouspool[2048];
static int nvousused;
static Vous *vousfree;
static Vous *voushash[VOUSHASH];
static Lock vouslock;
static Vous*
getvous(void)
{
Vous *v;
if(vousfree){
v = vousfree;
vousfree = v->link;
}else if(nvousused < nelem(vouspool))
v = &vouspool[nvousused++];
else
abort();
return v;
}
static void
putvous(Vous *v)
{
lock(&vouslock);
v->link = vousfree;
vousfree = v;
unlock(&vouslock);
}
static Vous*
findvous(ulong tag, ulong val, int pid)
{
int h;
Vous *v, **l;
lock(&vouslock);
h = tag%VOUSHASH;
for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
if(v->tag == tag){
*l = v->link;
unlock(&vouslock);
return v;
}
}
v = getvous();
v->pid = pid;
v->link = voushash[h];
v->val = val;
v->tag = tag;
lock(&v->lk);
voushash[h] = v;
unlock(&vouslock);
return v;
}
#define DBG 0
ulong
rendezvous(ulong tag, ulong val)
{
int me, vpid;
ulong rval;
Vous *v;
me = getpid();
v = findvous(tag, val, me);
if(v->pid == me){
if(DBG)fprint(2, "pid is %d tag %lux, sleeping\n", me, tag);
/*
* No rendezvous partner was found; the next guy
* through will find v and wake us, so we must go
* to sleep.
*
* To go to sleep:
* 1. disable USR1 signals.
* 2. unlock v->lk (tells waker okay to signal us).
* 3. atomically suspend and enable USR1 signals.
*
* The call to ignusr1() could be done once at
* process creation instead of every time through rendezvous.
*/
v->val = val;
unlock(&v->lk);
while(sys_futex((u32int*)&v->tag, FUTEX_WAIT, tag, nil, nil) < 0 && errno==EINTR)
;
rval = v->val;
if(DBG)fprint(2, "pid is %d, awake\n", me);
putvous(v);
}else{
/*
* Found someone to meet. Wake him:
*
* A. lock v->lk (waits for him to get to his step 2)
* B. send a USR1
*
* He won't get the USR1 until he suspends, which
* means it must wake him up (it can't get delivered
* before he sleeps).
*/
vpid = v->pid;
lock(&v->lk);
rval = v->val;
v->val = val;
v->tag++;
unlock(&v->lk);
sys_futex((u32int*)&v->tag, FUTEX_WAKE, 1, nil, nil);
}
return rval;
}

View file

@ -86,7 +86,13 @@ _allocmemimage(Rectangle r, u32int chan)
return nil;
md->ref = 1;
md->base = poolalloc(imagmem, (2+nw)*sizeof(u32int));
/*
* The first two words are the md and the callerpc.
* Then nw words of data.
* The final word lets the drawing routines be a little
* sloppy about reading past the end of the block.
*/
md->base = poolalloc(imagmem, (2+nw+1)*sizeof(u32int));
if(md->base == nil){
free(md);
return nil;

View file

@ -86,19 +86,27 @@ fsunmount(Fsys *fs)
void
_fsdecref(Fsys *fs)
{
Fid *f, *next;
Fid *f, **l, *next;
qlock(&fs->lk);
--fs->ref;
//fprint(2, "fsdecref %p to %d\n", fs, fs->ref);
if(fs->ref == 0){
close(fs->fd);
/* trim the list down to just the first in each chunk */
for(l=&fs->freefid; *l; ){
if((*l)->fid%Fidchunk == 0)
l = &(*l)->next;
else
*l = (*l)->next;
}
/* now free the list */
for(f=fs->freefid; f; f=next){
next = f->next;
if(f->fid%Fidchunk == 0)
free(f);
free(f);
}
free(fs);
return;
}
qunlock(&fs->lk);
}

View file

@ -23,8 +23,11 @@ nsmount(char *name, char *aname)
fd = dial(addr, 0, 0, 0);
if(fd < 0){
werrstr("dial %s: %r", addr);
free(addr);
return nil;
}
free(addr);
fcntl(fd, F_SETFL, FD_CLOEXEC);
fs = fsmount(fd, aname);

View file

@ -174,8 +174,8 @@ _threadfdwait(int fd, int rw, ulong pc)
struct {
Channel c;
Alt *qentry[2];
ulong x;
Alt *qentry[2];
} s;
threadfdwaitsetup();
@ -214,11 +214,15 @@ threadsleep(int ms)
struct {
Channel c;
ulong x;
Alt *qentry[2];
} s;
threadfdwaitsetup();
chaninit(&s.c, sizeof(ulong), 1);
s.c.qentry = (volatile Alt**)s.qentry;
s.c.nentry = 2;
memset(s.qentry, 0, sizeof s.qentry);
sleepchan[nsleep] = &s.c;
sleeptime[nsleep++] = p9nsec()/1000000+ms;
recvul(&s.c);