(once again in the right place)
initial import of pigz 2.1.6 sources. from http://www.zlib.net/pigz/: """ pigz, which stands for parallel implementation of gzip, is a fully functional replacement for gzip that exploits multiple processors and multiple cores to the hilt when compressing data. pigz was written by Mark Adler, and uses the zlib and pthread libraries. How is it pronounced? I'm glad you asked. It is pronounced "pig-zee". It is not pronounced like the plural of pig. """ once i am done adding bz2 support to pigz, i plan to obsolete my usr.bin/gzip.
This commit is contained in:
parent
bfe3cf1b4b
commit
e25fdb51d0
|
@ -0,0 +1,47 @@
|
|||
CFLAGS=-O3
|
||||
|
||||
pigz: pigz.o yarn.o
|
||||
cc -o pigz pigz.o yarn.o -lpthread -lz
|
||||
ln -f pigz unpigz
|
||||
|
||||
pigz.o: pigz.c yarn.h
|
||||
|
||||
yarn.o: yarn.c yarn.h
|
||||
|
||||
dev: pigz pigzt pigzn
|
||||
|
||||
pigzt: pigzt.o yarnt.o
|
||||
cc -o pigzt pigzt.o yarnt.o -lpthread -lz
|
||||
|
||||
pigzt.o: pigz.c yarn.h
|
||||
cc -Wall -O3 -DDEBUG -g -c -o pigzt.o pigz.c
|
||||
|
||||
yarnt.o: yarn.c yarn.h
|
||||
cc -Wall -O3 -DDEBUG -g -c -o yarnt.o yarn.c
|
||||
|
||||
pigzn: pigzn.o
|
||||
cc -o pigzn pigzn.o -lz
|
||||
|
||||
pigzn.o: pigz.c
|
||||
cc -Wall -O3 -DDEBUG -DNOTHREAD -g -c -o pigzn.o pigz.c
|
||||
|
||||
test: pigz
|
||||
./pigz -kf pigz.c ; ./pigz -t pigz.c.gz
|
||||
./pigz -kfb 32 pigz.c ; ./pigz -t pigz.c.gz
|
||||
./pigz -kfp 1 pigz.c ; ./pigz -t pigz.c.gz
|
||||
./pigz -kfz pigz.c ; ./pigz -t pigz.c.zz
|
||||
./pigz -kfK pigz.c ; ./pigz -t pigz.c.zip
|
||||
compress -f < pigz.c | ./unpigz | cmp - pigz.c
|
||||
rm -f pigz.c.gz pigz.c.zz pigz.c.zip
|
||||
|
||||
tests: dev test
|
||||
./pigzn -kf pigz.c ; ./pigz -t pigz.c.gz
|
||||
rm -f pigz.c.gz
|
||||
|
||||
docs: pigz.pdf
|
||||
|
||||
pigz.pdf: pigz.1
|
||||
groff -mandoc -f H -T ps pigz.1 | ps2pdf - pigz.pdf
|
||||
|
||||
clean:
|
||||
rm -f *.o pigz unpigz pigzn pigzt pigz.c.gz pigz.c.zz pigz.c.zip
|
|
@ -0,0 +1,48 @@
|
|||
pigz 2.1.6 (17 Jan 2010) by Mark Adler
|
||||
|
||||
pigz, which stands for Parallel Implementation of GZip, is a fully functional
|
||||
replacement for gzip that exploits multiple processors and multiple cores to
|
||||
the hilt when compressing data.
|
||||
|
||||
pigz was written by Mark Adler, and uses the zlib and pthread libraries.
|
||||
|
||||
This version of pigz is written to be portable across Unix-style operating
|
||||
systems that provide the zlib and pthread libraries.
|
||||
|
||||
Type "make" in this directory to build the "pigz" executable. You can then
|
||||
install the executable wherever you like in your path (e.g. /usr/local/bin/).
|
||||
Type "pigz" to see the command help and all of the command options.
|
||||
|
||||
The latest version of pigz can be found at http://zlib.net/pigz/ . You need
|
||||
zlib version 1.2.3 or later to compile pigz. You can find the latest version
|
||||
of zlib at http://zlib.net/ . You can look in pigz.c for the change history.
|
||||
|
||||
Questions, comments, bug reports, fixes, etc. can be emailed to Mark at his
|
||||
address in the license below.
|
||||
|
||||
The license from pigz.c is copied here:
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Mark Adler
|
||||
madler@alumni.caltech.edu
|
||||
|
||||
Mark accepts donations for providing this software. Donations are not
|
||||
required or expected. Any amount that you feel is appropriate would be
|
||||
appreciated. You can use this link:
|
||||
|
||||
https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=536055
|
|
@ -0,0 +1,187 @@
|
|||
.TH PIGZ 1 local
|
||||
.SH NAME
|
||||
pigz, unpigz \- compress or expand files
|
||||
.SH SYNOPSIS
|
||||
.ll +8
|
||||
.B pigz
|
||||
.RB [ " \-cdfhikKlLnNqrRtTz0..9 " ]
|
||||
[
|
||||
.B -b
|
||||
.I blocksize
|
||||
]
|
||||
[
|
||||
.B -p
|
||||
.I threads
|
||||
]
|
||||
[
|
||||
.B -S
|
||||
.I suffix
|
||||
]
|
||||
[
|
||||
.I "name \&..."
|
||||
]
|
||||
.ll -8
|
||||
.br
|
||||
.B unpigz
|
||||
.RB [ " \-cfhikKlLnNqrRtTz " ]
|
||||
[
|
||||
.B -b
|
||||
.I blocksize
|
||||
]
|
||||
[
|
||||
.B -p
|
||||
.I threads
|
||||
]
|
||||
[
|
||||
.B -S
|
||||
.I suffix
|
||||
]
|
||||
[
|
||||
.I "name \&..."
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.I Pigz
|
||||
compresses using threads to make use of multiple processors and cores.
|
||||
The input is broken up into 128 KB chunks with each compressed in parallel.
|
||||
The individual check value for each chunk is also calculated in parallel.
|
||||
The compressed data is written in order to the output, and a combined check
|
||||
value is calculated from the individual check values.
|
||||
.PP
|
||||
The compressed data format generated is in the gzip, zlib, or single-entry
|
||||
zip format using the deflate compression method. The compression produces
|
||||
partial raw deflate streams which are concatenated by a single write thread
|
||||
and wrapped with the appropriate header and trailer, where the trailer
|
||||
contains the combined check value.
|
||||
.PP
|
||||
Each partial raw deflate stream is terminated by an empty stored block
|
||||
(using the Z_SYNC_FLUSH option of zlib), in order to end that partial bit
|
||||
stream at a byte boundary. That allows the partial streams to be
|
||||
concatenated simply as sequences of bytes. This adds a very small four to
|
||||
five byte overhead to the output for each input chunk.
|
||||
.PP
|
||||
The default input block size is 128K, but can be changed with the
|
||||
.B -b
|
||||
option. The number of compress threads is set by default to the number
|
||||
of online processors,
|
||||
which can be changed using the
|
||||
.B -p
|
||||
option. Specifying
|
||||
.B -p 1
|
||||
avoids the use of threads entirely.
|
||||
.PP
|
||||
The input blocks, while compressed independently, have the last 32K of the
|
||||
previous block loaded as a preset dictionary to preserve the compression
|
||||
effectiveness of deflating in a single thread. This can be turned off using
|
||||
the
|
||||
.B -i
|
||||
or
|
||||
.B --independent
|
||||
option, so that the blocks can be decompressed
|
||||
independently for partial error recovery or for random access.
|
||||
.PP
|
||||
Decompression can't be parallelized, at least not without specially prepared
|
||||
deflate streams for that purpose. As a result,
|
||||
.I pigz
|
||||
uses a single thread
|
||||
(the main thread) for decompression, but will create three other threads for
|
||||
reading, writing, and check calculation, which can speed up decompression
|
||||
under some circumstances. Parallel decompression can be turned off by
|
||||
specifying one process
|
||||
(
|
||||
.B -dp 1
|
||||
or
|
||||
.B -tp 1
|
||||
).
|
||||
.PP
|
||||
Compressed files can be restored to their original form using
|
||||
.I pigz -d
|
||||
or
|
||||
.I unpigz.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.B -# --fast --best
|
||||
Regulate the speed of compression using the specified digit
|
||||
.IR # ,
|
||||
where
|
||||
.B \-1
|
||||
or
|
||||
.B \-\-fast
|
||||
indicates the fastest compression method (less compression)
|
||||
and
|
||||
.B \-9
|
||||
or
|
||||
.B \-\-best
|
||||
indicates the slowest compression method (best compression).
|
||||
Level 0 is no compression.
|
||||
.TP
|
||||
.B -b --blocksize mmm
|
||||
Set compression block size to mmmK (default 128KiB).
|
||||
.TP
|
||||
.B -c --stdout --to-stdout
|
||||
Write all processed output to stdout (won't delete).
|
||||
.TP
|
||||
.B -d --decompress --uncompress
|
||||
Decompress the compressed input.
|
||||
.TP
|
||||
.B -f --force
|
||||
Force overwrite, compress .gz, links, and to terminal.
|
||||
.TP
|
||||
.B -h --help
|
||||
Display a help screen and quit.
|
||||
.TP
|
||||
.B -i --independent
|
||||
Compress blocks independently for damage recovery.
|
||||
.TP
|
||||
.B -k --keep
|
||||
Do not delete original file after processing.
|
||||
.TP
|
||||
.B -K --zip
|
||||
Compress to PKWare zip (.zip) single entry format.
|
||||
.TP
|
||||
.B -l --list
|
||||
List the contents of the compressed input.
|
||||
.TP
|
||||
.B -L --license
|
||||
Display the
|
||||
.I pigz
|
||||
license and quit.
|
||||
.TP
|
||||
.B -n --no-name
|
||||
Do not store or restore file name in/from header.
|
||||
.TP
|
||||
.B -N --name
|
||||
Store/restore file name and mod time in/from header.
|
||||
.TP
|
||||
.B -p --processes n
|
||||
Allow up to n processes (default is the number of online processors)
|
||||
.TP
|
||||
.B -q --quiet --silent
|
||||
Print no messages, even on error.
|
||||
.TP
|
||||
.B -r --recursive
|
||||
Process the contents of all subdirectories.
|
||||
.TP
|
||||
.B -S --suffix .sss
|
||||
Use suffix .sss instead of .gz (for compression).
|
||||
.TP
|
||||
.B -t --test
|
||||
Test the integrity of the compressed input.
|
||||
.TP
|
||||
.B -T --no-time
|
||||
Do not store or restore mod time in/from header.
|
||||
.TP
|
||||
.B -v --verbose
|
||||
Provide more verbose output.
|
||||
.TP
|
||||
.B -V --version
|
||||
Show the version of pigz.
|
||||
.TP
|
||||
.B -z --zlib
|
||||
Compress to zlib (.zz) instead of gzip format.
|
||||
.SH "COPYRIGHT NOTICE"
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
.PP
|
||||
Copyright (C) 2007, 2008, 2009, 2010 Mark Adler <madler@alumni.caltech.edu>
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -0,0 +1,379 @@
|
|||
%!PS-Adobe-3.0
|
||||
%%Creator: groff version 1.19.2
|
||||
%%CreationDate: Sun Jan 17 12:33:29 2010
|
||||
%%DocumentNeededResources: font Helvetica
|
||||
%%+ font Helvetica-Bold
|
||||
%%+ font Helvetica-Oblique
|
||||
%%DocumentSuppliedResources: procset grops 1.19 2
|
||||
%%Pages: 2
|
||||
%%PageOrder: Ascend
|
||||
%%DocumentMedia: Default 595 842 0 () ()
|
||||
%%Orientation: Portrait
|
||||
%%EndComments
|
||||
%%BeginDefaults
|
||||
%%PageMedia: Default
|
||||
%%EndDefaults
|
||||
%%BeginProlog
|
||||
%%BeginResource: procset grops 1.19 2
|
||||
%!PS-Adobe-3.0 Resource-ProcSet
|
||||
/setpacking where{
|
||||
pop
|
||||
currentpacking
|
||||
true setpacking
|
||||
}if
|
||||
/grops 120 dict dup begin
|
||||
/SC 32 def
|
||||
/A/show load def
|
||||
/B{0 SC 3 -1 roll widthshow}bind def
|
||||
/C{0 exch ashow}bind def
|
||||
/D{0 exch 0 SC 5 2 roll awidthshow}bind def
|
||||
/E{0 rmoveto show}bind def
|
||||
/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
|
||||
/G{0 rmoveto 0 exch ashow}bind def
|
||||
/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
|
||||
/I{0 exch rmoveto show}bind def
|
||||
/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
|
||||
/K{0 exch rmoveto 0 exch ashow}bind def
|
||||
/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
|
||||
/M{rmoveto show}bind def
|
||||
/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
|
||||
/O{rmoveto 0 exch ashow}bind def
|
||||
/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
|
||||
/Q{moveto show}bind def
|
||||
/R{moveto 0 SC 3 -1 roll widthshow}bind def
|
||||
/S{moveto 0 exch ashow}bind def
|
||||
/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
|
||||
/SF{
|
||||
findfont exch
|
||||
[exch dup 0 exch 0 exch neg 0 0]makefont
|
||||
dup setfont
|
||||
[exch/setfont cvx]cvx bind def
|
||||
}bind def
|
||||
/MF{
|
||||
findfont
|
||||
[5 2 roll
|
||||
0 3 1 roll
|
||||
neg 0 0]makefont
|
||||
dup setfont
|
||||
[exch/setfont cvx]cvx bind def
|
||||
}bind def
|
||||
/level0 0 def
|
||||
/RES 0 def
|
||||
/PL 0 def
|
||||
/LS 0 def
|
||||
/MANUAL{
|
||||
statusdict begin/manualfeed true store end
|
||||
}bind def
|
||||
/PLG{
|
||||
gsave newpath clippath pathbbox grestore
|
||||
exch pop add exch pop
|
||||
}bind def
|
||||
/BP{
|
||||
/level0 save def
|
||||
1 setlinecap
|
||||
1 setlinejoin
|
||||
72 RES div dup scale
|
||||
LS{
|
||||
90 rotate
|
||||
}{
|
||||
0 PL translate
|
||||
}ifelse
|
||||
1 -1 scale
|
||||
}bind def
|
||||
/EP{
|
||||
level0 restore
|
||||
showpage
|
||||
}def
|
||||
/DA{
|
||||
newpath arcn stroke
|
||||
}bind def
|
||||
/SN{
|
||||
transform
|
||||
.25 sub exch .25 sub exch
|
||||
round .25 add exch round .25 add exch
|
||||
itransform
|
||||
}bind def
|
||||
/DL{
|
||||
SN
|
||||
moveto
|
||||
SN
|
||||
lineto stroke
|
||||
}bind def
|
||||
/DC{
|
||||
newpath 0 360 arc closepath
|
||||
}bind def
|
||||
/TM matrix def
|
||||
/DE{
|
||||
TM currentmatrix pop
|
||||
translate scale newpath 0 0 .5 0 360 arc closepath
|
||||
TM setmatrix
|
||||
}bind def
|
||||
/RC/rcurveto load def
|
||||
/RL/rlineto load def
|
||||
/ST/stroke load def
|
||||
/MT/moveto load def
|
||||
/CL/closepath load def
|
||||
/Fr{
|
||||
setrgbcolor fill
|
||||
}bind def
|
||||
/setcmykcolor where{
|
||||
pop
|
||||
/Fk{
|
||||
setcmykcolor fill
|
||||
}bind def
|
||||
}if
|
||||
/Fg{
|
||||
setgray fill
|
||||
}bind def
|
||||
/FL/fill load def
|
||||
/LW/setlinewidth load def
|
||||
/Cr/setrgbcolor load def
|
||||
/setcmykcolor where{
|
||||
pop
|
||||
/Ck/setcmykcolor load def
|
||||
}if
|
||||
/Cg/setgray load def
|
||||
/RE{
|
||||
findfont
|
||||
dup maxlength 1 index/FontName known not{1 add}if dict begin
|
||||
{
|
||||
1 index/FID ne{def}{pop pop}ifelse
|
||||
}forall
|
||||
/Encoding exch def
|
||||
dup/FontName exch def
|
||||
currentdict end definefont pop
|
||||
}bind def
|
||||
/DEFS 0 def
|
||||
/EBEGIN{
|
||||
moveto
|
||||
DEFS begin
|
||||
}bind def
|
||||
/EEND/end load def
|
||||
/CNT 0 def
|
||||
/level1 0 def
|
||||
/PBEGIN{
|
||||
/level1 save def
|
||||
translate
|
||||
div 3 1 roll div exch scale
|
||||
neg exch neg exch translate
|
||||
0 setgray
|
||||
0 setlinecap
|
||||
1 setlinewidth
|
||||
0 setlinejoin
|
||||
10 setmiterlimit
|
||||
[]0 setdash
|
||||
/setstrokeadjust where{
|
||||
pop
|
||||
false setstrokeadjust
|
||||
}if
|
||||
/setoverprint where{
|
||||
pop
|
||||
false setoverprint
|
||||
}if
|
||||
newpath
|
||||
/CNT countdictstack def
|
||||
userdict begin
|
||||
/showpage{}def
|
||||
/setpagedevice{}def
|
||||
}bind def
|
||||
/PEND{
|
||||
countdictstack CNT sub{end}repeat
|
||||
level1 restore
|
||||
}bind def
|
||||
end def
|
||||
/setpacking where{
|
||||
pop
|
||||
setpacking
|
||||
}if
|
||||
%%EndResource
|
||||
%%EndProlog
|
||||
%%BeginSetup
|
||||
%%BeginFeature: *PageSize Default
|
||||
<< /PageSize [ 595 842 ] /ImagingBBox null >> setpagedevice
|
||||
%%EndFeature
|
||||
%%IncludeResource: font Helvetica
|
||||
%%IncludeResource: font Helvetica-Bold
|
||||
%%IncludeResource: font Helvetica-Oblique
|
||||
grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
|
||||
def/PL 841.89 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron
|
||||
/Zcaron/scaron/zcaron/Ydieresis/trademark/quotesingle/Euro/.notdef
|
||||
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
|
||||
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
|
||||
/.notdef/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
|
||||
/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
|
||||
/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
|
||||
/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
|
||||
/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
|
||||
/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
|
||||
/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
|
||||
/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
|
||||
/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
|
||||
/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
|
||||
/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
|
||||
/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
|
||||
/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
|
||||
/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
|
||||
/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
|
||||
/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
|
||||
/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
|
||||
/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
|
||||
/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
|
||||
/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
|
||||
/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
|
||||
/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
|
||||
/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
|
||||
/Helvetica-Oblique@0 ENC0/Helvetica-Oblique RE/Helvetica-Bold@0 ENC0
|
||||
/Helvetica-Bold RE/Helvetica@0 ENC0/Helvetica RE
|
||||
%%EndSetup
|
||||
%%Page: 1 1
|
||||
%%BeginPageSetup
|
||||
BP
|
||||
%%EndPageSetup
|
||||
/F0 10/Helvetica@0 SF 394.1(PIGZ\(1\) PIGZ\(1\))72 48 R/F1 10.95
|
||||
/Helvetica-Bold@0 SF(NAME)72 84 Q F0(pigz, unpigz \255 compress or e)108
|
||||
96 Q(xpand \214les)-.3 E F1(SYNOPSIS)72 112.8 Q/F2 10/Helvetica-Bold@0
|
||||
SF(pigz)108 124.8 Q F0([)2.78 E F2(\255cdfhikKlLnNqrRtTz0..9)2.78 E F0
|
||||
2.78(][)2.78 G F2(-b)A/F3 10/Helvetica-Oblique@0 SF -.2(bl)2.78 G(oc).2
|
||||
E(ksiz)-.2 E(e)-.15 E F0 2.78(][)3.5 G F2(-p)A F3(threads)2.26 E F0 2.78
|
||||
(][)3.57 G F2(-S)A F3(suf\214x)2.65 E F0 2.78(][)4.22 G F3(name ...)-.15
|
||||
E F0(])5.56 E F2(unpigz)108 136.8 Q F0([)2.78 E F2(\255cfhikKlLnNqrRtTz)
|
||||
2.78 E F0 2.78(][)2.78 G F2(-b)A F3 -.2(bl)2.78 G(oc).2 E(ksiz)-.2 E(e)
|
||||
-.15 E F0 2.78(][)3.5 G F2(-p)A F3(threads)2.26 E F0 2.78(][)3.57 G F2
|
||||
(-S)A F3(suf\214x)2.65 E F0 2.78(][)4.22 G F3(name ...)-.15 E F0(])5.56
|
||||
E F1(DESCRIPTION)72 153.6 Q F3(Pigz)107.64 165.6 Q F0 .54
|
||||
(compresses using threads to mak)4.53 F 3.32(eu)-.2 G .54(se of m)-3.32
|
||||
F .54(ultiple processors and cores)-.1 F 6.1(.T)-.15 G .54
|
||||
(he input is bro-)-6.1 F -.2(ke)108 177.6 S 2.888(nu).2 G 2.888(pi)
|
||||
-2.888 G .109(nto 128 KB chunks with each compressed in par)-2.888 F
|
||||
2.889(allel. The)-.1 F .109(individual chec)2.889 F 2.889(kv)-.2 G .109
|
||||
(alue f)-3.139 F .109(or each)-.3 F .463
|
||||
(chunk is also calculated in par)108 189.6 R 3.243(allel. The)-.1 F .462
|
||||
(compressed data is wr)3.242 F .462(itten in order to the output, and a)
|
||||
.15 F(combined chec)108 201.6 Q 2.78(kv)-.2 G
|
||||
(alue is calculated from the individual chec)-3.03 E 2.78(kv)-.2 G
|
||||
(alues)-3.03 E(.)-.15 E 1.276(The compressed data f)108 218.4 R -2.53
|
||||
(or mat)-.3 F(gener)4.056 E 1.276(ated is in the gzip)-.1 F 4.056(,z)
|
||||
-.35 G(lib)-4.056 E 4.056(,o)-.4 G 4.056(rs)-4.056 G -2.48(ingle-entr y)
|
||||
-4.056 F 1.276(zip f)4.056 F -2.53(or mat)-.3 F 1.276(using the)4.056 F
|
||||
1.068(de\215ate compression method.)108 230.4 R 1.067
|
||||
(The compression produces par)6.628 F 1.067(tial r).4 F 1.467 -.2(aw d)
|
||||
-.1 H 1.067(e\215ate streams which are).2 F .13(concatenated b)108 242.4
|
||||
R 2.91(yas)-.2 G .13(ingle wr)-2.91 F .131(ite thread and wr).15 F .131
|
||||
(apped with the appropr)-.1 F .131(iate header and tr).15 F(ailer)-.1 E
|
||||
2.911(,w)-.5 G(here)-2.911 E(the tr)108 254.4 Q
|
||||
(ailer contains the combined chec)-.1 E 2.78(kv)-.2 G(alue)-3.03 E(.)
|
||||
-.15 E 5.675(Each par)108 271.2 R 5.675(tial r).4 F 6.075 -.2(aw d)-.1 H
|
||||
5.675(e\215ate stream is ter).2 F 5.675(minated b).25 F 8.455(ya)-.2 G
|
||||
8.454(ne)-8.455 G 5.674(mpty stored b)-8.454 F(loc)-.2 E 8.454(k\()-.2 G
|
||||
5.674(using the)-8.454 F .769
|
||||
(Z_SYNC_FLUSH option of zlib\), in order to end that par)108 283.2 R .77
|
||||
(tial bit stream at a b).4 F .77(yte boundar)-.2 F 5.55 -1(y. T).3 H
|
||||
(hat)1 E(allo)108 295.2 Q 1.088(ws the par)-.15 F 1.087
|
||||
(tial streams to be concatenated simply as sequences of b).4 F(ytes)-.2
|
||||
E 6.647(.T)-.15 G 1.087(his adds a v)-6.647 F -2.48(er y)-.25 F(small f)
|
||||
108 307.2 Q(our to \214v)-.3 E 2.78(eb)-.25 G(yte o)-2.98 E -.25(ve)-.15
|
||||
G(rhead to the output f).25 E(or each input chunk.)-.3 E .255(The def)
|
||||
108 324 R .255(ault input b)-.3 F(loc)-.2 E 3.035(ks)-.2 G(iz)-3.035 E
|
||||
3.035(ei)-.15 G 3.035(s1)-3.035 G .255(28K, b)-3.035 F .256
|
||||
(ut can be changed with the)-.2 F F2(-b)3.036 E F0 3.036(option. The)
|
||||
3.036 F -.1(nu)3.036 G .256(mber of com-).1 F .807
|
||||
(press threads is set b)108 336 R 3.586(yd)-.2 G(ef)-3.586 E .806
|
||||
(ault to 4, which can be changed using the)-.3 F F2(-p)3.586 E F0 3.586
|
||||
(option. Specifying)3.586 F F2 .806(-p 1)3.586 F F0 -.2(av)108 348 S
|
||||
(oids the use of threads entirely)-.05 E(.)-1 E .082(The input b)108
|
||||
364.8 R(loc)-.2 E(ks)-.2 E 2.862(,w)-.15 G .082
|
||||
(hile compressed independently)-2.862 F 2.862(,h)-1 G -.2(av)-2.862 G
|
||||
2.862(et)-.05 G .082(he last 32K of the pre)-2.862 F .083(vious b)-.3 F
|
||||
(loc)-.2 E 2.863(kl)-.2 G(oaded)-2.863 E .977(as a preset dictionar)108
|
||||
376.8 R 3.757(yt).3 G 3.757(op)-3.757 G -2.48(reser v)-3.757 F 3.757(et)
|
||||
-.25 G .976(he compression eff)-3.757 F(ectiv)-.3 E .976
|
||||
(eness of de\215ating in a single thread.)-.25 F 1.194(This can be tur)
|
||||
108 388.8 R 1.194(ned off using the).25 F F2(-i)3.974 E F0(or)3.974 E F2
|
||||
(--independent)3.974 E F0 1.194(option, so that the b)3.974 F(loc)-.2 E
|
||||
1.195(ks can be decom-)-.2 F(pressed independently f)108 400.8 Q(or par)
|
||||
-.3 E(tial error reco).4 E -.25(ve)-.15 G -.6 .3(ry o).25 H 2.78(rf)-.3
|
||||
G(or r)-3.08 E(andom access)-.1 E(.)-.15 E 1.125
|
||||
(Decompression can't be par)108 417.6 R(alleliz)-.1 E 1.124
|
||||
(ed, at least not without specially prepared de\215ate streams f)-.15 F
|
||||
(or)-.3 E .21(that pur)108 429.6 R(pose).3 E 5.77(.A)-.15 G 2.99(sar)
|
||||
-5.77 G(esult,)-2.99 E F3(pigz)3.35 E F0 .211
|
||||
(uses a single thread \(the main thread\) f)4.2 F .211
|
||||
(or decompression, b)-.3 F .211(ut will)-.2 F .075
|
||||
(create three other threads f)108 441.6 R .074(or reading, wr)-.3 F .074
|
||||
(iting, and chec).15 F 2.854(kc)-.2 G .074
|
||||
(alculation, which can speed up decom-)-2.854 F .201
|
||||
(pression under some circumstances)108 453.6 R 5.761(.P)-.15 G(ar)-6.161
|
||||
E .202(allel decompression can be tur)-.1 F .202(ned off b).25 F 2.982
|
||||
(ys)-.2 G .202(pecifying one)-2.982 F(process \()108 465.6 Q F2(-dp 1)
|
||||
2.78 E F0(or)2.78 E F2(-tp 1)2.78 E F0(\).)2.78 E
|
||||
(Compressed \214les can be restored to their or)108 482.4 Q(iginal f).15
|
||||
E -2.53(or m)-.3 F(using)2.78 E F3(pigz -d)3.14 E F0(or)4.24 E F3
|
||||
(unpigz.)2.34 E F1(OPTIONS)72 511.2 Q F2(-# --fast --best)108 523.2 Q F0
|
||||
.703(Regulate the speed of compression using the speci\214ed digit)144
|
||||
535.2 R F3(#)3.483 E F0 3.483(,w)1.25 G(here)-3.483 E F2<ad31>3.483 E F0
|
||||
(or)3.483 E F2(\255\255fast)3.482 E F0(indi-)3.482 E .163(cates the f)
|
||||
144 547.2 R .163(astest compression method \(less compression\) and)-.3
|
||||
F F2<ad39>2.943 E F0(or)2.944 E F2(\255\255best)2.944 E F0 .164
|
||||
(indicates the)2.944 F(slo)144 559.2 Q -.1(we)-.15 G
|
||||
(st compression method \(best compression\).).1 E(Le)5.56 E -.25(ve)-.3
|
||||
G 2.78(l0i).25 G 2.78(sn)-2.78 G 2.78(oc)-2.78 G(ompression.)-2.78 E F2
|
||||
(-b --b)108 576 Q(loc)-.1 E -2.68(ksiz e)-.2 F(mmm)2.78 E F0
|
||||
(Set compression b)144 588 Q(loc)-.2 E 2.78(ks)-.2 G(iz)-2.78 E 2.78(et)
|
||||
-.15 G 2.78(om)-2.78 G(mmK \(def)-2.78 E(ault 128KiB\).)-.3 E F2
|
||||
(-c --stdout --to-stdout)108 604.8 Q F0 -2.63(Wr ite)144 616.8 R
|
||||
(all processed output to stdout \(w)2.78 E(on't delete\).)-.1 E F2
|
||||
(-d --decompress --uncompress)108 633.6 Q F0
|
||||
(Decompress the compressed input.)144 645.6 Q F2(-f --f)108 662.4 Q(or)
|
||||
-.2 E(ce)-.2 E F0 -.3(Fo)144 674.4 S(rce o).3 E -.25(ve)-.15 G -2.63
|
||||
(rwr ite).25 F 2.78(,c)-.15 G(ompress .gz, links)-2.78 E 2.78(,a)-.15 G
|
||||
(nd to ter)-2.78 E(minal.).25 E F2(-h --help)108 691.2 Q F0(Displa)144
|
||||
703.2 Q 2.78(yah)-.3 G(elp screen and quit.)-2.78 E 215.38(local 1)
|
||||
295.72 768 R 0 Cg EP
|
||||
%%Page: 2 2
|
||||
%%BeginPageSetup
|
||||
BP
|
||||
%%EndPageSetup
|
||||
/F0 10/Helvetica@0 SF 394.1(PIGZ\(1\) PIGZ\(1\))72 48 R/F1 10
|
||||
/Helvetica-Bold@0 SF(-i --independent)108 84 Q F0(Compress b)144 96 Q
|
||||
(loc)-.2 E(ks independently f)-.2 E(or damage reco)-.3 E -.25(ve)-.15 G
|
||||
.3(ry).25 G(.)-1.3 E F1(-k --keep)108 112.8 Q F0(Do not delete or)144
|
||||
124.8 Q(iginal \214le after processing.).15 E F1(-K --zip)108 141.6 Q F0
|
||||
(Compress to PKW)144 153.6 Q(are zip \(.zip\) single entr)-.4 E 2.78(yf)
|
||||
.3 G -2.53(or mat.)-3.08 F F1(-l --list)108 170.4 Q F0
|
||||
(List the contents of the compressed input.)6 E F1(-L --license)108
|
||||
187.2 Q F0(Displa)144 199.2 Q 2.78(yt)-.3 G(he)-2.78 E/F2 10
|
||||
/Helvetica-Oblique@0 SF(pigz)3.14 E F0(license and quit.)3.99 E F1
|
||||
(-n --no-name)108 216 Q F0
|
||||
(Do not store or restore \214le name in/from header)144 228 Q(.)-.5 E F1
|
||||
(-N --name)108 244.8 Q F0
|
||||
(Store/restore \214le name and mod time in/from header)144 256.8 Q(.)-.5
|
||||
E F1(-p --pr)108 273.6 Q(ocesses n)-.2 E F0(Allo)144 285.6 Q 2.78(wu)
|
||||
-.15 G 2.78(pt)-2.78 G 2.78(onp)-2.78 G(rocesses \(def)-2.78 E
|
||||
(ault is the n)-.3 E(umber of online processors\))-.1 E F1
|
||||
(-q --quiet --silent)108 302.4 Q F0 -2.63(Pr int)144 314.4 R
|
||||
(no messages)2.78 E 2.78(,e)-.15 G -.25(ve)-3.08 G 2.78(no).25 G 2.78
|
||||
(ne)-2.78 G(rror)-2.78 E(.)-.5 E F1(-r --recur)108 331.2 Q(sive)-.15 E
|
||||
F0(Process the contents of all subdirector)144 343.2 Q(ies).15 E(.)-.15
|
||||
E F1(-S --suf\214x .sss)108 360 Q F0
|
||||
(Use suf\214x .sss instead of .gz \(f)144 372 Q(or compression\).)-.3 E
|
||||
F1(-t --test)108 388.8 Q F0 -1.2(Te)144 400.8 S(st the integ)1.2 E .15
|
||||
(ri)-.1 G(ty of the compressed input.)-.15 E F1(-T --no-time)108 417.6 Q
|
||||
F0(Do not store or restore mod time in/from header)144 429.6 Q(.)-.5 E
|
||||
F1(-v --verbose)108 446.4 Q F0(Pro)144 458.4 Q(vide more v)-.15 E
|
||||
(erbose output.)-.25 E F1(-V --ver)108 475.2 Q(sion)-.15 E F0(Sho)144
|
||||
487.2 Q 2.78(wt)-.15 G(he v)-2.78 E(ersion of pigz.)-.25 E F1(-z --zlib)
|
||||
108 504 Q F0(Compress to zlib \(.zz\) instead of gzip f)144 516 Q -2.53
|
||||
(or mat.)-.3 F/F3 10.95/Helvetica-Bold@0 SF(COPYRIGHT NO)72 532.8 Q
|
||||
(TICE)-.438 E F0 1.554(This softw)108 544.8 R 1.554(are is pro)-.15 F
|
||||
1.554(vided 'as-is', without an)-.15 F 4.333(ye)-.15 G 1.553
|
||||
(xpress or implied w)-4.633 F(arr)-.15 E(anty)-.1 E 7.113(.I)-1 G 4.333
|
||||
(nn)-7.113 G 4.333(oe)-4.333 G -.25(ve)-4.633 G 1.553(nt will the).25 F
|
||||
(author be held liab)108 556.8 Q(le f)-.2 E(or an)-.3 E 2.78(yd)-.15 G
|
||||
(amages ar)-2.78 E(ising from the use of this softw).15 E(are)-.15 E(.)
|
||||
-.15 E(Cop)108 573.6 Q -2.63(yr ight)-.3 F
|
||||
(\(C\) 2007, 2008, 2009, 2010 Mar)2.78 E 2.78(kA).15 G
|
||||
(dler <madler@alumni.caltech.edu>)-2.78 E 215.38(local 2)295.72 768 R 0
|
||||
Cg EP
|
||||
%%Trailer
|
||||
end
|
||||
%%EOF
|
|
@ -0,0 +1,26 @@
|
|||
Summary: pigz is a parallel implementation of gzip which utilizes multiple cores
|
||||
Name: pigz
|
||||
Version: 2.1.6
|
||||
Release: 1
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
License: GPL
|
||||
Group: Applications/Tools
|
||||
Packager: Duncan Brown <duncan@duncanbrown.org>
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
URL: http://www.zlib.net/pigz
|
||||
|
||||
%description
|
||||
pigz, which stands for parallel implementation of gzip, is a fully functional replacement for gzip that exploits multiple processors and multiple cores to the hilt when compressing data. pigz was written by Mark Adler, and uses the zlib and pthread libraries.
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
%prep
|
||||
mkdir -p $RPM_BUILD_ROOT
|
||||
%setup -q
|
||||
%build
|
||||
make
|
||||
mkdir -p ${RPM_BUILD_ROOT}/usr/bin
|
||||
mv pigz ${RPM_BUILD_ROOT}/usr/bin
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
/usr/bin/pigz
|
|
@ -0,0 +1,365 @@
|
|||
/* yarn.c -- generic thread operations implemented using pthread functions
|
||||
* Copyright (C) 2008 Mark Adler
|
||||
* Version 1.1 26 Oct 2008 Mark Adler
|
||||
* For conditions of distribution and use, see copyright notice in yarn.h
|
||||
*/
|
||||
|
||||
/* Basic thread operations implemented using the POSIX pthread library. All
|
||||
pthread references are isolated within this module to allow alternate
|
||||
implementations with other thread libraries. See yarn.h for the description
|
||||
of these operations. */
|
||||
|
||||
/* Version history:
|
||||
1.0 19 Oct 2008 First version
|
||||
1.1 26 Oct 2008 No need to set the stack size -- remove
|
||||
Add yarn_abort() function for clean-up on error exit
|
||||
*/
|
||||
|
||||
/* for thread portability */
|
||||
#define _POSIX_PTHREAD_SEMANTICS
|
||||
#define _REENTRANT
|
||||
|
||||
/* external libraries and entities referenced */
|
||||
#include <stdio.h> /* fprintf(), stderr */
|
||||
#include <stdlib.h> /* exit(), malloc(), free(), NULL */
|
||||
#include <pthread.h> /* pthread_t, pthread_create(), pthread_join(), */
|
||||
/* pthread_attr_t, pthread_attr_init(), pthread_attr_destroy(),
|
||||
PTHREAD_CREATE_JOINABLE, pthread_attr_setdetachstate(),
|
||||
pthread_self(), pthread_equal(),
|
||||
pthread_mutex_t, PTHREAD_MUTEX_INITIALIZER, pthread_mutex_init(),
|
||||
pthread_mutex_lock(), pthread_mutex_unlock(), pthread_mutex_destroy(),
|
||||
pthread_cond_t, PTHREAD_COND_INITIALIZER, pthread_cond_init(),
|
||||
pthread_cond_broadcast(), pthread_cond_wait(), pthread_cond_destroy() */
|
||||
#include <errno.h> /* ENOMEM, EAGAIN, EINVAL */
|
||||
|
||||
/* interface definition */
|
||||
#include "yarn.h"
|
||||
|
||||
/* constants */
|
||||
#define local static /* for non-exported functions and globals */
|
||||
|
||||
/* error handling external globals, resettable by application */
|
||||
char *yarn_prefix = "yarn";
|
||||
void (*yarn_abort)(int) = NULL;
|
||||
|
||||
|
||||
/* immediately exit -- use for errors that shouldn't ever happen */
|
||||
local void fail(int err)
|
||||
{
|
||||
fprintf(stderr, "%s: %s (%d) -- aborting\n", yarn_prefix,
|
||||
err == ENOMEM ? "out of memory" : "internal pthread error", err);
|
||||
if (yarn_abort != NULL)
|
||||
yarn_abort(err);
|
||||
exit(err == ENOMEM || err == EAGAIN ? err : EINVAL);
|
||||
}
|
||||
|
||||
/* memory handling routines provided by user -- if none are provided, malloc()
|
||||
and free() are used, which are therefore assumed to be thread-safe */
|
||||
typedef void *(*malloc_t)(size_t);
|
||||
typedef void (*free_t)(void *);
|
||||
local malloc_t my_malloc_f = malloc;
|
||||
local free_t my_free = free;
|
||||
|
||||
/* use user-supplied allocation routines instead of malloc() and free() */
|
||||
void yarn_mem(malloc_t lease, free_t vacate)
|
||||
{
|
||||
my_malloc_f = lease;
|
||||
my_free = vacate;
|
||||
}
|
||||
|
||||
/* memory allocation that cannot fail (from the point of view of the caller) */
|
||||
local void *my_malloc(size_t size)
|
||||
{
|
||||
void *block;
|
||||
|
||||
if ((block = my_malloc_f(size)) == NULL)
|
||||
fail(ENOMEM);
|
||||
return block;
|
||||
}
|
||||
|
||||
/* -- lock functions -- */
|
||||
|
||||
struct lock_s {
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
long value;
|
||||
};
|
||||
|
||||
lock *new_lock(long initial)
|
||||
{
|
||||
int ret;
|
||||
lock *bolt;
|
||||
|
||||
bolt = my_malloc(sizeof(struct lock_s));
|
||||
if ((ret = pthread_mutex_init(&(bolt->mutex), NULL)) ||
|
||||
(ret = pthread_cond_init(&(bolt->cond), NULL)))
|
||||
fail(ret);
|
||||
bolt->value = initial;
|
||||
return bolt;
|
||||
}
|
||||
|
||||
void possess(lock *bolt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = pthread_mutex_lock(&(bolt->mutex))) != 0)
|
||||
fail(ret);
|
||||
}
|
||||
|
||||
void release(lock *bolt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = pthread_mutex_unlock(&(bolt->mutex))) != 0)
|
||||
fail(ret);
|
||||
}
|
||||
|
||||
void twist(lock *bolt, enum twist_op op, long val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (op == TO)
|
||||
bolt->value = val;
|
||||
else if (op == BY)
|
||||
bolt->value += val;
|
||||
if ((ret = pthread_cond_broadcast(&(bolt->cond))) ||
|
||||
(ret = pthread_mutex_unlock(&(bolt->mutex))))
|
||||
fail(ret);
|
||||
}
|
||||
|
||||
#define until(a) while(!(a))
|
||||
|
||||
void wait_for(lock *bolt, enum wait_op op, long val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (op) {
|
||||
case TO_BE:
|
||||
until (bolt->value == val)
|
||||
if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0)
|
||||
fail(ret);
|
||||
break;
|
||||
case NOT_TO_BE:
|
||||
until (bolt->value != val)
|
||||
if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0)
|
||||
fail(ret);
|
||||
break;
|
||||
case TO_BE_MORE_THAN:
|
||||
until (bolt->value > val)
|
||||
if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0)
|
||||
fail(ret);
|
||||
break;
|
||||
case TO_BE_LESS_THAN:
|
||||
until (bolt->value < val)
|
||||
if ((ret = pthread_cond_wait(&(bolt->cond), &(bolt->mutex))) != 0)
|
||||
fail(ret);
|
||||
}
|
||||
}
|
||||
|
||||
long peek_lock(lock *bolt)
|
||||
{
|
||||
return bolt->value;
|
||||
}
|
||||
|
||||
void free_lock(lock *bolt)
|
||||
{
|
||||
int ret;
|
||||
if ((ret = pthread_cond_destroy(&(bolt->cond))) ||
|
||||
(ret = pthread_mutex_destroy(&(bolt->mutex))))
|
||||
fail(ret);
|
||||
my_free(bolt);
|
||||
}
|
||||
|
||||
/* -- thread functions (uses lock functions above) -- */
|
||||
|
||||
struct thread_s {
|
||||
pthread_t id;
|
||||
int done; /* true if this thread has exited */
|
||||
thread *next; /* for list of all launched threads */
|
||||
};
|
||||
|
||||
/* list of threads launched but not joined, count of threads exited but not
|
||||
joined (incremented by ignition() just before exiting) */
|
||||
local lock threads_lock = {
|
||||
PTHREAD_MUTEX_INITIALIZER,
|
||||
PTHREAD_COND_INITIALIZER,
|
||||
0 /* number of threads exited but not joined */
|
||||
};
|
||||
local thread *threads = NULL; /* list of extant threads */
|
||||
|
||||
/* structure in which to pass the probe and its payload to ignition() */
|
||||
struct capsule {
|
||||
void (*probe)(void *);
|
||||
void *payload;
|
||||
};
|
||||
|
||||
/* mark the calling thread as done and alert join_all() */
|
||||
local void reenter(void *dummy)
|
||||
{
|
||||
thread *match, **prior;
|
||||
pthread_t me;
|
||||
|
||||
/* find this thread in the threads list by matching the thread id */
|
||||
me = pthread_self();
|
||||
possess(&(threads_lock));
|
||||
prior = &(threads);
|
||||
while ((match = *prior) != NULL) {
|
||||
if (pthread_equal(match->id, me))
|
||||
break;
|
||||
prior = &(match->next);
|
||||
}
|
||||
if (match == NULL)
|
||||
fail(EINVAL);
|
||||
|
||||
/* mark this thread as done and move it to the head of the list */
|
||||
match->done = 1;
|
||||
if (threads != match) {
|
||||
*prior = match->next;
|
||||
match->next = threads;
|
||||
threads = match;
|
||||
}
|
||||
|
||||
/* update the count of threads to be joined and alert join_all() */
|
||||
twist(&(threads_lock), BY, +1);
|
||||
}
|
||||
|
||||
/* all threads go through this routine so that just before the thread exits,
|
||||
it marks itself as done in the threads list and alerts join_all() so that
|
||||
the thread resources can be released -- use cleanup stack so that the
|
||||
marking occurs even if the thread is cancelled */
|
||||
local void *ignition(void *arg)
|
||||
{
|
||||
struct capsule *capsule = arg;
|
||||
|
||||
/* run reenter() before leaving */
|
||||
pthread_cleanup_push(reenter, NULL);
|
||||
|
||||
/* execute the requested function with argument */
|
||||
capsule->probe(capsule->payload);
|
||||
my_free(capsule);
|
||||
|
||||
/* mark this thread as done and let join_all() know */
|
||||
pthread_cleanup_pop(1);
|
||||
|
||||
/* exit thread */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* not all POSIX implementations create threads as joinable by default, so that
|
||||
is made explicit here */
|
||||
thread *launch(void (*probe)(void *), void *payload)
|
||||
{
|
||||
int ret;
|
||||
thread *th;
|
||||
struct capsule *capsule;
|
||||
pthread_attr_t attr;
|
||||
|
||||
/* construct the requested call and argument for the ignition() routine
|
||||
(allocated instead of automatic so that we're sure this will still be
|
||||
there when ignition() actually starts up -- ignition() will free this
|
||||
allocation) */
|
||||
capsule = my_malloc(sizeof(struct capsule));
|
||||
capsule->probe = probe;
|
||||
capsule->payload = payload;
|
||||
|
||||
/* assure this thread is in the list before join_all() or ignition() looks
|
||||
for it */
|
||||
possess(&(threads_lock));
|
||||
|
||||
/* create the thread and call ignition() from that thread */
|
||||
th = my_malloc(sizeof(struct thread_s));
|
||||
if ((ret = pthread_attr_init(&attr)) ||
|
||||
(ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)) ||
|
||||
(ret = pthread_create(&(th->id), &attr, ignition, capsule)) ||
|
||||
(ret = pthread_attr_destroy(&attr)))
|
||||
fail(ret);
|
||||
|
||||
/* put the thread in the threads list for join_all() */
|
||||
th->done = 0;
|
||||
th->next = threads;
|
||||
threads = th;
|
||||
release(&(threads_lock));
|
||||
return th;
|
||||
}
|
||||
|
||||
void join(thread *ally)
|
||||
{
|
||||
int ret;
|
||||
thread *match, **prior;
|
||||
|
||||
/* wait for thread to exit and return its resources */
|
||||
if ((ret = pthread_join(ally->id, NULL)) != 0)
|
||||
fail(ret);
|
||||
|
||||
/* find the thread in the threads list */
|
||||
possess(&(threads_lock));
|
||||
prior = &(threads);
|
||||
while ((match = *prior) != NULL) {
|
||||
if (match == ally)
|
||||
break;
|
||||
prior = &(match->next);
|
||||
}
|
||||
if (match == NULL)
|
||||
fail(EINVAL);
|
||||
|
||||
/* remove thread from list and update exited count, free thread */
|
||||
if (match->done)
|
||||
threads_lock.value--;
|
||||
*prior = match->next;
|
||||
release(&(threads_lock));
|
||||
my_free(ally);
|
||||
}
|
||||
|
||||
/* This implementation of join_all() only attempts to join threads that have
|
||||
announced that they have exited (see ignition()). When there are many
|
||||
threads, this is faster than waiting for some random thread to exit while a
|
||||
bunch of other threads have already exited. */
|
||||
int join_all(void)
|
||||
{
|
||||
int ret, count;
|
||||
thread *match, **prior;
|
||||
|
||||
/* grab the threads list and initialize the joined count */
|
||||
count = 0;
|
||||
possess(&(threads_lock));
|
||||
|
||||
/* do until threads list is empty */
|
||||
while (threads != NULL) {
|
||||
/* wait until at least one thread has reentered */
|
||||
wait_for(&(threads_lock), NOT_TO_BE, 0);
|
||||
|
||||
/* find the first thread marked done (should be at or near the top) */
|
||||
prior = &(threads);
|
||||
while ((match = *prior) != NULL) {
|
||||
if (match->done)
|
||||
break;
|
||||
prior = &(match->next);
|
||||
}
|
||||
if (match == NULL)
|
||||
fail(EINVAL);
|
||||
|
||||
/* join the thread (will be almost immediate), remove from the threads
|
||||
list, update the reenter count, and free the thread */
|
||||
if ((ret = pthread_join(match->id, NULL)) != 0)
|
||||
fail(ret);
|
||||
threads_lock.value--;
|
||||
*prior = match->next;
|
||||
my_free(match);
|
||||
count++;
|
||||
}
|
||||
|
||||
/* let go of the threads list and return the number of threads joined */
|
||||
release(&(threads_lock));
|
||||
return count;
|
||||
}
|
||||
|
||||
/* cancel and join the thread -- the thread will cancel when it gets to a file
|
||||
operation, a sleep or pause, or a condition wait */
|
||||
void destruct(thread *off_course)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if ((ret = pthread_cancel(off_course->id)) != 0)
|
||||
fail(ret);
|
||||
join(off_course);
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/* yarn.h -- generic interface for thread operations
|
||||
* Copyright (C) 2008 Mark Adler
|
||||
* Version 1.1 26 Oct 2008 Mark Adler
|
||||
*/
|
||||
|
||||
/*
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the author be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
Mark Adler
|
||||
madler@alumni.caltech.edu
|
||||
*/
|
||||
|
||||
/* Basic thread operations
|
||||
|
||||
This interface isolates the local operating system implementation of threads
|
||||
from the application in order to facilitate platform independent use of
|
||||
threads. All of the implementation details are deliberately hidden.
|
||||
|
||||
Assuming adequate system resources and proper use, none of these functions
|
||||
can fail. As a result, any errors encountered will cause an exit() to be
|
||||
executed.
|
||||
|
||||
These functions allow the simple launching and joining of threads, and the
|
||||
locking of objects and synchronization of changes of objects. The latter is
|
||||
implemented with a single lock type that contains an integer value. The
|
||||
value can be ignored for simple exclusive access to an object, or the value
|
||||
can be used to signal and wait for changes to an object.
|
||||
|
||||
-- Arguments --
|
||||
|
||||
thread *thread; identifier for launched thread, used by join
|
||||
void probe(void *); pointer to function "probe", run when thread starts
|
||||
void *payload; single argument passed to the probe function
|
||||
lock *lock; a lock with a value -- used for exclusive access to
|
||||
an object and to synchronize threads waiting for
|
||||
changes to an object
|
||||
long val; value to set lock, increment lock, or wait for
|
||||
int n; number of threads joined
|
||||
|
||||
-- Thread functions --
|
||||
|
||||
thread = launch(probe, payload) - launch a thread -- exit via probe() return
|
||||
join(thread) - join a thread and by joining end it, waiting for the thread
|
||||
to exit if it hasn't already -- will free the resources allocated by
|
||||
launch() (don't try to join the same thread more than once)
|
||||
n = join_all() - join all threads launched by launch() that are not joined
|
||||
yet and free the resources allocated by the launches, usually to clean
|
||||
up when the thread processing is done -- join_all() returns an int with
|
||||
the count of the number of threads joined (join_all() should only be
|
||||
called from the main thread, and should only be called after any calls
|
||||
of join() have completed)
|
||||
destruct(thread) - terminate the thread in mid-execution and join it
|
||||
(depending on the implementation, the termination may not be immediate,
|
||||
but may wait for the thread to execute certain thread or file i/o
|
||||
operations)
|
||||
|
||||
-- Lock functions --
|
||||
|
||||
lock = new_lock(val) - create a new lock with initial value val (lock is
|
||||
created in the released state)
|
||||
possess(lock) - acquire exclusive possession of a lock, waiting if necessary
|
||||
twist(lock, [TO | BY], val) - set lock to or increment lock by val, signal
|
||||
all threads waiting on this lock and then release the lock -- must
|
||||
possess the lock before calling (twist releases, so don't do a
|
||||
release() after a twist() on the same lock)
|
||||
wait_for(lock, [TO_BE | NOT_TO_BE | TO_BE_MORE_THAN | TO_BE_LESS_THAN], val)
|
||||
- wait on lock value to be, not to be, be greater than, or be less than
|
||||
val -- must possess the lock before calling, will possess the lock on
|
||||
return but the lock is released while waiting to permit other threads
|
||||
to use twist() to change the value and signal the change (so make sure
|
||||
that the object is in a usable state when waiting)
|
||||
release(lock) - release a possessed lock (do not try to release a lock that
|
||||
the current thread does not possess)
|
||||
val = peek_lock(lock) - return the value of the lock (assumes that lock is
|
||||
already possessed, no possess or release is done by peek_lock())
|
||||
free_lock(lock) - free the resources allocated by new_lock() (application
|
||||
must assure that the lock is released before calling free_lock())
|
||||
|
||||
-- Memory allocation ---
|
||||
|
||||
yarn_mem(better_malloc, better_free) - set the memory allocation and free
|
||||
routines for use by the yarn routines where the supplied routines have
|
||||
the same interface and operation as malloc() and free(), and may be
|
||||
provided in order to supply thread-safe memory allocation routines or
|
||||
for any other reason -- by default malloc() and free() will be used
|
||||
|
||||
-- Error control --
|
||||
|
||||
yarn_name - a char pointer to a string that will be the prefix for any error
|
||||
messages that these routines generate before exiting -- if not changed
|
||||
by the application, "yarn" will be used
|
||||
yarn_abort - an external function that will be executed when there is an
|
||||
internal yarn error, due to out of memory or misuse -- this function
|
||||
may exit to abort the application, or if it returns, the yarn error
|
||||
handler will exit (set to NULL by default for no action)
|
||||
*/
|
||||
|
||||
extern char *yarn_prefix;
|
||||
extern void (*yarn_abort)(int);
|
||||
|
||||
void yarn_mem(void *(*)(size_t), void (*)(void *));
|
||||
|
||||
typedef struct thread_s thread;
|
||||
thread *launch(void (*)(void *), void *);
|
||||
void join(thread *);
|
||||
int join_all(void);
|
||||
void destruct(thread *);
|
||||
|
||||
typedef struct lock_s lock;
|
||||
lock *new_lock(long);
|
||||
void possess(lock *);
|
||||
void release(lock *);
|
||||
enum twist_op { TO, BY };
|
||||
void twist(lock *, enum twist_op, long);
|
||||
enum wait_op {
|
||||
TO_BE, /* or */ NOT_TO_BE, /* that is the question */
|
||||
TO_BE_MORE_THAN, TO_BE_LESS_THAN };
|
||||
void wait_for(lock *, enum wait_op, long);
|
||||
long peek_lock(lock *);
|
||||
void free_lock(lock *);
|
Loading…
Reference in New Issue