tag 1.0.1
This commit is contained in:
parent
4d3523ca8a
commit
515579160d
53 changed files with 13960 additions and 0 deletions
25
1.0.1/.cvsignore
Normal file
25
1.0.1/.cvsignore
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
*.lo
|
||||||
|
*.la
|
||||||
|
.deps
|
||||||
|
.libs
|
||||||
|
*.loT
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
aclocal.m4
|
||||||
|
autom4te.cache
|
||||||
|
config.h
|
||||||
|
config.h.in
|
||||||
|
config.log
|
||||||
|
config.status
|
||||||
|
configure
|
||||||
|
libtool
|
||||||
|
stamp-h
|
||||||
|
stamp-h.in
|
||||||
|
stamp-h1
|
||||||
|
umem_test
|
||||||
|
umem_test2
|
||||||
|
umem_test3
|
||||||
|
Doxyfile
|
||||||
|
umem.spec
|
||||||
|
*.tar.gz
|
||||||
|
*.tar.bz2
|
0
1.0.1/AUTHORS
Normal file
0
1.0.1/AUTHORS
Normal file
2
1.0.1/COPYING
Normal file
2
1.0.1/COPYING
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
Please see COPYRIGHT and OPENSOLARIS.LICENSE for the copyright
|
||||||
|
and license details.
|
6
1.0.1/COPYRIGHT
Normal file
6
1.0.1/COPYRIGHT
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
The bulk of the library is Copyright 2004 Sun Microsystems, Inc.
|
||||||
|
Portions are Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
|
||||||
|
The library is distributed under the terms of the CDDL.
|
||||||
|
See the file OPENSOLARIS.LICENSE for more information.
|
||||||
|
|
0
1.0.1/ChangeLog
Normal file
0
1.0.1/ChangeLog
Normal file
1228
1.0.1/Doxyfile.in
Normal file
1228
1.0.1/Doxyfile.in
Normal file
File diff suppressed because it is too large
Load diff
62
1.0.1/Makefile.am
Normal file
62
1.0.1/Makefile.am
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
lib_LTLIBRARIES = libumem.la libumem_malloc.la
|
||||||
|
noinst_PROGRAMS = umem_test umem_test2 umem_test3
|
||||||
|
|
||||||
|
libumem_la_LDFLAGS = -lpthread -ldl
|
||||||
|
|
||||||
|
umem_test_SOURCES = umem_test.c
|
||||||
|
umem_test_LDADD = -lumem
|
||||||
|
|
||||||
|
umem_test2_SOURCES = umem_test2.c
|
||||||
|
umem_test2_LDADD = -lumem
|
||||||
|
|
||||||
|
umem_test3_SOURCES = umem_test3.c
|
||||||
|
umem_test3_LDADD = -lumem -lumem_malloc
|
||||||
|
|
||||||
|
libumem_la_SOURCES = init_lib.c \
|
||||||
|
umem_agent_support.c \
|
||||||
|
umem_fail.c \
|
||||||
|
umem_fork.c \
|
||||||
|
umem_update_thread.c \
|
||||||
|
vmem_mmap.c \
|
||||||
|
vmem_sbrk.c \
|
||||||
|
envvar.c \
|
||||||
|
getpcstack.c \
|
||||||
|
misc.c \
|
||||||
|
misc.h \
|
||||||
|
vmem_base.c \
|
||||||
|
vmem_base.h \
|
||||||
|
vmem_stand.h \
|
||||||
|
umem.c \
|
||||||
|
umem.h \
|
||||||
|
umem_base.h \
|
||||||
|
umem_impl.h \
|
||||||
|
sol_compat.h \
|
||||||
|
vmem.c \
|
||||||
|
sys/vmem.h \
|
||||||
|
sys/vmem_impl_user.h
|
||||||
|
|
||||||
|
libumem_malloc_la_SOURCES = malloc.c
|
||||||
|
libumem_malloc_la_LDFLAGS = -lpthread -ldl -R$(libdir) -lumem
|
||||||
|
|
||||||
|
man3_MANS = umem_alloc.3 umem_cache_create.3 umem_debug.3
|
||||||
|
EXTRA_DIST = COPYRIGHT OPENSOLARIS.LICENSE umem.spec Doxyfile umem_test4 \
|
||||||
|
$(man3_MANS)
|
||||||
|
|
||||||
|
nobase_include_HEADERS = umem.h sys/vmem.h
|
||||||
|
|
||||||
|
TESTS = umem_test umem_test2 umem_test3 umem_test4
|
||||||
|
|
||||||
|
html-local:
|
||||||
|
mkdir -p docs
|
||||||
|
doxygen Doxyfile
|
||||||
|
|
||||||
|
clean-local:
|
||||||
|
rm -rf docs
|
||||||
|
|
||||||
|
.PHONY: rpm
|
||||||
|
rpm: dist-bzip2
|
||||||
|
rpmbuild -ta $(distdir).tar.bz2
|
||||||
|
|
||||||
|
# XXX: Non-i386: SPARC asm. x86_64?
|
||||||
|
# Convert this to GNU as format: i386_subr_sol.s
|
||||||
|
# <http://cvs.opensolaris.org/source/xref/on/usr/src/lib/libumem/>
|
0
1.0.1/NEWS
Normal file
0
1.0.1/NEWS
Normal file
385
1.0.1/OPENSOLARIS.LICENSE
Normal file
385
1.0.1/OPENSOLARIS.LICENSE
Normal file
|
@ -0,0 +1,385 @@
|
||||||
|
Unless otherwise noted, all files in this distribution are released
|
||||||
|
under the Common Development and Distribution License (CDDL),
|
||||||
|
Version 1.0 only. Exceptions are noted within the associated
|
||||||
|
source files.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
1.1. "Contributor" means each individual or entity that creates
|
||||||
|
or contributes to the creation of Modifications.
|
||||||
|
|
||||||
|
1.2. "Contributor Version" means the combination of the Original
|
||||||
|
Software, prior Modifications used by a Contributor (if any),
|
||||||
|
and the Modifications made by that particular Contributor.
|
||||||
|
|
||||||
|
1.3. "Covered Software" means (a) the Original Software, or (b)
|
||||||
|
Modifications, or (c) the combination of files containing
|
||||||
|
Original Software with files containing Modifications, in
|
||||||
|
each case including portions thereof.
|
||||||
|
|
||||||
|
1.4. "Executable" means the Covered Software in any form other
|
||||||
|
than Source Code.
|
||||||
|
|
||||||
|
1.5. "Initial Developer" means the individual or entity that first
|
||||||
|
makes Original Software available under this License.
|
||||||
|
|
||||||
|
1.6. "Larger Work" means a work which combines Covered Software or
|
||||||
|
portions thereof with code not governed by the terms of this
|
||||||
|
License.
|
||||||
|
|
||||||
|
1.7. "License" means this document.
|
||||||
|
|
||||||
|
1.8. "Licensable" means having the right to grant, to the maximum
|
||||||
|
extent possible, whether at the time of the initial grant or
|
||||||
|
subsequently acquired, any and all of the rights conveyed
|
||||||
|
herein.
|
||||||
|
|
||||||
|
1.9. "Modifications" means the Source Code and Executable form of
|
||||||
|
any of the following:
|
||||||
|
|
||||||
|
A. Any file that results from an addition to, deletion from or
|
||||||
|
modification of the contents of a file containing Original
|
||||||
|
Software or previous Modifications;
|
||||||
|
|
||||||
|
B. Any new file that contains any part of the Original
|
||||||
|
Software or previous Modifications; or
|
||||||
|
|
||||||
|
C. Any new file that is contributed or otherwise made
|
||||||
|
available under the terms of this License.
|
||||||
|
|
||||||
|
1.10. "Original Software" means the Source Code and Executable
|
||||||
|
form of computer software code that is originally released
|
||||||
|
under this License.
|
||||||
|
|
||||||
|
1.11. "Patent Claims" means any patent claim(s), now owned or
|
||||||
|
hereafter acquired, including without limitation, method,
|
||||||
|
process, and apparatus claims, in any patent Licensable by
|
||||||
|
grantor.
|
||||||
|
|
||||||
|
1.12. "Source Code" means (a) the common form of computer software
|
||||||
|
code in which modifications are made and (b) associated
|
||||||
|
documentation included in or with such code.
|
||||||
|
|
||||||
|
1.13. "You" (or "Your") means an individual or a legal entity
|
||||||
|
exercising rights under, and complying with all of the terms
|
||||||
|
of, this License. For legal entities, "You" includes any
|
||||||
|
entity which controls, is controlled by, or is under common
|
||||||
|
control with You. For purposes of this definition,
|
||||||
|
"control" means (a) the power, direct or indirect, to cause
|
||||||
|
the direction or management of such entity, whether by
|
||||||
|
contract or otherwise, or (b) ownership of more than fifty
|
||||||
|
percent (50%) of the outstanding shares or beneficial
|
||||||
|
ownership of such entity.
|
||||||
|
|
||||||
|
2. License Grants.
|
||||||
|
|
||||||
|
2.1. The Initial Developer Grant.
|
||||||
|
|
||||||
|
Conditioned upon Your compliance with Section 3.1 below and
|
||||||
|
subject to third party intellectual property claims, the Initial
|
||||||
|
Developer hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
(a) under intellectual property rights (other than patent or
|
||||||
|
trademark) Licensable by Initial Developer, to use,
|
||||||
|
reproduce, modify, display, perform, sublicense and
|
||||||
|
distribute the Original Software (or portions thereof),
|
||||||
|
with or without Modifications, and/or as part of a Larger
|
||||||
|
Work; and
|
||||||
|
|
||||||
|
(b) under Patent Claims infringed by the making, using or
|
||||||
|
selling of Original Software, to make, have made, use,
|
||||||
|
practice, sell, and offer for sale, and/or otherwise
|
||||||
|
dispose of the Original Software (or portions thereof).
|
||||||
|
|
||||||
|
(c) The licenses granted in Sections 2.1(a) and (b) are
|
||||||
|
effective on the date Initial Developer first distributes
|
||||||
|
or otherwise makes the Original Software available to a
|
||||||
|
third party under the terms of this License.
|
||||||
|
|
||||||
|
(d) Notwithstanding Section 2.1(b) above, no patent license is
|
||||||
|
granted: (1) for code that You delete from the Original
|
||||||
|
Software, or (2) for infringements caused by: (i) the
|
||||||
|
modification of the Original Software, or (ii) the
|
||||||
|
combination of the Original Software with other software
|
||||||
|
or devices.
|
||||||
|
|
||||||
|
2.2. Contributor Grant.
|
||||||
|
|
||||||
|
Conditioned upon Your compliance with Section 3.1 below and
|
||||||
|
subject to third party intellectual property claims, each
|
||||||
|
Contributor hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
(a) under intellectual property rights (other than patent or
|
||||||
|
trademark) Licensable by Contributor to use, reproduce,
|
||||||
|
modify, display, perform, sublicense and distribute the
|
||||||
|
Modifications created by such Contributor (or portions
|
||||||
|
thereof), either on an unmodified basis, with other
|
||||||
|
Modifications, as Covered Software and/or as part of a
|
||||||
|
Larger Work; and
|
||||||
|
|
||||||
|
(b) under Patent Claims infringed by the making, using, or
|
||||||
|
selling of Modifications made by that Contributor either
|
||||||
|
alone and/or in combination with its Contributor Version
|
||||||
|
(or portions of such combination), to make, use, sell,
|
||||||
|
offer for sale, have made, and/or otherwise dispose of:
|
||||||
|
(1) Modifications made by that Contributor (or portions
|
||||||
|
thereof); and (2) the combination of Modifications made by
|
||||||
|
that Contributor with its Contributor Version (or portions
|
||||||
|
of such combination).
|
||||||
|
|
||||||
|
(c) The licenses granted in Sections 2.2(a) and 2.2(b) are
|
||||||
|
effective on the date Contributor first distributes or
|
||||||
|
otherwise makes the Modifications available to a third
|
||||||
|
party.
|
||||||
|
|
||||||
|
(d) Notwithstanding Section 2.2(b) above, no patent license is
|
||||||
|
granted: (1) for any code that Contributor has deleted
|
||||||
|
from the Contributor Version; (2) for infringements caused
|
||||||
|
by: (i) third party modifications of Contributor Version,
|
||||||
|
or (ii) the combination of Modifications made by that
|
||||||
|
Contributor with other software (except as part of the
|
||||||
|
Contributor Version) or other devices; or (3) under Patent
|
||||||
|
Claims infringed by Covered Software in the absence of
|
||||||
|
Modifications made by that Contributor.
|
||||||
|
|
||||||
|
3. Distribution Obligations.
|
||||||
|
|
||||||
|
3.1. Availability of Source Code.
|
||||||
|
|
||||||
|
Any Covered Software that You distribute or otherwise make
|
||||||
|
available in Executable form must also be made available in Source
|
||||||
|
Code form and that Source Code form must be distributed only under
|
||||||
|
the terms of this License. You must include a copy of this
|
||||||
|
License with every copy of the Source Code form of the Covered
|
||||||
|
Software You distribute or otherwise make available. You must
|
||||||
|
inform recipients of any such Covered Software in Executable form
|
||||||
|
as to how they can obtain such Covered Software in Source Code
|
||||||
|
form in a reasonable manner on or through a medium customarily
|
||||||
|
used for software exchange.
|
||||||
|
|
||||||
|
3.2. Modifications.
|
||||||
|
|
||||||
|
The Modifications that You create or to which You contribute are
|
||||||
|
governed by the terms of this License. You represent that You
|
||||||
|
believe Your Modifications are Your original creation(s) and/or
|
||||||
|
You have sufficient rights to grant the rights conveyed by this
|
||||||
|
License.
|
||||||
|
|
||||||
|
3.3. Required Notices.
|
||||||
|
|
||||||
|
You must include a notice in each of Your Modifications that
|
||||||
|
identifies You as the Contributor of the Modification. You may
|
||||||
|
not remove or alter any copyright, patent or trademark notices
|
||||||
|
contained within the Covered Software, or any notices of licensing
|
||||||
|
or any descriptive text giving attribution to any Contributor or
|
||||||
|
the Initial Developer.
|
||||||
|
|
||||||
|
3.4. Application of Additional Terms.
|
||||||
|
|
||||||
|
You may not offer or impose any terms on any Covered Software in
|
||||||
|
Source Code form that alters or restricts the applicable version
|
||||||
|
of this License or the recipients' rights hereunder. You may
|
||||||
|
choose to offer, and to charge a fee for, warranty, support,
|
||||||
|
indemnity or liability obligations to one or more recipients of
|
||||||
|
Covered Software. However, you may do so only on Your own behalf,
|
||||||
|
and not on behalf of the Initial Developer or any Contributor.
|
||||||
|
You must make it absolutely clear that any such warranty, support,
|
||||||
|
indemnity or liability obligation is offered by You alone, and You
|
||||||
|
hereby agree to indemnify the Initial Developer and every
|
||||||
|
Contributor for any liability incurred by the Initial Developer or
|
||||||
|
such Contributor as a result of warranty, support, indemnity or
|
||||||
|
liability terms You offer.
|
||||||
|
|
||||||
|
3.5. Distribution of Executable Versions.
|
||||||
|
|
||||||
|
You may distribute the Executable form of the Covered Software
|
||||||
|
under the terms of this License or under the terms of a license of
|
||||||
|
Your choice, which may contain terms different from this License,
|
||||||
|
provided that You are in compliance with the terms of this License
|
||||||
|
and that the license for the Executable form does not attempt to
|
||||||
|
limit or alter the recipient's rights in the Source Code form from
|
||||||
|
the rights set forth in this License. If You distribute the
|
||||||
|
Covered Software in Executable form under a different license, You
|
||||||
|
must make it absolutely clear that any terms which differ from
|
||||||
|
this License are offered by You alone, not by the Initial
|
||||||
|
Developer or Contributor. You hereby agree to indemnify the
|
||||||
|
Initial Developer and every Contributor for any liability incurred
|
||||||
|
by the Initial Developer or such Contributor as a result of any
|
||||||
|
such terms You offer.
|
||||||
|
|
||||||
|
3.6. Larger Works.
|
||||||
|
|
||||||
|
You may create a Larger Work by combining Covered Software with
|
||||||
|
other code not governed by the terms of this License and
|
||||||
|
distribute the Larger Work as a single product. In such a case,
|
||||||
|
You must make sure the requirements of this License are fulfilled
|
||||||
|
for the Covered Software.
|
||||||
|
|
||||||
|
4. Versions of the License.
|
||||||
|
|
||||||
|
4.1. New Versions.
|
||||||
|
|
||||||
|
Sun Microsystems, Inc. is the initial license steward and may
|
||||||
|
publish revised and/or new versions of this License from time to
|
||||||
|
time. Each version will be given a distinguishing version number.
|
||||||
|
Except as provided in Section 4.3, no one other than the license
|
||||||
|
steward has the right to modify this License.
|
||||||
|
|
||||||
|
4.2. Effect of New Versions.
|
||||||
|
|
||||||
|
You may always continue to use, distribute or otherwise make the
|
||||||
|
Covered Software available under the terms of the version of the
|
||||||
|
License under which You originally received the Covered Software.
|
||||||
|
If the Initial Developer includes a notice in the Original
|
||||||
|
Software prohibiting it from being distributed or otherwise made
|
||||||
|
available under any subsequent version of the License, You must
|
||||||
|
distribute and make the Covered Software available under the terms
|
||||||
|
of the version of the License under which You originally received
|
||||||
|
the Covered Software. Otherwise, You may also choose to use,
|
||||||
|
distribute or otherwise make the Covered Software available under
|
||||||
|
the terms of any subsequent version of the License published by
|
||||||
|
the license steward.
|
||||||
|
|
||||||
|
4.3. Modified Versions.
|
||||||
|
|
||||||
|
When You are an Initial Developer and You want to create a new
|
||||||
|
license for Your Original Software, You may create and use a
|
||||||
|
modified version of this License if You: (a) rename the license
|
||||||
|
and remove any references to the name of the license steward
|
||||||
|
(except to note that the license differs from this License); and
|
||||||
|
(b) otherwise make it clear that the license contains terms which
|
||||||
|
differ from this License.
|
||||||
|
|
||||||
|
5. DISCLAIMER OF WARRANTY.
|
||||||
|
|
||||||
|
COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS"
|
||||||
|
BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
|
||||||
|
INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED
|
||||||
|
SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR
|
||||||
|
PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
|
||||||
|
PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY
|
||||||
|
COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
|
||||||
|
INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
|
||||||
|
NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
|
||||||
|
WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
|
||||||
|
ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS
|
||||||
|
DISCLAIMER.
|
||||||
|
|
||||||
|
6. TERMINATION.
|
||||||
|
|
||||||
|
6.1. This License and the rights granted hereunder will terminate
|
||||||
|
automatically if You fail to comply with terms herein and fail to
|
||||||
|
cure such breach within 30 days of becoming aware of the breach.
|
||||||
|
Provisions which, by their nature, must remain in effect beyond
|
||||||
|
the termination of this License shall survive.
|
||||||
|
|
||||||
|
6.2. If You assert a patent infringement claim (excluding
|
||||||
|
declaratory judgment actions) against Initial Developer or a
|
||||||
|
Contributor (the Initial Developer or Contributor against whom You
|
||||||
|
assert such claim is referred to as "Participant") alleging that
|
||||||
|
the Participant Software (meaning the Contributor Version where
|
||||||
|
the Participant is a Contributor or the Original Software where
|
||||||
|
the Participant is the Initial Developer) directly or indirectly
|
||||||
|
infringes any patent, then any and all rights granted directly or
|
||||||
|
indirectly to You by such Participant, the Initial Developer (if
|
||||||
|
the Initial Developer is not the Participant) and all Contributors
|
||||||
|
under Sections 2.1 and/or 2.2 of this License shall, upon 60 days
|
||||||
|
notice from Participant terminate prospectively and automatically
|
||||||
|
at the expiration of such 60 day notice period, unless if within
|
||||||
|
such 60 day period You withdraw Your claim with respect to the
|
||||||
|
Participant Software against such Participant either unilaterally
|
||||||
|
or pursuant to a written agreement with Participant.
|
||||||
|
|
||||||
|
6.3. In the event of termination under Sections 6.1 or 6.2 above,
|
||||||
|
all end user licenses that have been validly granted by You or any
|
||||||
|
distributor hereunder prior to termination (excluding licenses
|
||||||
|
granted to You by any distributor) shall survive termination.
|
||||||
|
|
||||||
|
7. LIMITATION OF LIABILITY.
|
||||||
|
|
||||||
|
UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
|
||||||
|
(INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE
|
||||||
|
INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF
|
||||||
|
COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE
|
||||||
|
LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR
|
||||||
|
CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT
|
||||||
|
LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK
|
||||||
|
STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
|
||||||
|
COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
|
||||||
|
INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
|
||||||
|
LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL
|
||||||
|
INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT
|
||||||
|
APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO
|
||||||
|
NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT
|
||||||
|
APPLY TO YOU.
|
||||||
|
|
||||||
|
8. U.S. GOVERNMENT END USERS.
|
||||||
|
|
||||||
|
The Covered Software is a "commercial item," as that term is
|
||||||
|
defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial
|
||||||
|
computer software" (as that term is defined at 48
|
||||||
|
C.F.R. 252.227-7014(a)(1)) and "commercial computer software
|
||||||
|
documentation" as such terms are used in 48 C.F.R. 12.212
|
||||||
|
(Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48
|
||||||
|
C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all
|
||||||
|
U.S. Government End Users acquire Covered Software with only those
|
||||||
|
rights set forth herein. This U.S. Government Rights clause is in
|
||||||
|
lieu of, and supersedes, any other FAR, DFAR, or other clause or
|
||||||
|
provision that addresses Government rights in computer software
|
||||||
|
under this License.
|
||||||
|
|
||||||
|
9. MISCELLANEOUS.
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning subject
|
||||||
|
matter hereof. If any provision of this License is held to be
|
||||||
|
unenforceable, such provision shall be reformed only to the extent
|
||||||
|
necessary to make it enforceable. This License shall be governed
|
||||||
|
by the law of the jurisdiction specified in a notice contained
|
||||||
|
within the Original Software (except to the extent applicable law,
|
||||||
|
if any, provides otherwise), excluding such jurisdiction's
|
||||||
|
conflict-of-law provisions. Any litigation relating to this
|
||||||
|
License shall be subject to the jurisdiction of the courts located
|
||||||
|
in the jurisdiction and venue specified in a notice contained
|
||||||
|
within the Original Software, with the losing party responsible
|
||||||
|
for costs, including, without limitation, court costs and
|
||||||
|
reasonable attorneys' fees and expenses. The application of the
|
||||||
|
United Nations Convention on Contracts for the International Sale
|
||||||
|
of Goods is expressly excluded. Any law or regulation which
|
||||||
|
provides that the language of a contract shall be construed
|
||||||
|
against the drafter shall not apply to this License. You agree
|
||||||
|
that You alone are responsible for compliance with the United
|
||||||
|
States export administration regulations (and the export control
|
||||||
|
laws and regulation of any other countries) when You use,
|
||||||
|
distribute or otherwise make available any Covered Software.
|
||||||
|
|
||||||
|
10. RESPONSIBILITY FOR CLAIMS.
|
||||||
|
|
||||||
|
As between Initial Developer and the Contributors, each party is
|
||||||
|
responsible for claims and damages arising, directly or
|
||||||
|
indirectly, out of its utilization of rights under this License
|
||||||
|
and You agree to work with Initial Developer and Contributors to
|
||||||
|
distribute such responsibility on an equitable basis. Nothing
|
||||||
|
herein is intended or shall be deemed to constitute any admission
|
||||||
|
of liability.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND
|
||||||
|
DISTRIBUTION LICENSE (CDDL)
|
||||||
|
|
||||||
|
For Covered Software in this distribution, this License shall
|
||||||
|
be governed by the laws of the State of California (excluding
|
||||||
|
conflict-of-law provisions).
|
||||||
|
|
||||||
|
Any litigation relating to this License shall be subject to the
|
||||||
|
jurisdiction of the Federal Courts of the Northern District of
|
||||||
|
California and the state courts of the State of California, with
|
||||||
|
venue lying in Santa Clara County, California.
|
24
1.0.1/README
Normal file
24
1.0.1/README
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
Portable libumem.
|
||||||
|
================
|
||||||
|
|
||||||
|
This is a port of Solaris libumem to non-Solaris systems.
|
||||||
|
|
||||||
|
The port was made while integrating libumem with our Ecelerity MTA product, so
|
||||||
|
your initial experience will not be 100% out-of-the-box, because there is no
|
||||||
|
standalone configure script for the library at this time. (patches welcome!)
|
||||||
|
|
||||||
|
In addition, since our deployment is threaded, we force the library into
|
||||||
|
threaded mode.
|
||||||
|
|
||||||
|
While the library is itself stable (it's the memory allocator used by the
|
||||||
|
Solaris OS), the port may have a few rough edges. We're shipping umem with
|
||||||
|
Linux and Windows versions of our product as we have found it to be stable.
|
||||||
|
|
||||||
|
We will continue to update this project as and when we make improvements, and
|
||||||
|
welcome third-party patches that improve the usability for everyone.
|
||||||
|
|
||||||
|
|
||||||
|
Wez Furlong,
|
||||||
|
Message Systems, Inc.
|
||||||
|
wez (at) messagesystems (dot) com
|
||||||
|
|
51
1.0.1/README-alpha
Normal file
51
1.0.1/README-alpha
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
This is the libumem package.
|
||||||
|
This document describes the actions needed to build the pre-release
|
||||||
|
or subversion version of the package. See end of file for copying conditions.
|
||||||
|
|
||||||
|
* Introduction
|
||||||
|
|
||||||
|
This is a *pre-release* version, and not ready for production use yet. If
|
||||||
|
you are taking source from subversion, you will need to have libtool, automake,
|
||||||
|
and autoconf installed to help contribute. See the chapter `Building' for the
|
||||||
|
detailed instructions. The script autogen.sh is provided to help autoconfigure
|
||||||
|
libumem from the cvs src. After you run autogen.sh, there should be a file
|
||||||
|
'INSTALL' with (generic) installation instructions. Package-specific
|
||||||
|
installation instructions are set forth in the file README.
|
||||||
|
|
||||||
|
Please, note that the accompanying documentation may be inaccurate or
|
||||||
|
incomplete. The subversion history is the authoritative documentation of all
|
||||||
|
recent changes.
|
||||||
|
|
||||||
|
Report bugs at https://labs.omniti.com/trac/portableumem/newticket
|
||||||
|
|
||||||
|
* Checking Out the Sources
|
||||||
|
|
||||||
|
The following instructions apply if you wish to obtain sources from
|
||||||
|
the subversion repository:
|
||||||
|
|
||||||
|
To checkout the source tree from subversion issue the following command:
|
||||||
|
|
||||||
|
svn co https://labs.omniti.com/portableumem/trunk portable-umem
|
||||||
|
|
||||||
|
* Building
|
||||||
|
|
||||||
|
In order to build this you will first need to have right versions
|
||||||
|
of autotools and some auxiliary GNU programs. At the time of this
|
||||||
|
writing these are:
|
||||||
|
|
||||||
|
Package Version (>=)
|
||||||
|
======== ============
|
||||||
|
automake 1.4
|
||||||
|
autoconf 2.50
|
||||||
|
libtool 1.5.0
|
||||||
|
|
||||||
|
To prepare the package for building run autogen.sh. Then run
|
||||||
|
./configure with the desired options (See INSTALL and README for the
|
||||||
|
detailed instructions). Finally, run make. Notice that the first make
|
||||||
|
of the package should be made in the source directory. Subsequent
|
||||||
|
makes can use build directory different from the source one.
|
||||||
|
|
||||||
|
* Copyright information:
|
||||||
|
|
||||||
|
Please see COPYRIGHT and OPENSOLARIS.LICENSE for the copyright
|
||||||
|
and license details.
|
19
1.0.1/TODO
Normal file
19
1.0.1/TODO
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
To-do List for the Linux port of umem
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
* Autconf'ery for <stdint.h> in "sol_compat.h".
|
||||||
|
|
||||||
|
* Fix #define wreakage for THR_RETURN, THR_API in "sol_compat.h".
|
||||||
|
|
||||||
|
* Replace use of Ecelerity's portable atomic locking header with something
|
||||||
|
equivalent in "sol_compat.h".
|
||||||
|
|
||||||
|
* ec_debug_vprintf -> something else?
|
||||||
|
|
||||||
|
* test suite.
|
||||||
|
|
||||||
|
* static library support.
|
||||||
|
|
||||||
|
* doxygen'ate the headers/code, to produce reference docs.
|
||||||
|
|
||||||
|
* HAVE_DOT in Doxyfile.in should be detected by configure.
|
3
1.0.1/autogen.sh
Executable file
3
1.0.1/autogen.sh
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
autoreconf -i -s
|
31
1.0.1/configure.ac
Normal file
31
1.0.1/configure.ac
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
AC_INIT([umem], [1.0.1], [], [umem])
|
||||||
|
AM_INIT_AUTOMAKE([dist-bzip2])
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
AM_PROG_AS
|
||||||
|
AC_PROG_LIBTOOL
|
||||||
|
|
||||||
|
AC_C_INLINE
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether pthread_mutex_t is larger than 24 bytes])
|
||||||
|
AC_TRY_RUN(
|
||||||
|
[
|
||||||
|
#include <pthread.h>
|
||||||
|
int main(void){return (sizeof(pthread_mutex_t) > 24);}
|
||||||
|
],
|
||||||
|
[AC_MSG_RESULT(yes)],
|
||||||
|
[
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
AC_DEFINE(UMEM_PTHREAD_MUTEX_TOO_BIG, [1], [need bigger cache])
|
||||||
|
AC_MSG_WARN([*** increasing umem cpu cache size to compensate.])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
AC_CHECK_HEADERS([sys/mman.h sys/sysmacros.h sys/time.h malloc.h])
|
||||||
|
AC_CHECK_FUNCS([issetugid mallinfo malloc_stats])
|
||||||
|
|
||||||
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
AC_CONFIG_FILES([Makefile Doxyfile umem.spec])
|
||||||
|
|
||||||
|
AC_OUTPUT
|
714
1.0.1/envvar.c
Normal file
714
1.0.1/envvar.c
Normal file
|
@ -0,0 +1,714 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)envvar.c 1.5 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#if HAVE_DLFCN_H
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "umem_base.h"
|
||||||
|
#include "vmem_base.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A umem environment variable, like UMEM_DEBUG, is set to a series
|
||||||
|
* of items, seperated by ',':
|
||||||
|
*
|
||||||
|
* UMEM_DEBUG="audit=10,guards,firewall=512"
|
||||||
|
*
|
||||||
|
* This structure describes items. Each item has a name, type, and
|
||||||
|
* description. During processing, an item read from the user may
|
||||||
|
* be either "valid" or "invalid".
|
||||||
|
*
|
||||||
|
* A valid item has an argument, if required, and it is of the right
|
||||||
|
* form (doesn't overflow, doesn't contain any unexpected characters).
|
||||||
|
*
|
||||||
|
* If the item is valid, item_flag_target != NULL, and:
|
||||||
|
* type is not CLEARFLAG, then (*item_flag_target) |= item_flag_value
|
||||||
|
* type is CLEARFLAG, then (*item_flag_target) &= ~item_flag_value
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define UMEM_ENV_ITEM_MAX 512
|
||||||
|
|
||||||
|
struct umem_env_item;
|
||||||
|
|
||||||
|
typedef int arg_process_t(const struct umem_env_item *item, const char *value);
|
||||||
|
#define ARG_SUCCESS 0 /* processing successful */
|
||||||
|
#define ARG_BAD 1 /* argument had a bad value */
|
||||||
|
|
||||||
|
typedef struct umem_env_item {
|
||||||
|
const char *item_name; /* tag in environment variable */
|
||||||
|
const char *item_interface_stability;
|
||||||
|
enum {
|
||||||
|
ITEM_INVALID,
|
||||||
|
ITEM_FLAG, /* only a flag. No argument allowed */
|
||||||
|
ITEM_CLEARFLAG, /* only a flag, but clear instead of set */
|
||||||
|
ITEM_OPTUINT, /* optional integer argument */
|
||||||
|
ITEM_UINT, /* required integer argument */
|
||||||
|
ITEM_OPTSIZE, /* optional size_t argument */
|
||||||
|
ITEM_SIZE, /* required size_t argument */
|
||||||
|
ITEM_SPECIAL /* special argument processing */
|
||||||
|
} item_type;
|
||||||
|
const char *item_description;
|
||||||
|
uint_t *item_flag_target; /* the variable containing the flag */
|
||||||
|
uint_t item_flag_value; /* the value to OR in */
|
||||||
|
uint_t *item_uint_target; /* the variable to hold the integer */
|
||||||
|
size_t *item_size_target;
|
||||||
|
arg_process_t *item_special; /* callback for special handling */
|
||||||
|
} umem_env_item_t;
|
||||||
|
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
static arg_process_t umem_backend_process;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
/* replace getenv() with a specialized version that doesn't
|
||||||
|
* need to allocate memory. We can't use strlen or strcmp
|
||||||
|
* here. */
|
||||||
|
#include <unistd.h>
|
||||||
|
static char *safe_getenv(const char *name)
|
||||||
|
{
|
||||||
|
int i, l;
|
||||||
|
for (l = 0; name[l]; l++)
|
||||||
|
;
|
||||||
|
for (i = 0; __environ[i]; i++) {
|
||||||
|
if (!memcmp(__environ[i], name, l) && __environ[i][l] == '=') {
|
||||||
|
return &__environ[i][l+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#define getenv(x) safe_getenv(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static arg_process_t umem_log_process;
|
||||||
|
|
||||||
|
const char *____umem_environ_msg_options = "-- UMEM_OPTIONS --";
|
||||||
|
|
||||||
|
static umem_env_item_t umem_options_items[] = {
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
{ "backend", "Evolving", ITEM_SPECIAL,
|
||||||
|
"=sbrk for sbrk(2), =mmap for mmap(2)",
|
||||||
|
NULL, 0, NULL, NULL,
|
||||||
|
&umem_backend_process
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ "concurrency", "Private", ITEM_UINT,
|
||||||
|
"Max concurrency",
|
||||||
|
NULL, 0, &umem_max_ncpus
|
||||||
|
},
|
||||||
|
{ "max_contention", "Private", ITEM_UINT,
|
||||||
|
"Maximum contention in a reap interval before the depot is "
|
||||||
|
"resized.",
|
||||||
|
NULL, 0, &umem_depot_contention
|
||||||
|
},
|
||||||
|
{ "nomagazines", "Private", ITEM_FLAG,
|
||||||
|
"no caches will be multithreaded, and no caching will occur.",
|
||||||
|
&umem_flags, UMF_NOMAGAZINE
|
||||||
|
},
|
||||||
|
{ "reap_interval", "Private", ITEM_UINT,
|
||||||
|
"Minimum time between reaps and updates, in seconds.",
|
||||||
|
NULL, 0, &umem_reap_interval
|
||||||
|
},
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
{ "sbrk_pagesize", "Private", ITEM_SIZE,
|
||||||
|
"The preferred page size for the sbrk(2) heap.",
|
||||||
|
NULL, 0, NULL, &vmem_sbrk_pagesize
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{ NULL, "-- end of UMEM_OPTIONS --", ITEM_INVALID }
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *____umem_environ_msg_debug = "-- UMEM_DEBUG --";
|
||||||
|
|
||||||
|
static umem_env_item_t umem_debug_items[] = {
|
||||||
|
{ "default", "Unstable", ITEM_FLAG,
|
||||||
|
"audit,contents,guards",
|
||||||
|
&umem_flags,
|
||||||
|
UMF_AUDIT | UMF_CONTENTS | UMF_DEADBEEF | UMF_REDZONE
|
||||||
|
},
|
||||||
|
{ "audit", "Unstable", ITEM_OPTUINT,
|
||||||
|
"Enable auditing. optionally =frames to set the number of "
|
||||||
|
"stored stack frames",
|
||||||
|
&umem_flags, UMF_AUDIT, &umem_stack_depth
|
||||||
|
},
|
||||||
|
{ "contents", "Unstable", ITEM_OPTSIZE,
|
||||||
|
"Enable contents storing. UMEM_LOGGING=contents also "
|
||||||
|
"required. optionally =bytes to set the number of stored "
|
||||||
|
"bytes",
|
||||||
|
&umem_flags, UMF_CONTENTS, NULL, &umem_content_maxsave
|
||||||
|
},
|
||||||
|
{ "guards", "Unstable", ITEM_FLAG,
|
||||||
|
"Enables guards and special patterns",
|
||||||
|
&umem_flags, UMF_DEADBEEF | UMF_REDZONE
|
||||||
|
},
|
||||||
|
{ "verbose", "Unstable", ITEM_FLAG,
|
||||||
|
"Enables writing error messages to stderr",
|
||||||
|
&umem_output, 1
|
||||||
|
},
|
||||||
|
|
||||||
|
{ "nosignal", "Private", ITEM_FLAG,
|
||||||
|
"Abort if called from a signal handler. Turns on 'audit'. "
|
||||||
|
"Note that this is not always a bug.",
|
||||||
|
&umem_flags, UMF_AUDIT | UMF_CHECKSIGNAL
|
||||||
|
},
|
||||||
|
{ "firewall", "Private", ITEM_SIZE,
|
||||||
|
"=minbytes. Every object >= minbytes in size will have its "
|
||||||
|
"end against an unmapped page",
|
||||||
|
&umem_flags, UMF_FIREWALL, NULL, &umem_minfirewall
|
||||||
|
},
|
||||||
|
{ "lite", "Private", ITEM_FLAG,
|
||||||
|
"debugging-lite",
|
||||||
|
&umem_flags, UMF_LITE
|
||||||
|
},
|
||||||
|
{ "maxverify", "Private", ITEM_SIZE,
|
||||||
|
"=maxbytes, Maximum bytes to check when 'guards' is active. "
|
||||||
|
"Normally all bytes are checked.",
|
||||||
|
NULL, 0, NULL, &umem_maxverify
|
||||||
|
},
|
||||||
|
{ "noabort", "Private", ITEM_CLEARFLAG,
|
||||||
|
"umem will not abort when a recoverable error occurs "
|
||||||
|
"(i.e. double frees, certain kinds of corruption)",
|
||||||
|
&umem_abort, 1
|
||||||
|
},
|
||||||
|
{ "mtbf", "Private", ITEM_UINT,
|
||||||
|
"=mtbf, the mean time between injected failures. Works best "
|
||||||
|
"if prime.\n",
|
||||||
|
NULL, 0, &umem_mtbf
|
||||||
|
},
|
||||||
|
{ "random", "Private", ITEM_FLAG,
|
||||||
|
"randomize flags on a per-cache basis",
|
||||||
|
&umem_flags, UMF_RANDOMIZE
|
||||||
|
},
|
||||||
|
{ "allverbose", "Private", ITEM_FLAG,
|
||||||
|
"Enables writing all logged messages to stderr",
|
||||||
|
&umem_output, 2
|
||||||
|
},
|
||||||
|
|
||||||
|
{ NULL, "-- end of UMEM_DEBUG --", ITEM_INVALID }
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *____umem_environ_msg_logging = "-- UMEM_LOGGING --";
|
||||||
|
|
||||||
|
static umem_env_item_t umem_logging_items[] = {
|
||||||
|
{ "transaction", "Unstable", ITEM_SPECIAL,
|
||||||
|
"If 'audit' is set in UMEM_DEBUG, the audit structures "
|
||||||
|
"from previous transactions are entered into this log.",
|
||||||
|
NULL, 0, NULL,
|
||||||
|
&umem_transaction_log_size, &umem_log_process
|
||||||
|
},
|
||||||
|
{ "contents", "Unstable", ITEM_SPECIAL,
|
||||||
|
"If 'audit' is set in UMEM_DEBUG, the contents of objects "
|
||||||
|
"are recorded in this log as they are freed. If the "
|
||||||
|
"'contents' option is not set in UMEM_DEBUG, the first "
|
||||||
|
"256 bytes of each freed buffer will be saved.",
|
||||||
|
&umem_flags, UMF_CONTENTS, NULL,
|
||||||
|
&umem_content_log_size, &umem_log_process
|
||||||
|
},
|
||||||
|
{ "fail", "Unstable", ITEM_SPECIAL,
|
||||||
|
"Records are entered into this log for every failed "
|
||||||
|
"allocation.",
|
||||||
|
NULL, 0, NULL,
|
||||||
|
&umem_failure_log_size, &umem_log_process
|
||||||
|
},
|
||||||
|
|
||||||
|
{ "slab", "Private", ITEM_SPECIAL,
|
||||||
|
"Every slab created will be entered into this log.",
|
||||||
|
NULL, 0, NULL,
|
||||||
|
&umem_slab_log_size, &umem_log_process
|
||||||
|
},
|
||||||
|
|
||||||
|
{ NULL, "-- end of UMEM_LOGGING --", ITEM_INVALID }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct umem_envvar {
|
||||||
|
const char *env_name;
|
||||||
|
const char *env_func;
|
||||||
|
umem_env_item_t *env_item_list;
|
||||||
|
const char *env_getenv_result;
|
||||||
|
const char *env_func_result;
|
||||||
|
} umem_envvar_t;
|
||||||
|
|
||||||
|
static umem_envvar_t umem_envvars[] = {
|
||||||
|
{ "UMEM_DEBUG", "_umem_debug_init", umem_debug_items },
|
||||||
|
{ "UMEM_OPTIONS", "_umem_options_init", umem_options_items },
|
||||||
|
{ "UMEM_LOGGING", "_umem_logging_init", umem_logging_items },
|
||||||
|
{ NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static umem_envvar_t *env_current;
|
||||||
|
#define CURRENT (env_current->env_name)
|
||||||
|
|
||||||
|
static int
|
||||||
|
empty(const char *str)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while ((c = *str) != '\0' && isspace(c))
|
||||||
|
str++;
|
||||||
|
|
||||||
|
return (*str == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
item_uint_process(const umem_env_item_t *item, const char *item_arg)
|
||||||
|
{
|
||||||
|
ulong_t result;
|
||||||
|
char *endptr = "";
|
||||||
|
int olderrno;
|
||||||
|
|
||||||
|
olderrno = errno;
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
if (empty(item_arg)) {
|
||||||
|
goto badnumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = strtoul(item_arg, &endptr, 10);
|
||||||
|
|
||||||
|
if (result == ULONG_MAX && errno == ERANGE) {
|
||||||
|
errno = olderrno;
|
||||||
|
goto overflow;
|
||||||
|
}
|
||||||
|
errno = olderrno;
|
||||||
|
|
||||||
|
if (*endptr != '\0')
|
||||||
|
goto badnumber;
|
||||||
|
if ((uint_t)result != result)
|
||||||
|
goto overflow;
|
||||||
|
|
||||||
|
(*item->item_uint_target) = (uint_t)result;
|
||||||
|
return (ARG_SUCCESS);
|
||||||
|
|
||||||
|
badnumber:
|
||||||
|
log_message("%s: %s: not a number\n", CURRENT, item->item_name);
|
||||||
|
return (ARG_BAD);
|
||||||
|
|
||||||
|
overflow:
|
||||||
|
log_message("%s: %s: overflowed\n", CURRENT, item->item_name);
|
||||||
|
return (ARG_BAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
item_size_process(const umem_env_item_t *item, const char *item_arg)
|
||||||
|
{
|
||||||
|
ulong_t result;
|
||||||
|
ulong_t result_arg;
|
||||||
|
char *endptr = "";
|
||||||
|
int olderrno;
|
||||||
|
|
||||||
|
if (empty(item_arg))
|
||||||
|
goto badnumber;
|
||||||
|
|
||||||
|
olderrno = errno;
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
result_arg = strtoul(item_arg, &endptr, 10);
|
||||||
|
|
||||||
|
if (result_arg == ULONG_MAX && errno == ERANGE) {
|
||||||
|
errno = olderrno;
|
||||||
|
goto overflow;
|
||||||
|
}
|
||||||
|
errno = olderrno;
|
||||||
|
|
||||||
|
result = result_arg;
|
||||||
|
|
||||||
|
switch (*endptr) {
|
||||||
|
case 't':
|
||||||
|
case 'T':
|
||||||
|
result *= 1024;
|
||||||
|
if (result < result_arg)
|
||||||
|
goto overflow;
|
||||||
|
/*FALLTHRU*/
|
||||||
|
case 'g':
|
||||||
|
case 'G':
|
||||||
|
result *= 1024;
|
||||||
|
if (result < result_arg)
|
||||||
|
goto overflow;
|
||||||
|
/*FALLTHRU*/
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
result *= 1024;
|
||||||
|
if (result < result_arg)
|
||||||
|
goto overflow;
|
||||||
|
/*FALLTHRU*/
|
||||||
|
case 'k':
|
||||||
|
case 'K':
|
||||||
|
result *= 1024;
|
||||||
|
if (result < result_arg)
|
||||||
|
goto overflow;
|
||||||
|
endptr++; /* skip over the size character */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break; /* handled later */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*endptr != '\0')
|
||||||
|
goto badnumber;
|
||||||
|
|
||||||
|
(*item->item_size_target) = result;
|
||||||
|
return (ARG_SUCCESS);
|
||||||
|
|
||||||
|
badnumber:
|
||||||
|
log_message("%s: %s: not a number\n", CURRENT, item->item_name);
|
||||||
|
return (ARG_BAD);
|
||||||
|
|
||||||
|
overflow:
|
||||||
|
log_message("%s: %s: overflowed\n", CURRENT, item->item_name);
|
||||||
|
return (ARG_BAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
umem_log_process(const umem_env_item_t *item, const char *item_arg)
|
||||||
|
{
|
||||||
|
if (item_arg != NULL) {
|
||||||
|
int ret;
|
||||||
|
ret = item_size_process(item, item_arg);
|
||||||
|
if (ret != ARG_SUCCESS)
|
||||||
|
return (ret);
|
||||||
|
|
||||||
|
if (*item->item_size_target == 0)
|
||||||
|
return (ARG_SUCCESS);
|
||||||
|
} else
|
||||||
|
*item->item_size_target = 64*1024;
|
||||||
|
|
||||||
|
umem_logging = 1;
|
||||||
|
return (ARG_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
static int
|
||||||
|
umem_backend_process(const umem_env_item_t *item, const char *item_arg)
|
||||||
|
{
|
||||||
|
const char *name = item->item_name;
|
||||||
|
|
||||||
|
if (item_arg == NULL)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (strcmp(item_arg, "sbrk") == 0)
|
||||||
|
vmem_backend |= VMEM_BACKEND_SBRK;
|
||||||
|
else if (strcmp(item_arg, "mmap") == 0)
|
||||||
|
vmem_backend |= VMEM_BACKEND_MMAP;
|
||||||
|
else
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return (ARG_SUCCESS);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
log_message("%s: %s: must be %s=sbrk or %s=mmap\n",
|
||||||
|
CURRENT, name, name, name);
|
||||||
|
return (ARG_BAD);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
process_item(const umem_env_item_t *item, const char *item_arg)
|
||||||
|
{
|
||||||
|
int arg_required = 0;
|
||||||
|
arg_process_t *processor;
|
||||||
|
|
||||||
|
switch (item->item_type) {
|
||||||
|
case ITEM_FLAG:
|
||||||
|
case ITEM_CLEARFLAG:
|
||||||
|
case ITEM_OPTUINT:
|
||||||
|
case ITEM_OPTSIZE:
|
||||||
|
case ITEM_SPECIAL:
|
||||||
|
arg_required = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ITEM_UINT:
|
||||||
|
case ITEM_SIZE:
|
||||||
|
arg_required = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (item->item_type) {
|
||||||
|
case ITEM_FLAG:
|
||||||
|
case ITEM_CLEARFLAG:
|
||||||
|
if (item_arg != NULL) {
|
||||||
|
log_message("%s: %s: does not take a value. ignored\n",
|
||||||
|
CURRENT, item->item_name);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
processor = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ITEM_UINT:
|
||||||
|
case ITEM_OPTUINT:
|
||||||
|
processor = item_uint_process;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ITEM_SIZE:
|
||||||
|
case ITEM_OPTSIZE:
|
||||||
|
processor = item_size_process;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ITEM_SPECIAL:
|
||||||
|
processor = item->item_special;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_message("%s: %s: Invalid type. Ignored\n",
|
||||||
|
CURRENT, item->item_name);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg_required && item_arg == NULL) {
|
||||||
|
log_message("%s: %s: Required value missing\n",
|
||||||
|
CURRENT, item->item_name);
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item_arg != NULL || item->item_type == ITEM_SPECIAL) {
|
||||||
|
if (processor(item, item_arg) != ARG_SUCCESS)
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->item_flag_target) {
|
||||||
|
if (item->item_type == ITEM_CLEARFLAG)
|
||||||
|
(*item->item_flag_target) &= ~item->item_flag_value;
|
||||||
|
else
|
||||||
|
(*item->item_flag_target) |= item->item_flag_value;
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
invalid:
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ENV_SHORT_BYTES 10 /* bytes to print on error */
|
||||||
|
void
|
||||||
|
umem_process_value(umem_env_item_t *item_list, const char *beg, const char *end)
|
||||||
|
{
|
||||||
|
char buf[UMEM_ENV_ITEM_MAX];
|
||||||
|
char *argptr;
|
||||||
|
|
||||||
|
size_t count;
|
||||||
|
|
||||||
|
while (beg < end && isspace(*beg))
|
||||||
|
beg++;
|
||||||
|
|
||||||
|
while (beg < end && isspace(*(end - 1)))
|
||||||
|
end--;
|
||||||
|
|
||||||
|
if (beg >= end) {
|
||||||
|
log_message("%s: empty option\n", CURRENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = end - beg;
|
||||||
|
|
||||||
|
if (count + 1 > sizeof (buf)) {
|
||||||
|
char outbuf[ENV_SHORT_BYTES + 1];
|
||||||
|
/*
|
||||||
|
* Have to do this, since sprintf("%10s",...) calls malloc()
|
||||||
|
*/
|
||||||
|
(void) strncpy(outbuf, beg, ENV_SHORT_BYTES);
|
||||||
|
outbuf[ENV_SHORT_BYTES] = 0;
|
||||||
|
|
||||||
|
log_message("%s: argument \"%s...\" too long\n", CURRENT,
|
||||||
|
outbuf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) strncpy(buf, beg, count);
|
||||||
|
buf[count] = 0;
|
||||||
|
|
||||||
|
argptr = strchr(buf, '=');
|
||||||
|
|
||||||
|
if (argptr != NULL)
|
||||||
|
*argptr++ = 0;
|
||||||
|
|
||||||
|
for (; item_list->item_name != NULL; item_list++) {
|
||||||
|
if (strcmp(buf, item_list->item_name) == 0) {
|
||||||
|
(void) process_item(item_list, argptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log_message("%s: '%s' not recognized\n", CURRENT, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
void
|
||||||
|
umem_setup_envvars(int invalid)
|
||||||
|
{
|
||||||
|
umem_envvar_t *cur_env;
|
||||||
|
static volatile enum {
|
||||||
|
STATE_START,
|
||||||
|
STATE_GETENV,
|
||||||
|
STATE_DLOPEN,
|
||||||
|
STATE_DLSYM,
|
||||||
|
STATE_FUNC,
|
||||||
|
STATE_DONE
|
||||||
|
} state = STATE_START;
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
void *h;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (invalid) {
|
||||||
|
const char *where;
|
||||||
|
/*
|
||||||
|
* One of the calls below invoked malloc() recursively. We
|
||||||
|
* remove any partial results and return.
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case STATE_START:
|
||||||
|
where = "before getenv(3C) calls -- "
|
||||||
|
"getenv(3C) results ignored.";
|
||||||
|
break;
|
||||||
|
case STATE_GETENV:
|
||||||
|
where = "during getenv(3C) calls -- "
|
||||||
|
"getenv(3C) results ignored.";
|
||||||
|
break;
|
||||||
|
case STATE_DLOPEN:
|
||||||
|
where = "during dlopen(3C) call -- "
|
||||||
|
"_umem_*() results ignored.";
|
||||||
|
break;
|
||||||
|
case STATE_DLSYM:
|
||||||
|
where = "during dlsym(3C) call -- "
|
||||||
|
"_umem_*() results ignored.";
|
||||||
|
break;
|
||||||
|
case STATE_FUNC:
|
||||||
|
where = "during _umem_*() call -- "
|
||||||
|
"_umem_*() results ignored.";
|
||||||
|
break;
|
||||||
|
case STATE_DONE:
|
||||||
|
where = "after dlsym() or _umem_*() calls.";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
where = "at unknown point -- "
|
||||||
|
"_umem_*() results ignored.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_message("recursive allocation %s\n", where);
|
||||||
|
|
||||||
|
for (cur_env = umem_envvars; cur_env->env_name != NULL;
|
||||||
|
cur_env++) {
|
||||||
|
if (state == STATE_GETENV)
|
||||||
|
cur_env->env_getenv_result = NULL;
|
||||||
|
if (state != STATE_DONE)
|
||||||
|
cur_env->env_func_result = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = STATE_DONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = STATE_GETENV;
|
||||||
|
|
||||||
|
for (cur_env = umem_envvars; cur_env->env_name != NULL; cur_env++) {
|
||||||
|
cur_env->env_getenv_result = getenv(cur_env->env_name);
|
||||||
|
if (state == STATE_DONE)
|
||||||
|
return; /* recursed */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define dlopen(a, b) GetModuleHandle(NULL)
|
||||||
|
# define dlsym(a, b) GetProcAddress((HANDLE)a, b)
|
||||||
|
# define dlclose(a) 0
|
||||||
|
# define dlerror() 0
|
||||||
|
#endif
|
||||||
|
state = STATE_DLOPEN;
|
||||||
|
/* get a handle to the "a.out" object */
|
||||||
|
if ((h = dlopen(0, RTLD_FIRST | RTLD_LAZY)) != NULL) {
|
||||||
|
for (cur_env = umem_envvars; cur_env->env_name != NULL;
|
||||||
|
cur_env++) {
|
||||||
|
const char *(*func)(void);
|
||||||
|
const char *value;
|
||||||
|
|
||||||
|
state = STATE_DLSYM;
|
||||||
|
func = (const char *(*)(void))dlsym(h,
|
||||||
|
cur_env->env_func);
|
||||||
|
|
||||||
|
if (state == STATE_DONE)
|
||||||
|
break; /* recursed */
|
||||||
|
|
||||||
|
state = STATE_FUNC;
|
||||||
|
if (func != NULL) {
|
||||||
|
value = func();
|
||||||
|
if (state == STATE_DONE)
|
||||||
|
break; /* recursed */
|
||||||
|
cur_env->env_func_result = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) dlclose(h);
|
||||||
|
} else {
|
||||||
|
(void) dlerror(); /* snarf dlerror() */
|
||||||
|
}
|
||||||
|
#endif /* UMEM_STANDALONE */
|
||||||
|
|
||||||
|
state = STATE_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process the environment variables.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
umem_process_envvars(void)
|
||||||
|
{
|
||||||
|
const char *value;
|
||||||
|
const char *end, *next;
|
||||||
|
umem_envvar_t *cur_env;
|
||||||
|
|
||||||
|
for (cur_env = umem_envvars; cur_env->env_name != NULL; cur_env++) {
|
||||||
|
env_current = cur_env;
|
||||||
|
|
||||||
|
value = cur_env->env_getenv_result;
|
||||||
|
if (value == NULL)
|
||||||
|
value = cur_env->env_func_result;
|
||||||
|
|
||||||
|
/* ignore if missing or empty */
|
||||||
|
if (value == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (end = value; *end != '\0'; value = next) {
|
||||||
|
end = strchr(value, ',');
|
||||||
|
if (end != NULL)
|
||||||
|
next = end + 1; /* skip the comma */
|
||||||
|
else
|
||||||
|
next = end = value + strlen(value);
|
||||||
|
|
||||||
|
umem_process_value(cur_env->env_item_list, value, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
1.0.1/gdb-macros
Normal file
117
1.0.1/gdb-macros
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
# vim:ft=gdb:ts=2:sw=2:et:
|
||||||
|
|
||||||
|
set $UMF_AUDIT = 1
|
||||||
|
set $UMF_DEADBEEF = 2
|
||||||
|
set $UMF_REDZONE = 4
|
||||||
|
set $UMF_CONTENTS = 8
|
||||||
|
set $UMF_CHECKSIGNAL = 16
|
||||||
|
set $UMF_NOMAGAZINE = 32
|
||||||
|
set $UMF_FIREWALL = 64
|
||||||
|
set $UMF_LITE = 128
|
||||||
|
set $UMF_HASH = 256
|
||||||
|
set $UMF_RANDOMIZE = 512
|
||||||
|
|
||||||
|
define umastat_cache
|
||||||
|
set $cp = $arg0
|
||||||
|
set $meminuse = ($cp->cache_slab_create - $cp->cache_slab_destroy) * $cp->cache_slabsize
|
||||||
|
|
||||||
|
if (($cp->cache_cpu[0].cc_magsize != 0) || ($cp->cache_flags & $UMF_NOMAGAZINE))
|
||||||
|
set $magsize = $cp->cache_cpu[0].cc_magsize
|
||||||
|
else
|
||||||
|
set $magsize = $cp->cache_magtype->mt_magsize
|
||||||
|
end
|
||||||
|
|
||||||
|
set $alloc = $cp->cache_slab_alloc + $cp->cache_full.ml_alloc
|
||||||
|
set $avail = $cp->cache_full.ml_total * $magsize
|
||||||
|
set $total = $cp->cache_buftotal
|
||||||
|
|
||||||
|
# walk the cpu caches
|
||||||
|
set $cpu_current = 0
|
||||||
|
while $cpu_current < umem_max_ncpus
|
||||||
|
set $cpu = umem_cpus[$cpu_current]
|
||||||
|
set $cpu_cache = (umem_cpu_cache_t*)((char*)$cp + $cpu->cpu_cache_offset)
|
||||||
|
|
||||||
|
if $cpu_cache->cc_rounds > 0
|
||||||
|
set $avail = $avail + $cpu_cache->cc_rounds
|
||||||
|
end
|
||||||
|
if $cpu_cache->cc_prounds > 0
|
||||||
|
set $avail = $avail + $cpu_cache->cc_prounds
|
||||||
|
end
|
||||||
|
set $alloc = $alloc + $cpu_cache->cc_alloc
|
||||||
|
|
||||||
|
set $cpu_current = $cpu_current + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# walk some slabs
|
||||||
|
set $slab = $cp->cache_nullslab.slab_next
|
||||||
|
while $slab != &$cp->cache_nullslab
|
||||||
|
set $avail = $avail + $slab->slab_chunks - $slab->slab_refcnt
|
||||||
|
set $slab = $slab->slab_next
|
||||||
|
end
|
||||||
|
|
||||||
|
printf "%-25s %6u %6u %6u %9u %9u %5llu\n", $cp->cache_name, $cp->cache_bufsize, $total - $avail, $total, $meminuse, $alloc, $cp->cache_alloc_fail
|
||||||
|
end
|
||||||
|
|
||||||
|
document umastat
|
||||||
|
umem allocator stats
|
||||||
|
end
|
||||||
|
|
||||||
|
define umastat
|
||||||
|
printf "cache buf buf buf memory alloc alloc\n"
|
||||||
|
printf "name size in use total in use succeed fail\n"
|
||||||
|
printf "---------------------------- ------ ------ ------ --------- --------- -----\n"
|
||||||
|
set $cp = umem_null_cache->cache_next
|
||||||
|
while $cp != &umem_null_cache
|
||||||
|
umastat_cache $cp
|
||||||
|
set $cp = $cp->cache_next
|
||||||
|
end
|
||||||
|
printf "---------------------------- ------ ------ ------ --------- --------- -----\n"
|
||||||
|
set $vmem = vmem_list
|
||||||
|
while $vmem != 0
|
||||||
|
set $meminuse = 0
|
||||||
|
set $alloc = 0
|
||||||
|
set $fail = 0
|
||||||
|
set $cp = umem_null_cache->cache_next
|
||||||
|
while $cp != &umem_null_cache
|
||||||
|
if $cp->cache_arena == $vmem
|
||||||
|
set $meminuse = $meminuse + (($cp->cache_slab_create - $cp->cache_slab_destroy) * $cp->cache_slabsize)
|
||||||
|
|
||||||
|
if (($cp->cache_cpu[0].cc_magsize != 0) || ($cp->cache_flags & $UMF_NOMAGAZINE))
|
||||||
|
set $magsize = $cp->cache_cpu[0].cc_magsize
|
||||||
|
else
|
||||||
|
set $magsize = $cp->cache_magtype->mt_magsize
|
||||||
|
end
|
||||||
|
|
||||||
|
set $alloc = $alloc + ($cp->cache_slab_alloc + $cp->cache_full.ml_alloc)
|
||||||
|
set $avail = $avail + ($cp->cache_full.ml_total * $magsize)
|
||||||
|
end
|
||||||
|
set $cp = $cp->cache_next
|
||||||
|
end
|
||||||
|
printf "Total %-25s %9u %9u %5u\n", $vmem->vm_name, $meminuse, $alloc, $fail
|
||||||
|
set $vmem = $vmem->vm_next
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
define umem_status
|
||||||
|
printf "Concurrency:\t%d\n", umem_max_ncpus
|
||||||
|
printf "Logs\t\t"
|
||||||
|
if umem_transaction_log != 0
|
||||||
|
printf "transaction=%d ", umem_transaction_log->lh_chunksize * umem_transaction_log->lh_nchunks
|
||||||
|
end
|
||||||
|
if umem_content_log != 0
|
||||||
|
printf "content=%d ", umem_content_log->lh_chunksize * umem_content_log->lh_nchunks
|
||||||
|
end
|
||||||
|
if umem_failure_log != 0
|
||||||
|
printf "fail=%d ", umem_failure_log->lh_chunksize * umem_failure_log->lh_nchunks
|
||||||
|
end
|
||||||
|
if umem_slab_log != 0
|
||||||
|
printf "slab=%d ", umem_slab_log->lh_chunksize * umem_slab_log->lh_nchunks
|
||||||
|
end
|
||||||
|
if umem_logging == 0
|
||||||
|
printf "(inactive)"
|
||||||
|
end
|
||||||
|
printf "\nMessage buffer:\n"
|
||||||
|
set $msg = &umem_error_buffer + umem_error_begin
|
||||||
|
printf "%s", $msg
|
||||||
|
end
|
||||||
|
|
211
1.0.1/getpcstack.c
Normal file
211
1.0.1/getpcstack.c
Normal file
|
@ -0,0 +1,211 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)getpcstack.c 1.5 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
#if HAVE_UCONTEXT_H
|
||||||
|
#include <ucontext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_SYS_FRAME_H
|
||||||
|
#include <sys/frame.h>
|
||||||
|
#endif
|
||||||
|
#if HAVE_SYS_STACK_H
|
||||||
|
#include <sys/stack.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#if defined(__MACH__)
|
||||||
|
/*
|
||||||
|
* Darwin doesn't have any exposed frame info, so give it some space.
|
||||||
|
*/
|
||||||
|
#define UMEM_FRAMESIZE (2 * sizeof(long long))
|
||||||
|
|
||||||
|
#elif defined(__sparc) || defined(__sparcv9)
|
||||||
|
extern void flush_windows(void);
|
||||||
|
#define UMEM_FRAMESIZE MINFRAME
|
||||||
|
|
||||||
|
#elif defined(__i386) || defined(__amd64)
|
||||||
|
/*
|
||||||
|
* On x86, MINFRAME is defined to be 0, but we want to be sure we can
|
||||||
|
* dereference the entire frame structure.
|
||||||
|
*/
|
||||||
|
#define UMEM_FRAMESIZE (sizeof (struct frame))
|
||||||
|
|
||||||
|
#elif !defined(EC_UMEM_DUMMY_PCSTACK)
|
||||||
|
#error needs update for new architecture
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a pc-only stacktrace. Used for kmem_alloc() buffer ownership tracking.
|
||||||
|
* Returns MIN(current stack depth, pcstack_limit).
|
||||||
|
*/
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
getpcstack(uintptr_t *pcstack, int pcstack_limit, int check_signal)
|
||||||
|
{
|
||||||
|
#ifdef EC_UMEM_DUMMY_PCSTACK
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
struct frame *fp;
|
||||||
|
struct frame *nextfp, *minfp;
|
||||||
|
int depth = 0;
|
||||||
|
uintptr_t base = 0;
|
||||||
|
size_t size = 0;
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
int on_altstack = 0;
|
||||||
|
uintptr_t sigbase = 0;
|
||||||
|
size_t sigsize = 0;
|
||||||
|
|
||||||
|
stack_t st;
|
||||||
|
|
||||||
|
if (stack_getbounds(&st) != 0) {
|
||||||
|
if (thr_stksegment(&st) != 0 ||
|
||||||
|
(uintptr_t)st.ss_sp < st.ss_size) {
|
||||||
|
return (0); /* unable to get stack bounds */
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* thr_stksegment(3C) has a slightly different interface than
|
||||||
|
* stack_getbounds(3C) -- correct it
|
||||||
|
*/
|
||||||
|
st.ss_sp = (void *)(((uintptr_t)st.ss_sp) - st.ss_size);
|
||||||
|
st.ss_flags = 0; /* can't be on-stack */
|
||||||
|
}
|
||||||
|
on_altstack = (st.ss_flags & SS_ONSTACK);
|
||||||
|
|
||||||
|
if (st.ss_size != 0) {
|
||||||
|
base = (uintptr_t)st.ss_sp;
|
||||||
|
size = st.ss_size;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If size == 0, then ss_sp is the *top* of the stack.
|
||||||
|
*
|
||||||
|
* Since we only allow increasing frame pointers, and we
|
||||||
|
* know our caller set his up correctly, we can treat ss_sp
|
||||||
|
* as an upper bound safely.
|
||||||
|
*/
|
||||||
|
base = 0;
|
||||||
|
size = (uintptr_t)st.ss_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_signal != 0) {
|
||||||
|
void (*sigfunc)() = NULL;
|
||||||
|
int sigfuncsize = 0;
|
||||||
|
extern void thr_sighndlrinfo(void (**)(), int *);
|
||||||
|
|
||||||
|
thr_sighndlrinfo(&sigfunc, &sigfuncsize);
|
||||||
|
sigbase = (uintptr_t)sigfunc;
|
||||||
|
sigsize = sigfuncsize;
|
||||||
|
}
|
||||||
|
#else /* UMEM_STANDALONE */
|
||||||
|
base = (uintptr_t)umem_min_stack;
|
||||||
|
size = umem_max_stack - umem_min_stack;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* shorten size so that fr_savfp and fr_savpc will be within the stack
|
||||||
|
* bounds.
|
||||||
|
*/
|
||||||
|
if (size >= UMEM_FRAMESIZE - 1)
|
||||||
|
size -= (UMEM_FRAMESIZE - 1);
|
||||||
|
else
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
#if defined(__sparc) || defined(__sparcv9)
|
||||||
|
flush_windows();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* LINTED alignment */
|
||||||
|
fp = (struct frame *)((caddr_t)getfp() + STACK_BIAS);
|
||||||
|
|
||||||
|
minfp = fp;
|
||||||
|
|
||||||
|
if (((uintptr_t)fp - base) >= size)
|
||||||
|
return (0); /* the frame pointer isn't in our stack */
|
||||||
|
|
||||||
|
while (depth < pcstack_limit) {
|
||||||
|
uintptr_t tmp;
|
||||||
|
|
||||||
|
/* LINTED alignment */
|
||||||
|
nextfp = (struct frame *)((caddr_t)fp->fr_savfp + STACK_BIAS);
|
||||||
|
tmp = (uintptr_t)nextfp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check nextfp for validity. It must be properly aligned,
|
||||||
|
* increasing compared to the last %fp (or the top of the
|
||||||
|
* stack we just switched to), and it must be inside
|
||||||
|
* [base, base + size).
|
||||||
|
*/
|
||||||
|
if (tmp != SA(tmp))
|
||||||
|
break;
|
||||||
|
else if (nextfp <= minfp || (tmp - base) >= size) {
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
if (tmp == NULL || !on_altstack)
|
||||||
|
break;
|
||||||
|
/*
|
||||||
|
* If we're on an alternate signal stack, try jumping
|
||||||
|
* to the main thread stack.
|
||||||
|
*
|
||||||
|
* If the main thread stack has an unlimited size, we
|
||||||
|
* punt, since we don't know where the frame pointer's
|
||||||
|
* been.
|
||||||
|
*
|
||||||
|
* (thr_stksegment() returns the *top of stack*
|
||||||
|
* in ss_sp, not the bottom)
|
||||||
|
*/
|
||||||
|
if (thr_stksegment(&st) == 0) {
|
||||||
|
if (st.ss_size >= (uintptr_t)st.ss_sp ||
|
||||||
|
st.ss_size < UMEM_FRAMESIZE - 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
on_altstack = 0;
|
||||||
|
base = (uintptr_t)st.ss_sp - st.ss_size;
|
||||||
|
size = st.ss_size - (UMEM_FRAMESIZE - 1);
|
||||||
|
minfp = (struct frame *)base;
|
||||||
|
continue; /* try again */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
if (check_signal && (fp->fr_savpc - sigbase) <= sigsize)
|
||||||
|
umem_panic("called from signal handler");
|
||||||
|
#endif
|
||||||
|
pcstack[depth++] = fp->fr_savpc;
|
||||||
|
fp = nextfp;
|
||||||
|
minfp = fp;
|
||||||
|
}
|
||||||
|
return (depth);
|
||||||
|
#endif
|
||||||
|
}
|
72
1.0.1/i386_subr_sol.s
Normal file
72
1.0.1/i386_subr_sol.s
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma ident "@(#)asm_subr.s 1.4 05/06/08 SMI"
|
||||||
|
|
||||||
|
#include <sys/asm_linkage.h>
|
||||||
|
|
||||||
|
#if defined(lint)
|
||||||
|
|
||||||
|
void *
|
||||||
|
getfp(void)
|
||||||
|
{
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
void
|
||||||
|
_breakpoint(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* lint */
|
||||||
|
|
||||||
|
#if defined(__amd64)
|
||||||
|
|
||||||
|
ENTRY(getfp)
|
||||||
|
movq %rbp, %rax
|
||||||
|
ret
|
||||||
|
SET_SIZE(getfp)
|
||||||
|
|
||||||
|
#else /* __i386 */
|
||||||
|
|
||||||
|
ENTRY(getfp)
|
||||||
|
movl %ebp, %eax
|
||||||
|
ret
|
||||||
|
SET_SIZE(getfp)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
ENTRY(_breakpoint)
|
||||||
|
int $3
|
||||||
|
ret
|
||||||
|
SET_SIZE(_breakpoint)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* lint */
|
149
1.0.1/init_lib.c
Normal file
149
1.0.1/init_lib.c
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)init_lib.c 1.2 05/06/08 SMI" */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization routines for the library version of libumem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "umem_base.h"
|
||||||
|
#include "vmem_base.h"
|
||||||
|
|
||||||
|
#if HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if HAVE_DLFCN_H
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
#include <machine/param.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
vmem_heap_init(void)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
vmem_backend = VMEM_BACKEND_MMAP;
|
||||||
|
#else
|
||||||
|
#if 0
|
||||||
|
void *handle = dlopen("libmapmalloc.so.1", RTLD_NOLOAD);
|
||||||
|
|
||||||
|
if (handle != NULL) {
|
||||||
|
#endif
|
||||||
|
log_message("sbrk backend disabled\n");
|
||||||
|
vmem_backend = VMEM_BACKEND_MMAP;
|
||||||
|
#if 0
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((vmem_backend & VMEM_BACKEND_MMAP) != 0) {
|
||||||
|
vmem_backend = VMEM_BACKEND_MMAP;
|
||||||
|
(void) vmem_mmap_arena(NULL, NULL);
|
||||||
|
} else {
|
||||||
|
#ifndef _WIN32
|
||||||
|
vmem_backend = VMEM_BACKEND_SBRK;
|
||||||
|
(void) vmem_sbrk_arena(NULL, NULL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
void
|
||||||
|
umem_type_init(caddr_t start, size_t len, size_t pgsize)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
SYSTEM_INFO info;
|
||||||
|
GetSystemInfo(&info);
|
||||||
|
pagesize = info.dwPageSize;
|
||||||
|
#elif !defined(__FreeBSD__)
|
||||||
|
pagesize = _sysconf(_SC_PAGESIZE);
|
||||||
|
#else
|
||||||
|
pagesize = PAGE_SIZE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
umem_get_max_ncpus(void)
|
||||||
|
{
|
||||||
|
#ifdef linux
|
||||||
|
/*
|
||||||
|
* HACK: sysconf() will invoke malloc() on Linux as part of reading
|
||||||
|
* in /proc/stat. To avoid recursion in the malloc replacement
|
||||||
|
* version of libumem, read /proc/stat into a static buffer.
|
||||||
|
*/
|
||||||
|
static char proc_stat[8192];
|
||||||
|
int fd;
|
||||||
|
int ncpus = 1;
|
||||||
|
|
||||||
|
fd = open("/proc/stat", O_RDONLY);
|
||||||
|
if (fd >= 0) {
|
||||||
|
const ssize_t n = read(fd, proc_stat, sizeof(proc_stat) - 1);
|
||||||
|
if (n >= 0) {
|
||||||
|
const char *cur;
|
||||||
|
const char *next;
|
||||||
|
|
||||||
|
proc_stat[n] = '\0';
|
||||||
|
cur = proc_stat;
|
||||||
|
while (*cur && (next = strstr(cur + 3, "cpu"))) {
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*cur)
|
||||||
|
ncpus = atoi(cur + 3) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ncpus;
|
||||||
|
|
||||||
|
#else /* !linux */
|
||||||
|
|
||||||
|
#if _SC_NPROCESSORS_ONLN
|
||||||
|
return (2 * sysconf(_SC_NPROCESSORS_ONLN));
|
||||||
|
#elif defined(_SC_NPROCESSORS_CONF)
|
||||||
|
return (2 * sysconf(_SC_NPROCESSORS_CONF));
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
SYSTEM_INFO info;
|
||||||
|
GetSystemInfo(&info);
|
||||||
|
return info.dwNumberOfProcessors;
|
||||||
|
#else
|
||||||
|
/* XXX: determine CPU count on other platforms */
|
||||||
|
return (1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* linux */
|
||||||
|
}
|
65
1.0.1/init_stand.c
Normal file
65
1.0.1/init_stand.c
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma ident "@(#)init_stand.c 1.3 05/06/08 SMI"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization routines for the standalone version of libumem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "umem_base.h"
|
||||||
|
#include "vmem_base.h"
|
||||||
|
|
||||||
|
#include "vmem_stand.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
vmem_heap_init(void)
|
||||||
|
{
|
||||||
|
vmem_backend = VMEM_BACKEND_STAND;
|
||||||
|
(void) vmem_stand_arena(NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
umem_type_init(caddr_t base, size_t len, size_t pgsize)
|
||||||
|
{
|
||||||
|
pagesize = pgsize;
|
||||||
|
|
||||||
|
vmem_stand_init();
|
||||||
|
(void) vmem_stand_add(base, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
umem_get_max_ncpus(void)
|
||||||
|
{
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
umem_add(caddr_t base, size_t len)
|
||||||
|
{
|
||||||
|
return (vmem_stand_add(base, len));
|
||||||
|
}
|
70
1.0.1/linktest_stand.c
Normal file
70
1.0.1/linktest_stand.c
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma ident "@(#)linktest_stand.c 1.3 05/06/08 SMI"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is used to verify that the standalone's external dependencies
|
||||||
|
* haven't changed in a way that'll break things that use it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void __umem_assert_failed(void) {}
|
||||||
|
void _atomic_add_64(void) {}
|
||||||
|
void _atomic_add_32_nv(void) {}
|
||||||
|
void bcopy(void) {}
|
||||||
|
void bzero(void) {}
|
||||||
|
void dladdr1(void) {}
|
||||||
|
void exit(void) {}
|
||||||
|
void getenv(void) {}
|
||||||
|
void gethrtime(void) {}
|
||||||
|
void membar_producer(void) {}
|
||||||
|
void memcpy(void) {}
|
||||||
|
void memset(void) {}
|
||||||
|
void snprintf(void) {}
|
||||||
|
void strchr(void) {}
|
||||||
|
void strcmp(void) {}
|
||||||
|
void strlen(void) {}
|
||||||
|
void strncpy(void) {}
|
||||||
|
void strrchr(void) {}
|
||||||
|
void strtoul(void) {}
|
||||||
|
void umem_err_recoverable(void) {}
|
||||||
|
void umem_panic(void) {}
|
||||||
|
void vsnprintf(void) {}
|
||||||
|
|
||||||
|
#ifdef __i386
|
||||||
|
void __mul64(void) {}
|
||||||
|
void __rem64(void) {}
|
||||||
|
void __div64(void) {}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
void __divdi3(void) {}
|
||||||
|
void __moddi3(void) {}
|
||||||
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
|
#endif /* __i386 */
|
||||||
|
|
||||||
|
int __ctype;
|
||||||
|
int errno;
|
465
1.0.1/malloc.c
Normal file
465
1.0.1/malloc.c
Normal file
|
@ -0,0 +1,465 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma ident "@(#)malloc.c 1.5 05/06/08 SMI"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SYSMACROS_H
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "umem_base.h"
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
# include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* malloc_data_t is an 8-byte structure which is located "before" the pointer
|
||||||
|
* returned from {m,c,re}alloc and memalign. The first four bytes give
|
||||||
|
* information about the buffer, and the second four bytes are a status byte.
|
||||||
|
*
|
||||||
|
* See umem_impl.h for the various magic numbers used, and the size
|
||||||
|
* encode/decode macros.
|
||||||
|
*
|
||||||
|
* The 'size' of the buffer includes the tags. That is, we encode the
|
||||||
|
* argument to umem_alloc(), not the argument to malloc().
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct malloc_data {
|
||||||
|
uint32_t malloc_size;
|
||||||
|
uint32_t malloc_stat; /* = UMEM_MALLOC_ENCODE(state, malloc_size) */
|
||||||
|
} malloc_data_t;
|
||||||
|
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
static void *umem_malloc_hook(size_t size_arg, const void *caller)
|
||||||
|
#else
|
||||||
|
void *
|
||||||
|
malloc(size_t size_arg)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef _LP64
|
||||||
|
uint32_t high_size = 0;
|
||||||
|
#endif
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
malloc_data_t *ret;
|
||||||
|
size = size_arg + sizeof (malloc_data_t);
|
||||||
|
|
||||||
|
#ifdef _LP64
|
||||||
|
if (size > UMEM_SECOND_ALIGN) {
|
||||||
|
size += sizeof (malloc_data_t);
|
||||||
|
high_size = (size >> 32);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (size < size_arg) {
|
||||||
|
errno = ENOMEM; /* overflow */
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
ret = (malloc_data_t *)_umem_alloc(size, UMEM_DEFAULT);
|
||||||
|
if (ret == NULL) {
|
||||||
|
if (size <= UMEM_MAXBUF)
|
||||||
|
errno = EAGAIN;
|
||||||
|
else
|
||||||
|
errno = ENOMEM;
|
||||||
|
return (NULL);
|
||||||
|
#ifdef _LP64
|
||||||
|
} else if (high_size > 0) {
|
||||||
|
uint32_t low_size = (uint32_t)size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* uses different magic numbers to make it harder to
|
||||||
|
* undetectably corrupt
|
||||||
|
*/
|
||||||
|
ret->malloc_size = high_size;
|
||||||
|
ret->malloc_stat = UMEM_MALLOC_ENCODE(MALLOC_MAGIC, high_size);
|
||||||
|
ret++;
|
||||||
|
|
||||||
|
ret->malloc_size = low_size;
|
||||||
|
ret->malloc_stat = UMEM_MALLOC_ENCODE(MALLOC_OVERSIZE_MAGIC,
|
||||||
|
low_size);
|
||||||
|
ret++;
|
||||||
|
} else if (size > UMEM_SECOND_ALIGN) {
|
||||||
|
uint32_t low_size = (uint32_t)size;
|
||||||
|
|
||||||
|
ret++; /* leave the first 8 bytes alone */
|
||||||
|
|
||||||
|
ret->malloc_size = low_size;
|
||||||
|
ret->malloc_stat = UMEM_MALLOC_ENCODE(MALLOC_SECOND_MAGIC,
|
||||||
|
low_size);
|
||||||
|
ret++;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
ret->malloc_size = size;
|
||||||
|
ret->malloc_stat = UMEM_MALLOC_ENCODE(MALLOC_MAGIC, size);
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
return ((void *)ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __GLIBC__
|
||||||
|
void *
|
||||||
|
calloc(size_t nelem, size_t elsize)
|
||||||
|
{
|
||||||
|
size_t size = nelem * elsize;
|
||||||
|
void *retval;
|
||||||
|
|
||||||
|
if (nelem > 0 && elsize > 0 && size/nelem != elsize) {
|
||||||
|
errno = ENOMEM; /* overflow */
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = malloc(size);
|
||||||
|
if (retval == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
(void) memset(retval, 0, size);
|
||||||
|
return (retval);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* memalign uses vmem_xalloc to do its work.
|
||||||
|
*
|
||||||
|
* in 64-bit, the memaligned buffer always has two tags. This simplifies the
|
||||||
|
* code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
static void *umem_memalign_hook(size_t size_arg, size_t align, const void *caller)
|
||||||
|
#else
|
||||||
|
void *
|
||||||
|
memalign(size_t align, size_t size_arg)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
uintptr_t phase;
|
||||||
|
|
||||||
|
void *buf;
|
||||||
|
malloc_data_t *ret;
|
||||||
|
|
||||||
|
size_t overhead;
|
||||||
|
|
||||||
|
if (size_arg == 0 || align == 0 || (align & (align - 1)) != 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if malloc provides the required alignment, use it.
|
||||||
|
*/
|
||||||
|
if (align <= UMEM_ALIGN ||
|
||||||
|
(align <= UMEM_SECOND_ALIGN && size_arg >= UMEM_SECOND_ALIGN))
|
||||||
|
return (malloc(size_arg));
|
||||||
|
|
||||||
|
#ifdef _LP64
|
||||||
|
overhead = 2 * sizeof (malloc_data_t);
|
||||||
|
#else
|
||||||
|
overhead = sizeof (malloc_data_t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ASSERT(overhead <= align);
|
||||||
|
|
||||||
|
size = size_arg + overhead;
|
||||||
|
phase = align - overhead;
|
||||||
|
|
||||||
|
if (umem_memalign_arena == NULL && umem_init() == 0) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < size_arg) {
|
||||||
|
errno = ENOMEM; /* overflow */
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = vmem_xalloc(umem_memalign_arena, size, align, phase,
|
||||||
|
0, NULL, NULL, VM_NOSLEEP);
|
||||||
|
|
||||||
|
if (buf == NULL) {
|
||||||
|
if ((size_arg + align) <= UMEM_MAXBUF)
|
||||||
|
errno = EAGAIN;
|
||||||
|
else
|
||||||
|
errno = ENOMEM;
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = (malloc_data_t *)buf;
|
||||||
|
{
|
||||||
|
uint32_t low_size = (uint32_t)size;
|
||||||
|
|
||||||
|
#ifdef _LP64
|
||||||
|
uint32_t high_size = (uint32_t)(size >> 32);
|
||||||
|
|
||||||
|
ret->malloc_size = high_size;
|
||||||
|
ret->malloc_stat = UMEM_MALLOC_ENCODE(MEMALIGN_MAGIC,
|
||||||
|
high_size);
|
||||||
|
ret++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret->malloc_size = low_size;
|
||||||
|
ret->malloc_stat = UMEM_MALLOC_ENCODE(MEMALIGN_MAGIC, low_size);
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(P2PHASE((uintptr_t)ret, align) == 0);
|
||||||
|
ASSERT((void *)((uintptr_t)ret - overhead) == buf);
|
||||||
|
|
||||||
|
return ((void *)ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __GLIBC__
|
||||||
|
void *
|
||||||
|
valloc(size_t size)
|
||||||
|
{
|
||||||
|
return (memalign(pagesize, size));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* process_free:
|
||||||
|
*
|
||||||
|
* Pulls information out of a buffer pointer, and optionally free it.
|
||||||
|
* This is used by free() and realloc() to process buffers.
|
||||||
|
*
|
||||||
|
* On failure, calls umem_err_recoverable() with an appropriate message
|
||||||
|
* On success, returns the data size through *data_size_arg, if (!is_free).
|
||||||
|
*
|
||||||
|
* Preserves errno, since free()'s semantics require it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
process_free(void *buf_arg,
|
||||||
|
int do_free, /* free the buffer, or just get its size? */
|
||||||
|
size_t *data_size_arg) /* output: bytes of data in buf_arg */
|
||||||
|
{
|
||||||
|
malloc_data_t *buf;
|
||||||
|
|
||||||
|
void *base;
|
||||||
|
size_t size;
|
||||||
|
size_t data_size;
|
||||||
|
|
||||||
|
const char *message;
|
||||||
|
int old_errno = errno;
|
||||||
|
|
||||||
|
buf = (malloc_data_t *)buf_arg;
|
||||||
|
|
||||||
|
buf--;
|
||||||
|
size = buf->malloc_size;
|
||||||
|
|
||||||
|
switch (UMEM_MALLOC_DECODE(buf->malloc_stat, size)) {
|
||||||
|
|
||||||
|
case MALLOC_MAGIC:
|
||||||
|
base = (void *)buf;
|
||||||
|
data_size = size - sizeof (malloc_data_t);
|
||||||
|
|
||||||
|
if (do_free)
|
||||||
|
buf->malloc_stat = UMEM_FREE_PATTERN_32;
|
||||||
|
|
||||||
|
goto process_malloc;
|
||||||
|
|
||||||
|
#ifdef _LP64
|
||||||
|
case MALLOC_SECOND_MAGIC:
|
||||||
|
base = (void *)(buf - 1);
|
||||||
|
data_size = size - 2 * sizeof (malloc_data_t);
|
||||||
|
|
||||||
|
if (do_free)
|
||||||
|
buf->malloc_stat = UMEM_FREE_PATTERN_32;
|
||||||
|
|
||||||
|
goto process_malloc;
|
||||||
|
|
||||||
|
case MALLOC_OVERSIZE_MAGIC: {
|
||||||
|
size_t high_size;
|
||||||
|
|
||||||
|
buf--;
|
||||||
|
high_size = buf->malloc_size;
|
||||||
|
|
||||||
|
if (UMEM_MALLOC_DECODE(buf->malloc_stat, high_size) !=
|
||||||
|
MALLOC_MAGIC) {
|
||||||
|
message = "invalid or corrupted buffer";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
size += high_size << 32;
|
||||||
|
|
||||||
|
base = (void *)buf;
|
||||||
|
data_size = size - 2 * sizeof (malloc_data_t);
|
||||||
|
|
||||||
|
if (do_free) {
|
||||||
|
buf->malloc_stat = UMEM_FREE_PATTERN_32;
|
||||||
|
(buf + 1)->malloc_stat = UMEM_FREE_PATTERN_32;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto process_malloc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case MEMALIGN_MAGIC: {
|
||||||
|
size_t overhead = sizeof (malloc_data_t);
|
||||||
|
|
||||||
|
#ifdef _LP64
|
||||||
|
size_t high_size;
|
||||||
|
|
||||||
|
overhead += sizeof (malloc_data_t);
|
||||||
|
|
||||||
|
buf--;
|
||||||
|
high_size = buf->malloc_size;
|
||||||
|
|
||||||
|
if (UMEM_MALLOC_DECODE(buf->malloc_stat, high_size) !=
|
||||||
|
MEMALIGN_MAGIC) {
|
||||||
|
message = "invalid or corrupted buffer";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size += high_size << 32;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* destroy the main tag's malloc_stat
|
||||||
|
*/
|
||||||
|
if (do_free)
|
||||||
|
(buf + 1)->malloc_stat = UMEM_FREE_PATTERN_32;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
base = (void *)buf;
|
||||||
|
data_size = size - overhead;
|
||||||
|
|
||||||
|
if (do_free)
|
||||||
|
buf->malloc_stat = UMEM_FREE_PATTERN_32;
|
||||||
|
|
||||||
|
goto process_memalign;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if (buf->malloc_stat == UMEM_FREE_PATTERN_32)
|
||||||
|
message = "double-free or invalid buffer";
|
||||||
|
else
|
||||||
|
message = "invalid or corrupted buffer";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
umem_err_recoverable("%s(%p): %s\n",
|
||||||
|
do_free? "free" : "realloc", buf_arg, message);
|
||||||
|
|
||||||
|
errno = old_errno;
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
process_malloc:
|
||||||
|
if (do_free)
|
||||||
|
_umem_free(base, size);
|
||||||
|
else
|
||||||
|
*data_size_arg = data_size;
|
||||||
|
|
||||||
|
errno = old_errno;
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
process_memalign:
|
||||||
|
if (do_free)
|
||||||
|
vmem_xfree(umem_memalign_arena, base, size);
|
||||||
|
else
|
||||||
|
*data_size_arg = data_size;
|
||||||
|
|
||||||
|
errno = old_errno;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
static void umem_free_hook(void *buf, const void *caller)
|
||||||
|
#else
|
||||||
|
void
|
||||||
|
free(void *buf)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (buf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process buf, freeing it if it is not corrupt.
|
||||||
|
*/
|
||||||
|
(void) process_free(buf, 1, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
static void *umem_realloc_hook(void *buf_arg, size_t newsize, const void *caller)
|
||||||
|
#else
|
||||||
|
void *
|
||||||
|
realloc(void *buf_arg, size_t newsize)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
size_t oldsize;
|
||||||
|
void *buf;
|
||||||
|
|
||||||
|
if (buf_arg == NULL)
|
||||||
|
return (malloc(newsize));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get the old data size without freeing the buffer
|
||||||
|
*/
|
||||||
|
if (process_free(buf_arg, 0, &oldsize) == 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newsize == oldsize) /* size didn't change */
|
||||||
|
return (buf_arg);
|
||||||
|
|
||||||
|
buf = malloc(newsize);
|
||||||
|
if (buf == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
(void) memcpy(buf, buf_arg, MIN(newsize, oldsize));
|
||||||
|
free(buf_arg);
|
||||||
|
return (buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
static void __attribute__((constructor)) umem_malloc_init_hook(void)
|
||||||
|
{
|
||||||
|
if (__malloc_hook != umem_malloc_hook) {
|
||||||
|
umem_startup(NULL, 0, 0, NULL, NULL);
|
||||||
|
__malloc_hook = umem_malloc_hook;
|
||||||
|
__free_hook = umem_free_hook;
|
||||||
|
__realloc_hook = umem_realloc_hook;
|
||||||
|
__memalign_hook = umem_memalign_hook;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*__malloc_initialize_hook)(void) = umem_malloc_init_hook;
|
||||||
|
|
||||||
|
#else
|
||||||
|
void __attribute__((constructor))
|
||||||
|
__malloc_umem_init (void)
|
||||||
|
{
|
||||||
|
umem_startup(NULL, 0, 0, NULL, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
301
1.0.1/misc.c
Normal file
301
1.0.1/misc.c
Normal file
|
@ -0,0 +1,301 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)misc.c 1.6 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#define _BUILDING_UMEM_MISC_C
|
||||||
|
#include "config.h"
|
||||||
|
/* #include "mtlib.h" */
|
||||||
|
#if HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#if HAVE_DLFCN_H
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if HAVE_SYS_MACHELF_H
|
||||||
|
#include <sys/machelf.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <umem_impl.h>
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
#ifdef ECELERITY
|
||||||
|
#include "util.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UMEM_ERRFD 2 /* goes to standard error */
|
||||||
|
#define UMEM_MAX_ERROR_SIZE 4096 /* error messages are truncated to this */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a circular buffer for holding error messages.
|
||||||
|
* umem_error_enter appends to the buffer, adding "..." to the beginning
|
||||||
|
* if data has been lost.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ERR_SIZE 8192 /* must be a power of 2 */
|
||||||
|
|
||||||
|
static mutex_t umem_error_lock = DEFAULTMUTEX;
|
||||||
|
#ifdef NEED_64_LOCK
|
||||||
|
pthread_mutex_t umem_ppc_64inc_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static char umem_error_buffer[ERR_SIZE] = "";
|
||||||
|
static uint_t umem_error_begin = 0;
|
||||||
|
static uint_t umem_error_end = 0;
|
||||||
|
|
||||||
|
#define WRITE_AND_INC(var, value) { \
|
||||||
|
umem_error_buffer[(var)++] = (value); \
|
||||||
|
var = P2PHASE((var), ERR_SIZE); \
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
umem_log_enter(const char *error_str, int serious)
|
||||||
|
{
|
||||||
|
int looped;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
looped = 0;
|
||||||
|
#ifdef ECELERITY
|
||||||
|
mem_printf(serious ? DCRITICAL : DINFO, "umem: %s", error_str);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
(void) mutex_lock(&umem_error_lock);
|
||||||
|
|
||||||
|
while ((c = *error_str++) != '\0') {
|
||||||
|
WRITE_AND_INC(umem_error_end, c);
|
||||||
|
if (umem_error_end == umem_error_begin)
|
||||||
|
looped = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
umem_error_buffer[umem_error_end] = 0;
|
||||||
|
|
||||||
|
if (looped) {
|
||||||
|
uint_t idx;
|
||||||
|
umem_error_begin = P2PHASE(umem_error_end + 1, ERR_SIZE);
|
||||||
|
|
||||||
|
idx = umem_error_begin;
|
||||||
|
WRITE_AND_INC(idx, '.');
|
||||||
|
WRITE_AND_INC(idx, '.');
|
||||||
|
WRITE_AND_INC(idx, '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) mutex_unlock(&umem_error_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
umem_error_enter(const char *error_str)
|
||||||
|
{
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
if (umem_output && !issetugid())
|
||||||
|
(void) write(UMEM_ERRFD, error_str, strlen(error_str));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
umem_log_enter(error_str, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
highbit(ulong_t i)
|
||||||
|
{
|
||||||
|
register int h = 1;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
return (0);
|
||||||
|
#ifdef _LP64
|
||||||
|
if (i & 0xffffffff00000000ul) {
|
||||||
|
h += 32; i >>= 32;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (i & 0xffff0000) {
|
||||||
|
h += 16; i >>= 16;
|
||||||
|
}
|
||||||
|
if (i & 0xff00) {
|
||||||
|
h += 8; i >>= 8;
|
||||||
|
}
|
||||||
|
if (i & 0xf0) {
|
||||||
|
h += 4; i >>= 4;
|
||||||
|
}
|
||||||
|
if (i & 0xc) {
|
||||||
|
h += 2; i >>= 2;
|
||||||
|
}
|
||||||
|
if (i & 0x2) {
|
||||||
|
h += 1;
|
||||||
|
}
|
||||||
|
return (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
lowbit(ulong_t i)
|
||||||
|
{
|
||||||
|
register int h = 1;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
return (0);
|
||||||
|
#ifdef _LP64
|
||||||
|
if (!(i & 0xffffffff)) {
|
||||||
|
h += 32; i >>= 32;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!(i & 0xffff)) {
|
||||||
|
h += 16; i >>= 16;
|
||||||
|
}
|
||||||
|
if (!(i & 0xff)) {
|
||||||
|
h += 8; i >>= 8;
|
||||||
|
}
|
||||||
|
if (!(i & 0xf)) {
|
||||||
|
h += 4; i >>= 4;
|
||||||
|
}
|
||||||
|
if (!(i & 0x3)) {
|
||||||
|
h += 2; i >>= 2;
|
||||||
|
}
|
||||||
|
if (!(i & 0x1)) {
|
||||||
|
h += 1;
|
||||||
|
}
|
||||||
|
return (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hrt2ts(hrtime_t hrt, timestruc_t *tsp)
|
||||||
|
{
|
||||||
|
tsp->tv_sec = hrt / NANOSEC;
|
||||||
|
tsp->tv_nsec = hrt % NANOSEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
log_message(const char *format, ...)
|
||||||
|
{
|
||||||
|
char buf[UMEM_MAX_ERROR_SIZE] = "";
|
||||||
|
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
(void) vsnprintf(buf, UMEM_MAX_ERROR_SIZE-1, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
if (umem_output > 1)
|
||||||
|
(void) write(UMEM_ERRFD, buf, strlen(buf));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
umem_log_enter(buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
void
|
||||||
|
debug_printf(const char *format, ...)
|
||||||
|
{
|
||||||
|
char buf[UMEM_MAX_ERROR_SIZE] = "";
|
||||||
|
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
(void) vsnprintf(buf, UMEM_MAX_ERROR_SIZE-1, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
(void) write(UMEM_ERRFD, buf, strlen(buf));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
umem_vprintf(const char *format, va_list va)
|
||||||
|
{
|
||||||
|
char buf[UMEM_MAX_ERROR_SIZE] = "";
|
||||||
|
|
||||||
|
(void) vsnprintf(buf, UMEM_MAX_ERROR_SIZE-1, format, va);
|
||||||
|
|
||||||
|
umem_error_enter(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
umem_printf(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
umem_vprintf(format, va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
void
|
||||||
|
umem_printf_warn(void *ignored, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
umem_vprintf(format, va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* print_sym tries to print out the symbol and offset of a pointer
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
print_sym(void *pointer)
|
||||||
|
{
|
||||||
|
#if HAVE_SYS_MACHELF_H
|
||||||
|
int result;
|
||||||
|
Dl_info sym_info;
|
||||||
|
|
||||||
|
uintptr_t end = NULL;
|
||||||
|
|
||||||
|
Sym *ext_info = NULL;
|
||||||
|
|
||||||
|
result = dladdr1(pointer, &sym_info, (void **)&ext_info,
|
||||||
|
RTLD_DL_SYMENT);
|
||||||
|
|
||||||
|
if (result != 0) {
|
||||||
|
const char *endpath;
|
||||||
|
|
||||||
|
end = (uintptr_t)sym_info.dli_saddr + ext_info->st_size;
|
||||||
|
|
||||||
|
endpath = strrchr(sym_info.dli_fname, '/');
|
||||||
|
if (endpath)
|
||||||
|
endpath++;
|
||||||
|
else
|
||||||
|
endpath = sym_info.dli_fname;
|
||||||
|
umem_printf("%s'", endpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == 0 || (uintptr_t)pointer > end) {
|
||||||
|
umem_printf("?? (0x%p)", pointer);
|
||||||
|
return (0);
|
||||||
|
} else {
|
||||||
|
umem_printf("%s+0x%p", sym_info.dli_sname,
|
||||||
|
(char *)pointer - (char *)sym_info.dli_saddr);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
150
1.0.1/misc.h
Normal file
150
1.0.1/misc.h
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MISC_H
|
||||||
|
#define _MISC_H
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)misc.h 1.6 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_THREAD_H
|
||||||
|
# include <thread.h>
|
||||||
|
#else
|
||||||
|
# include "sol_compat.h"
|
||||||
|
#endif
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uint_t umem_abort; /* abort when errors occur */
|
||||||
|
extern uint_t umem_output; /* output error messages to stderr */
|
||||||
|
extern caddr_t umem_min_stack; /* max stack address for audit log */
|
||||||
|
extern caddr_t umem_max_stack; /* min stack address for audit log */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* various utility functions
|
||||||
|
* These are globally implemented.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef offsetof
|
||||||
|
#define offsetof(s, m) ((size_t)(&(((s *)0)->m)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* a safe printf -- do not use for error messages.
|
||||||
|
*/
|
||||||
|
void debug_printf(const char *format, ...);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* adds a message to the log without writing it out.
|
||||||
|
*/
|
||||||
|
void log_message(const char *format, ...);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns the index of the (high/low) bit + 1
|
||||||
|
*/
|
||||||
|
int highbit(ulong_t) __attribute__ ((pure));
|
||||||
|
int lowbit(ulong_t) __attribute__ ((pure));
|
||||||
|
/* #pragma no_side_effect(highbit, lowbit) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Converts a hrtime_t to a timestruc_t
|
||||||
|
*/
|
||||||
|
void hrt2ts(hrtime_t hrt, timestruc_t *tsp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tries to print out the symbol and offset of a pointer using umem_error_info
|
||||||
|
*/
|
||||||
|
int print_sym(void *pointer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Information about the current error. Can be called multiple times, should
|
||||||
|
* be followed eventually with a call to umem_err or umem_err_recoverable.
|
||||||
|
*/
|
||||||
|
void umem_printf(const char *format, ...);
|
||||||
|
void umem_vprintf(const char *format, va_list);
|
||||||
|
|
||||||
|
void umem_printf_warn(void *ignored, const char *format, ...);
|
||||||
|
|
||||||
|
void umem_error_enter(const char *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* prints error message and stack trace, then aborts. Cannot return.
|
||||||
|
*/
|
||||||
|
void umem_panic(const char *format, ...) __attribute__((noreturn));
|
||||||
|
/* #pragma does_not_return(umem_panic) */
|
||||||
|
/* #pragma rarely_called(umem_panic) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* like umem_err, but only aborts if umem_abort > 0
|
||||||
|
*/
|
||||||
|
void umem_err_recoverable(const char *format, ...);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We define our own assertion handling since libc's assert() calls malloc()
|
||||||
|
*/
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define ASSERT(assertion) (void)0
|
||||||
|
#else
|
||||||
|
#define ASSERT(assertion) (void)((assertion) || \
|
||||||
|
__umem_assert_failed(#assertion, __FILE__, __LINE__))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int __umem_assert_failed(const char *assertion, const char *file, int line) __attribute__ ((noreturn));
|
||||||
|
/* #pragma does_not_return(__umem_assert_failed) */
|
||||||
|
/* #pragma rarely_called(__umem_assert_failed) */
|
||||||
|
/*
|
||||||
|
* These have architecture-specific implementations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the current function's frame pointer.
|
||||||
|
*/
|
||||||
|
extern void *getfp(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* puts a pc-only stack trace of up to pcstack_limit frames into pcstack.
|
||||||
|
* Returns the number of stacks written.
|
||||||
|
*
|
||||||
|
* if check_sighandler != 0, and we are in a signal context, calls
|
||||||
|
* umem_err_recoverable.
|
||||||
|
*/
|
||||||
|
extern int getpcstack(uintptr_t *pcstack, int pcstack_limit,
|
||||||
|
int check_sighandler);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _MISC_H */
|
245
1.0.1/sol_compat.h
Normal file
245
1.0.1/sol_compat.h
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2008 Message Systems, Inc. All rights reserved
|
||||||
|
* This header file distributed under the terms of the CDDL.
|
||||||
|
* Portions Copyright 2004 Sun Microsystems, Inc. All Rights reserved.
|
||||||
|
*/
|
||||||
|
#ifndef _EC_UMEM_SOL_COMPAT_H_
|
||||||
|
#define _EC_UMEM_SOL_COMPAT_H_
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define THR_RETURN DWORD
|
||||||
|
# define THR_API WINAPI
|
||||||
|
# define INLINE __inline
|
||||||
|
#else
|
||||||
|
# define THR_RETURN void *
|
||||||
|
# define THR_API
|
||||||
|
# define INLINE inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MACH__) || defined(_WIN32)
|
||||||
|
#define NO_WEAK_SYMBOLS
|
||||||
|
#define _umem_cache_alloc(a,b) umem_cache_alloc(a,b)
|
||||||
|
#define _umem_cache_free(a,b) umem_cache_free(a,b)
|
||||||
|
#define _umem_zalloc(a,b) umem_zalloc(a,b)
|
||||||
|
#define _umem_alloc(a,b) umem_alloc(a,b)
|
||||||
|
#define _umem_alloc_align(a,b,c) umem_alloc_align(a,b,c)
|
||||||
|
#define _umem_free(a,b) umem_free(a,b)
|
||||||
|
#define _umem_free_align(a,b) umem_free_align(a,b)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define bcopy(s, d, n) memcpy(d, s, n)
|
||||||
|
#define bzero(m, s) memset(m, 0, s)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef pthread_t thread_t;
|
||||||
|
typedef pthread_mutex_t mutex_t;
|
||||||
|
typedef pthread_cond_t cond_t;
|
||||||
|
typedef u_int64_t hrtime_t;
|
||||||
|
typedef uint32_t uint_t;
|
||||||
|
typedef unsigned long ulong_t;
|
||||||
|
typedef struct timespec timestruc_t;
|
||||||
|
typedef long long longlong_t;
|
||||||
|
typedef struct timespec timespec_t;
|
||||||
|
static INLINE hrtime_t gethrtime(void) {
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return (((u_int64_t)tv.tv_sec) << 32) | tv.tv_usec;
|
||||||
|
}
|
||||||
|
# define thr_self() pthread_self()
|
||||||
|
static INLINE thread_t _thr_self(void) {
|
||||||
|
return thr_self();
|
||||||
|
}
|
||||||
|
#if defined(__MACH__)
|
||||||
|
#define CPUHINT() (pthread_mach_thread_np(pthread_self()))
|
||||||
|
#endif
|
||||||
|
# define thr_sigsetmask pthread_sigmask
|
||||||
|
|
||||||
|
#define THR_BOUND 1
|
||||||
|
#define THR_DETACHED 2
|
||||||
|
#define THR_DAEMON 4
|
||||||
|
|
||||||
|
static INLINE int thr_create(void *stack_base,
|
||||||
|
size_t stack_size, THR_RETURN (THR_API *start_func)(void*),
|
||||||
|
void *arg, long flags, thread_t *new_thread_ID)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
|
||||||
|
if (flags & THR_DETACHED) {
|
||||||
|
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||||
|
}
|
||||||
|
ret = pthread_create(new_thread_ID, &attr, start_func, arg);
|
||||||
|
pthread_attr_destroy(&attr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# define mutex_init(mp, type, arg) pthread_mutex_init(mp, NULL)
|
||||||
|
# define mutex_lock(mp) pthread_mutex_lock(mp)
|
||||||
|
# define mutex_unlock(mp) pthread_mutex_unlock(mp)
|
||||||
|
# define mutex_destroy(mp) pthread_mutex_destroy(mp)
|
||||||
|
# define mutex_trylock(mp) pthread_mutex_trylock(mp)
|
||||||
|
# define DEFAULTMUTEX PTHREAD_MUTEX_INITIALIZER
|
||||||
|
# define DEFAULTCV PTHREAD_COND_INITIALIZER
|
||||||
|
# define MUTEX_HELD(mp) 1 /* not really, but only used in an assert */
|
||||||
|
|
||||||
|
# define cond_init(c, type, arg) pthread_cond_init(c, NULL)
|
||||||
|
# define cond_wait(c, m) pthread_cond_wait(c, m)
|
||||||
|
# define _cond_wait(c, m) pthread_cond_wait(c, m)
|
||||||
|
# define cond_signal(c) pthread_cond_signal(c)
|
||||||
|
# define cond_broadcast(c) pthread_cond_broadcast(c)
|
||||||
|
# define cond_destroy(c) pthread_cond_destroy(c)
|
||||||
|
# define cond_timedwait pthread_cond_timedwait
|
||||||
|
# define _cond_timedwait pthread_cond_timedwait
|
||||||
|
|
||||||
|
#ifndef RTLD_FIRST
|
||||||
|
# define RTLD_FIRST 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ECELERITY
|
||||||
|
# include "ec_atomic.h"
|
||||||
|
#else
|
||||||
|
# ifdef _WIN32
|
||||||
|
# define ec_atomic_inc(a) InterlockedIncrement(a)
|
||||||
|
# define ec_atomic_inc64(a) InterlockedIncrement64(a)
|
||||||
|
# elif defined(__MACH__)
|
||||||
|
# include <libkern/OSAtomic.h>
|
||||||
|
# define ec_atomic_inc(x) OSAtomicIncrement32Barrier((int32_t*)x)
|
||||||
|
# if !defined(__ppc__)
|
||||||
|
# define ec_atomic_inc64(x) OSAtomicIncrement64Barrier((int64_t*)x)
|
||||||
|
# endif
|
||||||
|
# elif (defined(__i386__) || defined(__x86_64__)) && defined(__GNUC__)
|
||||||
|
static INLINE uint_t ec_atomic_cas(uint_t *mem, uint_t with, uint_t cmp)
|
||||||
|
{
|
||||||
|
uint_t prev;
|
||||||
|
asm volatile ("lock; cmpxchgl %1, %2"
|
||||||
|
: "=a" (prev)
|
||||||
|
: "r" (with), "m" (*(mem)), "0" (cmp)
|
||||||
|
: "memory");
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
static INLINE uint64_t ec_atomic_cas64(uint64_t *mem, uint64_t with,
|
||||||
|
uint64_t cmp)
|
||||||
|
{
|
||||||
|
uint64_t prev;
|
||||||
|
# if defined(__x86_64__)
|
||||||
|
__asm__ volatile ("lock; cmpxchgq %1, %2"
|
||||||
|
: "=a" (prev)
|
||||||
|
: "r" (with), "m" (*(mem)), "0" (cmp)
|
||||||
|
: "memory");
|
||||||
|
# else
|
||||||
|
__asm__ volatile (
|
||||||
|
"pushl %%ebx;"
|
||||||
|
"mov 4+%1,%%ecx;"
|
||||||
|
"mov %1,%%ebx;"
|
||||||
|
"lock;"
|
||||||
|
"cmpxchg8b (%3);"
|
||||||
|
"popl %%ebx"
|
||||||
|
: "=A" (prev)
|
||||||
|
: "m" (with), "A" (cmp), "r" (mem)
|
||||||
|
: "%ecx", "memory");
|
||||||
|
# endif
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
static INLINE uint64_t ec_atomic_inc64(uint64_t *mem)
|
||||||
|
{
|
||||||
|
register uint64_t last;
|
||||||
|
do {
|
||||||
|
last = *mem;
|
||||||
|
} while (ec_atomic_cas64(mem, last+1, last) != last);
|
||||||
|
return ++last;
|
||||||
|
}
|
||||||
|
# define ec_atomic_inc64 ec_atomic_inc64
|
||||||
|
# else
|
||||||
|
# error no atomic solution for your platform
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifndef ec_atomic_inc
|
||||||
|
static INLINE uint_t ec_atomic_inc(uint_t *mem)
|
||||||
|
{
|
||||||
|
register uint_t last;
|
||||||
|
do {
|
||||||
|
last = *mem;
|
||||||
|
} while (ec_atomic_cas(mem, last+1, last) != last);
|
||||||
|
return ++last;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
# ifndef ec_atomic_inc64
|
||||||
|
/* yeah, it's not great. It's only used to bump failed allocation
|
||||||
|
* counts, so it is not critical right now. */
|
||||||
|
extern pthread_mutex_t umem_ppc_64inc_lock;
|
||||||
|
static INLINE uint64_t ec_atomic_inc64(uint64_t *val)
|
||||||
|
{
|
||||||
|
uint64_t rval;
|
||||||
|
pthread_mutex_lock(&umem_ppc_64inc_lock);
|
||||||
|
rval = *val + 1;
|
||||||
|
*val = rval;
|
||||||
|
pthread_mutex_unlock(&umem_ppc_64inc_lock);
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
# define ec_atomic_inc64 ec_atomic_inc64
|
||||||
|
# define NEED_64_LOCK 1
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define P2PHASE(x, align) ((x) & ((align) - 1))
|
||||||
|
#define P2ALIGN(x, align) ((x) & -(align))
|
||||||
|
#define P2NPHASE(x, align) (-(x) & ((align) - 1))
|
||||||
|
#define P2ROUNDUP(x, align) (-(-(x) & -(align)))
|
||||||
|
#define P2END(x, align) (-(~(x) & -(align)))
|
||||||
|
#define P2PHASEUP(x, align, phase) ((phase) - (((phase) - (x)) & -(align)))
|
||||||
|
#define P2CROSS(x, y, align) (((x) ^ (y)) > (align) - 1)
|
||||||
|
#define P2SAMEHIGHBIT(x, y) (((x) ^ (y)) < ((x) & (y)))
|
||||||
|
#define IS_P2ALIGNED(v, a) ((((uintptr_t)(v)) & ((uintptr_t)(a) - 1)) == 0)
|
||||||
|
#define ISP2(x) (((x) & ((x) - 1)) == 0)
|
||||||
|
|
||||||
|
/* beware! umem only uses these atomic adds for incrementing by 1 */
|
||||||
|
#define atomic_add_64(lvalptr, delta) ec_atomic_inc64(lvalptr)
|
||||||
|
#define atomic_add_32_nv(a, b) ec_atomic_inc(a)
|
||||||
|
|
||||||
|
#ifndef NANOSEC
|
||||||
|
#define NANOSEC 1000000000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define issetugid() 0
|
||||||
|
#elif !HAVE_ISSETUGID
|
||||||
|
#define issetugid() (geteuid() == 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _sysconf(a) sysconf(a)
|
||||||
|
#define __NORETURN __attribute__ ((noreturn))
|
||||||
|
|
||||||
|
#define EC_UMEM_DUMMY_PCSTACK 1
|
||||||
|
static INLINE int __nthreads(void)
|
||||||
|
{
|
||||||
|
/* or more; just to force multi-threaded mode */
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (SIZEOF_VOID_P == 8)
|
||||||
|
# define _LP64 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
# define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
#ifndef MAX
|
||||||
|
# define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
92
1.0.1/sparc_subr_sol.s
Normal file
92
1.0.1/sparc_subr_sol.s
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma ident "@(#)asm_subr.s 1.3 05/06/08 SMI"
|
||||||
|
|
||||||
|
#include <sys/asm_linkage.h>
|
||||||
|
|
||||||
|
#if defined(lint)
|
||||||
|
|
||||||
|
void *
|
||||||
|
getfp(void)
|
||||||
|
{
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
flush_windows(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
void
|
||||||
|
_breakpoint(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* lint */
|
||||||
|
|
||||||
|
ENTRY(getfp)
|
||||||
|
retl
|
||||||
|
mov %fp, %o0
|
||||||
|
SET_SIZE(getfp)
|
||||||
|
|
||||||
|
#ifdef UMEM_STANDALONE
|
||||||
|
#ifdef __sparcv9
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The caller doesn't need the top window to be flushed, so this
|
||||||
|
* is sufficient.
|
||||||
|
*/
|
||||||
|
ENTRY(flush_windows)
|
||||||
|
retl
|
||||||
|
flushw
|
||||||
|
SET_SIZE(flush_windows)
|
||||||
|
|
||||||
|
#else /* !__sparcv9 */
|
||||||
|
#error "This file does not provide a pre-v9 standalone flush_windows"
|
||||||
|
#endif /* __sparcv9 */
|
||||||
|
|
||||||
|
#else /* !UMEM_STANDALONE */
|
||||||
|
|
||||||
|
ENTRY(flush_windows)
|
||||||
|
retl
|
||||||
|
ta 0x3
|
||||||
|
SET_SIZE(flush_windows)
|
||||||
|
|
||||||
|
#endif /* UMEM_STANDALONE */
|
||||||
|
|
||||||
|
#ifndef UMEM_STANDALONE
|
||||||
|
ENTRY(_breakpoint)
|
||||||
|
retl
|
||||||
|
ta 0x1
|
||||||
|
SET_SIZE(_breakpoint)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* lint */
|
39
1.0.1/stand_mapfile
Normal file
39
1.0.1/stand_mapfile
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#
|
||||||
|
# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
# Use is subject to license terms.
|
||||||
|
#
|
||||||
|
# CDDL HEADER START
|
||||||
|
#
|
||||||
|
# The contents of this file are subject to the terms of the
|
||||||
|
# Common Development and Distribution License, Version 1.0 only
|
||||||
|
# (the "License"). You may not use this file except in compliance
|
||||||
|
# with the License.
|
||||||
|
#
|
||||||
|
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
# or http://www.opensolaris.org/os/licensing.
|
||||||
|
# See the License for the specific language governing permissions
|
||||||
|
# and limitations under the License.
|
||||||
|
#
|
||||||
|
# When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
# If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
#
|
||||||
|
# CDDL HEADER END
|
||||||
|
#
|
||||||
|
#ident "@(#)stand_mapfile 1.3 05/06/08 SMI"
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# This is a supplemental mapfile, used in addition to the standard one
|
||||||
|
# produced by the spec tools. This mapfile exposes an additional
|
||||||
|
# symbol (umem_startup) that is only present in the standalone version
|
||||||
|
# of libumem.
|
||||||
|
#
|
||||||
|
|
||||||
|
SUNWprivate1.1 {
|
||||||
|
global:
|
||||||
|
umem_startup;
|
||||||
|
umem_add;
|
||||||
|
};
|
125
1.0.1/stub_stand.c
Normal file
125
1.0.1/stub_stand.c
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma ident "@(#)stub_stand.c 1.3 05/06/08 SMI"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stubs for the standalone to reduce the dependence on external libraries
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <thread.h>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
_cond_init(cond_t *cvp, int type, void *arg)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
_cond_destroy(cond_t *cvp)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
_cond_wait(cond_t *cv, mutex_t *mutex)
|
||||||
|
{
|
||||||
|
umem_panic("attempt to wait on standumem cv %p", cv);
|
||||||
|
|
||||||
|
/*NOTREACHED*/
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
_cond_broadcast(cond_t *cvp)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_t
|
||||||
|
_thr_self(void)
|
||||||
|
{
|
||||||
|
return ((thread_t)1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static mutex_t _mp = DEFAULTMUTEX;
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
__mutex_init(mutex_t *mp, int type, void *arg)
|
||||||
|
{
|
||||||
|
(void) memcpy(mp, &_mp, sizeof (mutex_t));
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
__mutex_destroy(mutex_t *mp)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
__mutex_held(mutex_t *mp)
|
||||||
|
{
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
__mutex_lock(mutex_t *mp)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
__mutex_trylock(mutex_t *mp)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
int
|
||||||
|
__mutex_unlock(mutex_t *mp)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
issetugid(void)
|
||||||
|
{
|
||||||
|
return (1);
|
||||||
|
}
|
142
1.0.1/sys/vmem.h
Normal file
142
1.0.1/sys/vmem.h
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SYS_VMEM_H
|
||||||
|
#define _SYS_VMEM_H
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)vmem.h 1.13 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Per-allocation flags
|
||||||
|
*/
|
||||||
|
#define VM_SLEEP 0x00000000 /* same as KM_SLEEP */
|
||||||
|
#define VM_NOSLEEP 0x00000001 /* same as KM_NOSLEEP */
|
||||||
|
#define VM_PANIC 0x00000002 /* same as KM_PANIC */
|
||||||
|
#define VM_PUSHPAGE 0x00000004 /* same as KM_PUSHPAGE */
|
||||||
|
#define VM_KMFLAGS 0x000000ff /* flags that must match KM_* flags */
|
||||||
|
|
||||||
|
#define VM_BESTFIT 0x00000100
|
||||||
|
#define VM_FIRSTFIT 0x00000200
|
||||||
|
#define VM_NEXTFIT 0x00000400
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following flags are restricted for use only within the kernel.
|
||||||
|
* VM_MEMLOAD is for use by the HAT to avoid infinite recursion.
|
||||||
|
* VM_NORELOC is used by the kernel when static VA->PA mappings are required.
|
||||||
|
*/
|
||||||
|
#define VM_MEMLOAD 0x00000800
|
||||||
|
#define VM_NORELOC 0x00001000
|
||||||
|
/*
|
||||||
|
* VM_ABORT requests that vmem_alloc() *ignore* the VM_SLEEP/VM_NOSLEEP flags
|
||||||
|
* and forgo reaping if the allocation or attempted import, fails. This
|
||||||
|
* flag is a segkmem-specific flag, and should not be used by anyone else.
|
||||||
|
*/
|
||||||
|
#define VM_ABORT 0x00002000
|
||||||
|
|
||||||
|
#define VM_FLAGS 0x0000FFFF
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arena creation flags
|
||||||
|
*/
|
||||||
|
#define VMC_POPULATOR 0x00010000
|
||||||
|
#define VMC_NO_QCACHE 0x00020000 /* cannot use quantum caches */
|
||||||
|
#define VMC_IDENTIFIER 0x00040000 /* not backed by memory */
|
||||||
|
/*
|
||||||
|
* internal use only; the import function uses the vmem_ximport_t interface
|
||||||
|
* and may increase the request size if it so desires
|
||||||
|
*/
|
||||||
|
#define VMC_XALLOC 0x00080000
|
||||||
|
#define VMC_FLAGS 0xFFFF0000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Public segment types
|
||||||
|
*/
|
||||||
|
#define VMEM_ALLOC 0x01
|
||||||
|
#define VMEM_FREE 0x02
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Implementation-private segment types
|
||||||
|
*/
|
||||||
|
#define VMEM_SPAN 0x10
|
||||||
|
#define VMEM_ROTOR 0x20
|
||||||
|
#define VMEM_WALKER 0x40
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VMEM_REENTRANT indicates to vmem_walk() that the callback routine may
|
||||||
|
* call back into the arena being walked, so vmem_walk() must drop the
|
||||||
|
* arena lock before each callback. The caveat is that since the arena
|
||||||
|
* isn't locked, its state can change. Therefore it is up to the callback
|
||||||
|
* routine to handle cases where the segment isn't of the expected type.
|
||||||
|
* For example, we use this to walk heap_arena when generating a crash dump;
|
||||||
|
* see segkmem_dump() for sample usage.
|
||||||
|
*/
|
||||||
|
#define VMEM_REENTRANT 0x80000000
|
||||||
|
|
||||||
|
typedef struct vmem vmem_t;
|
||||||
|
typedef void *(vmem_alloc_t)(vmem_t *, size_t, int);
|
||||||
|
typedef void (vmem_free_t)(vmem_t *, void *, size_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Alternate import style; the requested size is passed in a pointer,
|
||||||
|
* which can be increased by the import function if desired.
|
||||||
|
*/
|
||||||
|
typedef void *(vmem_ximport_t)(vmem_t *, size_t *, int);
|
||||||
|
|
||||||
|
#ifdef _KERNEL
|
||||||
|
extern vmem_t *vmem_init(const char *, void *, size_t, size_t,
|
||||||
|
vmem_alloc_t *, vmem_free_t *);
|
||||||
|
extern void vmem_update(void *);
|
||||||
|
extern int vmem_is_populator();
|
||||||
|
extern size_t vmem_seg_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern vmem_t *vmem_create(const char *, void *, size_t, size_t,
|
||||||
|
vmem_alloc_t *, vmem_free_t *, vmem_t *, size_t, int);
|
||||||
|
extern vmem_t *vmem_xcreate(const char *, void *, size_t, size_t,
|
||||||
|
vmem_ximport_t *, vmem_free_t *, vmem_t *, size_t, int);
|
||||||
|
extern void vmem_destroy(vmem_t *);
|
||||||
|
extern void *vmem_alloc(vmem_t *, size_t, int);
|
||||||
|
extern void *vmem_xalloc(vmem_t *, size_t, size_t, size_t, size_t,
|
||||||
|
void *, void *, int);
|
||||||
|
extern void vmem_free(vmem_t *, void *, size_t);
|
||||||
|
extern void vmem_xfree(vmem_t *, void *, size_t);
|
||||||
|
extern void *vmem_add(vmem_t *, void *, size_t, int);
|
||||||
|
extern int vmem_contains(vmem_t *, void *, size_t);
|
||||||
|
extern void vmem_walk(vmem_t *, int, void (*)(void *, void *, size_t), void *);
|
||||||
|
extern size_t vmem_size(vmem_t *, int);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _SYS_VMEM_H */
|
165
1.0.1/sys/vmem_impl_user.h
Normal file
165
1.0.1/sys/vmem_impl_user.h
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 1999-2002 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SYS_VMEM_IMPL_USER_H
|
||||||
|
#define _SYS_VMEM_IMPL_USER_H
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)vmem_impl_user.h 1.2 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#if HAVE_SYS_KSTAT
|
||||||
|
#include <sys/kstat.h>
|
||||||
|
#endif
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
#include <sys/vmem.h>
|
||||||
|
#if HAVE_THREAD_H
|
||||||
|
#include <thread.h>
|
||||||
|
#else
|
||||||
|
# include "sol_compat.h"
|
||||||
|
#endif
|
||||||
|
#if HAVE_SYNC_H
|
||||||
|
#include <synch.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct vmem_seg vmem_seg_t;
|
||||||
|
|
||||||
|
#define VMEM_STACK_DEPTH 20
|
||||||
|
|
||||||
|
struct vmem_seg {
|
||||||
|
/*
|
||||||
|
* The first four fields must match vmem_freelist_t exactly.
|
||||||
|
*/
|
||||||
|
uintptr_t vs_start; /* start of segment (inclusive) */
|
||||||
|
uintptr_t vs_end; /* end of segment (exclusive) */
|
||||||
|
vmem_seg_t *vs_knext; /* next of kin (alloc, free, span) */
|
||||||
|
vmem_seg_t *vs_kprev; /* prev of kin */
|
||||||
|
|
||||||
|
vmem_seg_t *vs_anext; /* next in arena */
|
||||||
|
vmem_seg_t *vs_aprev; /* prev in arena */
|
||||||
|
uint8_t vs_type; /* alloc, free, span */
|
||||||
|
uint8_t vs_import; /* non-zero if segment was imported */
|
||||||
|
uint8_t vs_depth; /* stack depth if UMF_AUDIT active */
|
||||||
|
/*
|
||||||
|
* The following fields are present only when UMF_AUDIT is set.
|
||||||
|
*/
|
||||||
|
thread_t vs_thread;
|
||||||
|
hrtime_t vs_timestamp;
|
||||||
|
uintptr_t vs_stack[VMEM_STACK_DEPTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct vmem_freelist {
|
||||||
|
uintptr_t vs_start; /* always zero */
|
||||||
|
uintptr_t vs_end; /* segment size */
|
||||||
|
vmem_seg_t *vs_knext; /* next of kin */
|
||||||
|
vmem_seg_t *vs_kprev; /* prev of kin */
|
||||||
|
} vmem_freelist_t;
|
||||||
|
|
||||||
|
#define VS_SIZE(vsp) ((vsp)->vs_end - (vsp)->vs_start)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Segment hashing
|
||||||
|
*/
|
||||||
|
#define VMEM_HASH_INDEX(a, s, q, m) \
|
||||||
|
((((a) + ((a) >> (s)) + ((a) >> ((s) << 1))) >> (q)) & (m))
|
||||||
|
|
||||||
|
#define VMEM_HASH(vmp, addr) \
|
||||||
|
(&(vmp)->vm_hash_table[VMEM_HASH_INDEX(addr, \
|
||||||
|
(vmp)->vm_hash_shift, (vmp)->vm_qshift, (vmp)->vm_hash_mask)])
|
||||||
|
|
||||||
|
#define VMEM_NAMELEN 30
|
||||||
|
#define VMEM_HASH_INITIAL 16
|
||||||
|
#define VMEM_NQCACHE_MAX 16
|
||||||
|
#define VMEM_FREELISTS (sizeof (void *) * 8)
|
||||||
|
|
||||||
|
typedef struct vmem_kstat {
|
||||||
|
uint64_t vk_mem_inuse; /* memory in use */
|
||||||
|
uint64_t vk_mem_import; /* memory imported */
|
||||||
|
uint64_t vk_mem_total; /* total memory in arena */
|
||||||
|
uint32_t vk_source_id; /* vmem id of vmem source */
|
||||||
|
uint64_t vk_alloc; /* number of allocations */
|
||||||
|
uint64_t vk_free; /* number of frees */
|
||||||
|
uint64_t vk_wait; /* number of allocations that waited */
|
||||||
|
uint64_t vk_fail; /* number of allocations that failed */
|
||||||
|
uint64_t vk_lookup; /* hash lookup count */
|
||||||
|
uint64_t vk_search; /* freelist search count */
|
||||||
|
uint64_t vk_populate_wait; /* populates that waited */
|
||||||
|
uint64_t vk_populate_fail; /* populates that failed */
|
||||||
|
uint64_t vk_contains; /* vmem_contains() calls */
|
||||||
|
uint64_t vk_contains_search; /* vmem_contains() search cnt */
|
||||||
|
} vmem_kstat_t;
|
||||||
|
|
||||||
|
struct vmem {
|
||||||
|
char vm_name[VMEM_NAMELEN]; /* arena name */
|
||||||
|
cond_t vm_cv; /* cv for blocking allocations */
|
||||||
|
mutex_t vm_lock; /* arena lock */
|
||||||
|
uint32_t vm_id; /* vmem id */
|
||||||
|
uint32_t vm_mtbf; /* induced alloc failure rate */
|
||||||
|
int vm_cflags; /* arena creation flags */
|
||||||
|
int vm_qshift; /* log2(vm_quantum) */
|
||||||
|
size_t vm_quantum; /* vmem quantum */
|
||||||
|
size_t vm_qcache_max; /* maximum size to front by umem */
|
||||||
|
vmem_alloc_t *vm_source_alloc;
|
||||||
|
vmem_free_t *vm_source_free;
|
||||||
|
vmem_t *vm_source; /* vmem source for imported memory */
|
||||||
|
vmem_t *vm_next; /* next in vmem_list */
|
||||||
|
ssize_t vm_nsegfree; /* number of free vmem_seg_t's */
|
||||||
|
vmem_seg_t *vm_segfree; /* free vmem_seg_t list */
|
||||||
|
vmem_seg_t **vm_hash_table; /* allocated-segment hash table */
|
||||||
|
size_t vm_hash_mask; /* hash_size - 1 */
|
||||||
|
size_t vm_hash_shift; /* log2(vm_hash_mask + 1) */
|
||||||
|
ulong_t vm_freemap; /* bitmap of non-empty freelists */
|
||||||
|
vmem_seg_t vm_seg0; /* anchor segment */
|
||||||
|
vmem_seg_t vm_rotor; /* rotor for VM_NEXTFIT allocations */
|
||||||
|
vmem_seg_t *vm_hash0[VMEM_HASH_INITIAL]; /* initial hash table */
|
||||||
|
void *vm_qcache[VMEM_NQCACHE_MAX]; /* quantum caches */
|
||||||
|
vmem_freelist_t vm_freelist[VMEM_FREELISTS + 1]; /* power-of-2 flists */
|
||||||
|
vmem_kstat_t vm_kstat; /* kstat data */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We cannot use a mutex_t and MUTEX_HELD, since that will not work
|
||||||
|
* when libthread is not linked.
|
||||||
|
*/
|
||||||
|
typedef struct vmem_populate_lock {
|
||||||
|
mutex_t vmpl_mutex;
|
||||||
|
thread_t vmpl_thr;
|
||||||
|
} vmem_populate_lock_t;
|
||||||
|
|
||||||
|
#define VM_UMFLAGS VM_KMFLAGS
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _SYS_VMEM_IMPL_USER_H */
|
3191
1.0.1/umem.c
Normal file
3191
1.0.1/umem.c
Normal file
File diff suppressed because it is too large
Load diff
88
1.0.1/umem.h
Normal file
88
1.0.1/umem.h
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UMEM_H
|
||||||
|
#define _UMEM_H
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)umem.h 1.3 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/vmem.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UMEM_DEFAULT 0x0000 /* normal -- may fail */
|
||||||
|
#define UMEM_NOFAIL 0x0100 /* Never fails -- may call exit(2) */
|
||||||
|
|
||||||
|
#define UMEM_FLAGS 0xffff /* all settable umem flags */
|
||||||
|
|
||||||
|
extern void *umem_alloc(size_t, int);
|
||||||
|
extern void *umem_alloc_align(size_t, size_t, int);
|
||||||
|
extern void *umem_zalloc(size_t, int);
|
||||||
|
extern void umem_free(void *, size_t);
|
||||||
|
extern void umem_free_align(void *, size_t);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Flags for umem_cache_create()
|
||||||
|
*/
|
||||||
|
/*@{*/
|
||||||
|
#define UMC_NOTOUCH 0x00010000
|
||||||
|
#define UMC_NODEBUG 0x00020000
|
||||||
|
#define UMC_NOMAGAZINE 0x00040000
|
||||||
|
#define UMC_NOHASH 0x00080000
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
struct umem_cache; /* cache structure is opaque to umem clients */
|
||||||
|
|
||||||
|
typedef struct umem_cache umem_cache_t;
|
||||||
|
typedef int umem_constructor_t(void *, void *, int);
|
||||||
|
typedef void umem_destructor_t(void *, void *);
|
||||||
|
typedef void umem_reclaim_t(void *);
|
||||||
|
|
||||||
|
typedef int umem_nofail_callback_t(void);
|
||||||
|
#define UMEM_CALLBACK_RETRY 0
|
||||||
|
#define UMEM_CALLBACK_EXIT(status) (0x100 | ((status) & 0xFF))
|
||||||
|
|
||||||
|
extern void umem_nofail_callback(umem_nofail_callback_t *);
|
||||||
|
|
||||||
|
extern umem_cache_t *umem_cache_create(char *, size_t,
|
||||||
|
size_t, umem_constructor_t *, umem_destructor_t *, umem_reclaim_t *,
|
||||||
|
void *, vmem_t *, int);
|
||||||
|
extern void umem_cache_destroy(umem_cache_t *);
|
||||||
|
|
||||||
|
extern void *umem_cache_alloc(umem_cache_t *, int);
|
||||||
|
extern void umem_cache_free(umem_cache_t *, void *);
|
||||||
|
|
||||||
|
extern void umem_reap(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _UMEM_H */
|
129
1.0.1/umem.spec.in
Normal file
129
1.0.1/umem.spec.in
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
Name: @PACKAGE_NAME@
|
||||||
|
Version: @PACKAGE_VERSION@
|
||||||
|
Release: 2%{?dist}
|
||||||
|
Summary: Port of Solaris's slab allocator.
|
||||||
|
|
||||||
|
Group: System Environment/Libraries
|
||||||
|
License: CDDL
|
||||||
|
URL: https://labs.omniti.com/trac/portableumem/
|
||||||
|
Source0: %{name}-%{version}.tar.bz2
|
||||||
|
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||||
|
|
||||||
|
BuildRequires: autoconf >= 2.50
|
||||||
|
BuildRequires: automake >= 1.4
|
||||||
|
BuildRequires: libtool >= 1.4.2
|
||||||
|
BuildRequires: doxygen
|
||||||
|
BuildRequires: gcc
|
||||||
|
BuildRequires: binutils
|
||||||
|
BuildRequires: make
|
||||||
|
BuildRequires: mktemp
|
||||||
|
|
||||||
|
|
||||||
|
%description
|
||||||
|
This a port of Solaris's slab allocator, libumem, to Linux.
|
||||||
|
|
||||||
|
"A slab allocator is a cache management structure for efficient use
|
||||||
|
of [...] memory. [...] It is targeted for use of many small pieces
|
||||||
|
of memory chunks. By managing small memory chunks in the units
|
||||||
|
called slabs, this mechanism enables lower fragmentation, fast allocation,
|
||||||
|
and reclaming memory." (Description sourced from Wikipedia.)
|
||||||
|
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup -q
|
||||||
|
|
||||||
|
|
||||||
|
%build
|
||||||
|
%configure
|
||||||
|
%{__make}
|
||||||
|
%{__make} check
|
||||||
|
%{__make} html
|
||||||
|
|
||||||
|
|
||||||
|
%install
|
||||||
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
%makeinstall
|
||||||
|
|
||||||
|
# Remove the libtool files -- we don't want them.
|
||||||
|
find $RPM_BUILD_ROOT%{_libdir} -name '*.la' | xargs rm -fv
|
||||||
|
|
||||||
|
# Remove the symlink to the SONAME. Let ldconfig manage that.
|
||||||
|
rm -fv $RPM_BUILD_ROOT%{_libdir}/*.so.[0-9]
|
||||||
|
|
||||||
|
# Build the pkgconfig configurations.
|
||||||
|
mkdir -p $RPM_BUILD_ROOT%{_libdir}/pkgconfig
|
||||||
|
|
||||||
|
cat<<EOT >$RPM_BUILD_ROOT%{_libdir}/pkgconfig/%{name}-%{version}.pc
|
||||||
|
prefix=%{_prefix}
|
||||||
|
exec_prefix=%{_exec_prefix}
|
||||||
|
libdir=%{_libdir}
|
||||||
|
includedir=%{_includedir}
|
||||||
|
|
||||||
|
Name: %{name}
|
||||||
|
Version: %{version}
|
||||||
|
Description: Port of Solaris's slab allocator.
|
||||||
|
URL: https://labs.omniti.com/trac/portableumem/
|
||||||
|
Requires:
|
||||||
|
Libs: -L\${libdir} -lumem
|
||||||
|
Cflags:
|
||||||
|
EOT
|
||||||
|
|
||||||
|
cat<<EOT >$RPM_BUILD_ROOT%{_libdir}/pkgconfig/%{name}-malloc-%{version}.pc
|
||||||
|
prefix=%{_prefix}
|
||||||
|
exec_prefix=%{_exec_prefix}
|
||||||
|
libdir=%{_libdir}
|
||||||
|
includedir=%{_includedir}
|
||||||
|
|
||||||
|
Name: %{name}
|
||||||
|
Version: %{version}
|
||||||
|
Description: Port of Solaris's slab allocator. Libc malloc replacement.
|
||||||
|
URL: https://labs.omniti.com/trac/portableumem/
|
||||||
|
Requires:
|
||||||
|
Libs: -L\${libdir} -lumem_malloc
|
||||||
|
Cflags:
|
||||||
|
EOT
|
||||||
|
|
||||||
|
|
||||||
|
%clean
|
||||||
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
|
||||||
|
|
||||||
|
%pre
|
||||||
|
/sbin/ldconfig
|
||||||
|
|
||||||
|
|
||||||
|
%post
|
||||||
|
/sbin/ldconfig
|
||||||
|
|
||||||
|
|
||||||
|
%files
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%doc AUTHORS COPYING COPYRIGHT INSTALL NEWS OPENSOLARIS.LICENSE README
|
||||||
|
%{_libdir}/*.so.*
|
||||||
|
|
||||||
|
|
||||||
|
%package devel
|
||||||
|
|
||||||
|
Summary: Port of Solaris's slab allocator.
|
||||||
|
|
||||||
|
Group: Development/Libraries
|
||||||
|
|
||||||
|
Requires: pkgconfig
|
||||||
|
|
||||||
|
|
||||||
|
%description devel
|
||||||
|
|
||||||
|
This contains the libraries and header files for using this port
|
||||||
|
of Solaris's slab allocator, libumem, to Linux.
|
||||||
|
|
||||||
|
|
||||||
|
%files devel
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%doc AUTHORS COPYING COPYRIGHT INSTALL NEWS OPENSOLARIS.LICENSE README TODO
|
||||||
|
%doc docs/html
|
||||||
|
%{_includedir}/*.h
|
||||||
|
%{_includedir}/sys/*.h
|
||||||
|
%{_libdir}/*.so
|
||||||
|
%{_libdir}/*.a
|
||||||
|
%{_mandir}/man*/*
|
||||||
|
%{_libdir}/pkgconfig/*.pc
|
50
1.0.1/umem_agent_support.c
Normal file
50
1.0.1/umem_agent_support.c
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)umem_agent_support.c 1.2 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "umem_base.h"
|
||||||
|
|
||||||
|
#define AGENT_STACK_SIZE 4096
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
char __umem_agent_stack_beg[AGENT_STACK_SIZE];
|
||||||
|
char *__umem_agent_stack_end = __umem_agent_stack_beg + AGENT_STACK_SIZE;
|
||||||
|
|
||||||
|
void
|
||||||
|
__umem_agent_free_bp(umem_cache_t *cp, void *buf)
|
||||||
|
{
|
||||||
|
extern void _breakpoint(void); /* inline asm */
|
||||||
|
|
||||||
|
_umem_cache_free(cp, buf);
|
||||||
|
_breakpoint();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
525
1.0.1/umem_alloc.3
Normal file
525
1.0.1/umem_alloc.3
Normal file
|
@ -0,0 +1,525 @@
|
||||||
|
'\" te
|
||||||
|
.\" CDDL HEADER START
|
||||||
|
.\"
|
||||||
|
.\" The contents of this file are subject to the terms of the
|
||||||
|
.\" Common Development and Distribution License (the "License").
|
||||||
|
.\" You may not use this file except in compliance with the License.
|
||||||
|
.\"
|
||||||
|
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
.\" or http://www.opensolaris.org/os/licensing.
|
||||||
|
.\" See the License for the specific language governing permissions
|
||||||
|
.\" and limitations under the License.
|
||||||
|
.\"
|
||||||
|
.\" When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
.\" If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
.\" fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
.\" information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
.\"
|
||||||
|
.\" CDDL HEADER END
|
||||||
|
.\" Copyright (c) 2002, Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
.TH umem_alloc 3MALLOC "26 Aug 2002" "SunOS 5.11" "Memory Allocation Library Functions"
|
||||||
|
.SH NAME
|
||||||
|
umem_alloc, umem_zalloc, umem_free, umem_nofail_callback \- fast, scalable memory allocation
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
cc [ \fIflag \&.\|.\|.\fR ] \fIfile\fR\&.\|.\|. \fB-lumem\fR [ \fIlibrary \&.\|.\|.\fR ]
|
||||||
|
#include <umem.h>
|
||||||
|
|
||||||
|
\fBvoid *\fR\fBumem_alloc\fR(\fBsize_t\fR \fIsize\fR, \fBint\fR \fIflags\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid *\fR\fBumem_zalloc\fR(\fBsize_t\fR \fIsize\fR, \fBint\fR \fIflags\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid\fR \fBumem_free\fR(\fBvoid *\fR\fIbuf\fR, \fBsize_t\fR \fIsize\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid\fR \fBumem_nofail_callback\fR(\fB(int (*\fR\fIcallback\fR)(void));
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid *\fR\fBmalloc\fR(\fBsize_t\fR \fIsize\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid *\fR\fBcalloc\fR(\fBsize_t\fR \fInelem\fR, \fBsize_t\fR \fIelsize\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid\fR \fBfree\fR(\fBvoid *\fR\fIptr\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid *\fR\fBmemalign\fR(\fBsize_t\fR \fIalignment\fR, \fBsize_t\fR \fIsize\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid *\fR\fBrealloc\fR(\fBvoid *\fR\fIptr\fR, \fBsize_t\fR \fIsize\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid *\fR\fBvalloc\fR(\fBsize_t\fR \fIsize\fR);
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBumem_alloc()\fR function returns a pointer to a block of \fIsize\fR bytes suitably aligned for any variable type. The initial contents of memory allocated using \fBumem_alloc()\fR is undefined. The \fIflags\fR argument determines
|
||||||
|
the behavior of \fBumem_alloc()\fR if it is unable to fulfill the request. The \fIflags\fR argument can take the following values:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBUMEM_DEFAULT\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 14n
|
||||||
|
.rt
|
||||||
|
Return \fINULL\fR on failure.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBUMEM_NOFAIL\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 14n
|
||||||
|
.rt
|
||||||
|
Call an optional \fIcallback\fR (set with \fBumem_nofail_callback()\fR) on failure. The \fIcallback\fR takes no arguments and can finish by:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
returning \fBUMEM_CALLBACK_RETRY\fR, in which case the allocation will be retried. If the allocation fails, the callback will be invoked again.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
returning \fBUMEM_CALLBACK_EXIT\fR(\fIstatus\fR), in which case
|
||||||
|
\fBexit\fR(2) is invoked with \fIstatus\fR
|
||||||
|
as its argument. The \fBexit()\fR function is called only once. If multiple threads return from the \fBUMEM_NOFAIL\fR callback with \fBUMEM_CALLBACK_EXIT\fR(\fIstatus\fR), one will call \fBexit()\fR while the other blocks until \fBexit()\fR terminates the program.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
invoking a context-changing function (
|
||||||
|
\fBsetcontext\fR(2)) or a non-local jump (
|
||||||
|
\fBlongjmp\fR(3C) or
|
||||||
|
\fBsiglongjmp\fR(3C), or ending the current thread of control (
|
||||||
|
\fBthr_exit\fR(3C) or
|
||||||
|
\fBpthread_exit\fR(3C). The application is responsible for any necessary cleanup. The state of \fBlibumem\fR remains consistent.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
If no callback has been set or the callback has been set to \fINULL\fR, \fBumem_alloc\fR(..., \fBUMEM_NOFAIL\fR) behaves as though the callback returned \fBUMEM_CALLBACK_EXIT\fR(255).
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
The \fBlibumem\fR library can call callbacks from any place that a \fBUMEM_NOFAIL\fR allocation is issued. In multithreaded applications, callbacks are expected to perform their own concurrency management.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The function call \fBumem_alloc\fR(0, \fIflag\fR) always returns \fINULL\fR. The function call \fBumem_free\fR(\fINULL\fR, 0) is allowed.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBumem_zalloc()\fR function has the same semantics as \fBumem_alloc()\fR, but the block of memory is initialized to zeros before it is returned.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBumem_free()\fR function frees blocks previously allocated using \fBumem_alloc()\fR and \fBumem_zalloc()\fR. The buffer address and size must exactly match the original allocation. Memory must not be returned piecemeal.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBumem_nofail_callback()\fR function sets the process-wide UMEM_NOFAIL callback. See the description of UMEM_NOFAIL for more information.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBmalloc()\fR, \fBcalloc()\fR, \fBfree()\fR, \fBmemalign()\fR, \fBrealloc()\fR, and \fBvalloc()\fR functions are are as described in
|
||||||
|
\fBmalloc\fR(3C). The \fBlibumem\fR library provides these functions for backwards-compatibility with the standard functions.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH ENVIRONMENT VARIABLES
|
||||||
|
|
||||||
|
.LP
|
||||||
|
See
|
||||||
|
\fBumem_debug\fR(3MALLOC) for environment variables that effect the debugging features of the \fBlibumem\fR library.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fBUMEM_OPTIONS\fR
|
||||||
|
.ad
|
||||||
|
.RS 14n
|
||||||
|
.rt
|
||||||
|
Contains a list of comma-separated options. Unrecognized options are ignored. The options that are supported are:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBbackend\fR=\fBsbrk\fR\fR
|
||||||
|
.ad
|
||||||
|
.br
|
||||||
|
.na
|
||||||
|
\fB\fBbackend\fR=\fBmmap\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 14n
|
||||||
|
.rt
|
||||||
|
Set the underlying function used to allocate memory. This option can be set to \fBsbrk\fR (the default) for an
|
||||||
|
\fBsbrk\fR(2)-based source or \fBmmap\fR for an
|
||||||
|
\fBmmap\fR(2)-based
|
||||||
|
source. If set to a value that is not supported, \fBsbrk\fR will be used.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH EXAMPLES
|
||||||
|
.LP
|
||||||
|
\fBExample 1 \fRUsing the \fBumem_alloc()\fR function.
|
||||||
|
|
||||||
|
.LP
|
||||||
|
.in +2
|
||||||
|
.nf
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <umem.h>
|
||||||
|
\&...
|
||||||
|
char *buf = umem_alloc(1024, UMEM_DEFAULT);
|
||||||
|
|
||||||
|
if (buf == NULL) {
|
||||||
|
fprintf(stderr, "out of memory\en");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
/* cannot assume anything about buf's contents */
|
||||||
|
\&...
|
||||||
|
umem_free(buf, 1024);
|
||||||
|
\&...
|
||||||
|
.fi
|
||||||
|
.in -2
|
||||||
|
.LP
|
||||||
|
\fBExample 2 \fRUsing the \fBumem_zalloc()\fR function
|
||||||
|
|
||||||
|
.LP
|
||||||
|
.in +2
|
||||||
|
.nf
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <umem.h>
|
||||||
|
\&...
|
||||||
|
char *buf = umem_zalloc(1024, UMEM_DEFAULT);
|
||||||
|
|
||||||
|
if (buf == NULL) {
|
||||||
|
fprintf(stderr, "out of memory\en");
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
/* buf contains zeros */
|
||||||
|
\&...
|
||||||
|
umem_free(buf, 1024);
|
||||||
|
\&...
|
||||||
|
.fi
|
||||||
|
.in -2
|
||||||
|
.LP
|
||||||
|
\fBExample 3 \fRUsing UMEM_NOFAIL
|
||||||
|
|
||||||
|
.LP
|
||||||
|
.in +2
|
||||||
|
.nf
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <umem.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note that the allocation code below does not have to
|
||||||
|
* check for umem_alloc() returning NULL
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
my_failure_handler(void)
|
||||||
|
{
|
||||||
|
(void) fprintf(stderr, "out of memory\en");
|
||||||
|
return (UMEM_CALLBACK_EXIT(255));
|
||||||
|
}
|
||||||
|
\&...
|
||||||
|
umem_nofail_callback(my_failure_handler);
|
||||||
|
\&...
|
||||||
|
int i;
|
||||||
|
char *buf[100];
|
||||||
|
|
||||||
|
for (i = 0; i < 100; i++)
|
||||||
|
buf[i] = umem_alloc(1024 * 1024, UMEM_NOFAIL);
|
||||||
|
\&...
|
||||||
|
for (i = 0; i < 100; i++)
|
||||||
|
umem_free(buf[i], 1024 * 1024);
|
||||||
|
\&...
|
||||||
|
.fi
|
||||||
|
.in -2
|
||||||
|
.LP
|
||||||
|
\fBExample 4 \fRUsing UMEM_NOFAIL in a multithreaded application
|
||||||
|
|
||||||
|
.LP
|
||||||
|
.in +2
|
||||||
|
.nf
|
||||||
|
#define _REENTRANT
|
||||||
|
#include <thread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <umem.h>
|
||||||
|
|
||||||
|
void *
|
||||||
|
start_func(void *the_arg)
|
||||||
|
{
|
||||||
|
int *info = (int *)the_arg;
|
||||||
|
char *buf = umem_alloc(1024 * 1024, UMEM_NOFAIL);
|
||||||
|
|
||||||
|
/* does not need to check for buf == NULL */
|
||||||
|
buf[0] = 0;
|
||||||
|
...
|
||||||
|
/*
|
||||||
|
* if there were other UMEM_NOFAIL allocations,
|
||||||
|
* we would need to arrange for buf to be
|
||||||
|
* umem_free()ed upon failure.
|
||||||
|
*/
|
||||||
|
...
|
||||||
|
umem_free(buf, 1024 * 1024);
|
||||||
|
return (the_arg);
|
||||||
|
}
|
||||||
|
\&...
|
||||||
|
int
|
||||||
|
my_failure_handler(void)
|
||||||
|
{
|
||||||
|
/* terminate the current thread with status NULL */
|
||||||
|
thr_exit(NULL);
|
||||||
|
}
|
||||||
|
\&...
|
||||||
|
umem_nofail_callback(my_failure_handler);
|
||||||
|
\&...
|
||||||
|
int my_arg;
|
||||||
|
|
||||||
|
thread_t tid;
|
||||||
|
void *status;
|
||||||
|
|
||||||
|
(void) thr_create(NULL, NULL, start_func, &my_arg, 0,
|
||||||
|
NULL);
|
||||||
|
\&...
|
||||||
|
while (thr_join(0, &tid, &status) != 0)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (status == NULL) {
|
||||||
|
(void) fprintf(stderr, "thread %d ran out of memory\en",
|
||||||
|
tid);
|
||||||
|
}
|
||||||
|
\&...
|
||||||
|
.fi
|
||||||
|
.in -2
|
||||||
|
|
||||||
|
.SH ATTRIBUTES
|
||||||
|
|
||||||
|
.LP
|
||||||
|
See
|
||||||
|
\fBattributes\fR(5) for descriptions of the following attributes:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.TS
|
||||||
|
tab() box;
|
||||||
|
cw(2.75i) |cw(2.75i)
|
||||||
|
lw(2.75i) |lw(2.75i)
|
||||||
|
.
|
||||||
|
ATTRIBUTE TYPEATTRIBUTE VALUE
|
||||||
|
_
|
||||||
|
Interface StabilitySee below.
|
||||||
|
_
|
||||||
|
MT-LevelMT-Safe
|
||||||
|
.TE
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBmalloc()\fR, \fBcalloc()\fR, \fBfree()\fR, \fBrealloc()\fR, and \fBvalloc()\fR functions are Standard. The \fBmemalign()\fR function is Stable. The \fBumem_alloc()\fR, \fBumem_zalloc()\fR, \fBumem_free()\fR, and \fBumem_nofail_callback()\fR functions are Evolving.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
|
||||||
|
.LP
|
||||||
|
|
||||||
|
\fBexit\fR(2),
|
||||||
|
\fBmmap\fR(2),
|
||||||
|
\fBsbrk\fR(2),
|
||||||
|
\fBbsdmalloc\fR(3MALLOC),
|
||||||
|
\fBlibumem\fR(3LIB),
|
||||||
|
\fBlongjmp\fR(3C),
|
||||||
|
\fBmalloc\fR(3C),
|
||||||
|
\fBmalloc\fR(3MALLOC),
|
||||||
|
\fBmapmalloc\fR(3MALLOC),
|
||||||
|
\fBpthread_exit\fR(3C),
|
||||||
|
\fBthr_exit\fR(3C),
|
||||||
|
\fBumem_cache_create\fR(3MALLOC),
|
||||||
|
\fBumem_debug\fR(3MALLOC),
|
||||||
|
\fBwatchmalloc\fR(3MALLOC),
|
||||||
|
\fBattributes\fR(5),
|
||||||
|
\fBstandards\fR(5)
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH WARNINGS
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Any of the following can cause undefined results:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Passing a pointer returned from \fBumem_alloc()\fR or \fBumem_zalloc()\fR to \fBfree()\fR or \fBrealloc()\fR.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Passing a pointer returned from \fBmalloc()\fR, \fBcalloc()\fR, \fBvalloc()\fR, \fBmemalign()\fR, or \fBrealloc()\fR to \fBumem_free()\fR.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Writing past the end of a buffer allocated using \fBumem_alloc()\fR or \fBumem_zalloc()\fR
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Performing \fBUMEM_NOFAIL\fR allocations from an
|
||||||
|
\fBatexit\fR(3C) handler.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.LP
|
||||||
|
If the \fBUMEM_NOFAIL\fR callback performs \fBUMEM_NOFAIL\fR allocations, infinite recursion can occur.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH NOTES
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The following list compares the features of the
|
||||||
|
\fBmalloc\fR(3C),
|
||||||
|
\fBbsdmalloc\fR(3MALLOC),
|
||||||
|
\fBmalloc\fR(3MALLOC),
|
||||||
|
\fBmtmalloc\fR(3MALLOC) , and the \fBlibumem\fR
|
||||||
|
functions.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
The
|
||||||
|
\fBmalloc\fR(3C),
|
||||||
|
\fBbsdmalloc\fR(3MALLOC), and
|
||||||
|
\fBmalloc\fR(3MALLOC) functions have no support for concurrency. The \fBlibumem\fR and
|
||||||
|
\fBmtmalloc\fR(3MALLOC)
|
||||||
|
functions support concurrent allocations.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
The
|
||||||
|
\fBbsdmalloc\fR(3MALLOC) functions afford better performance but are space-inefficient.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
The
|
||||||
|
\fBmalloc\fR(3MALLOC) functions are space-efficient but have slower performance.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
The standard, fully SCD-compliant
|
||||||
|
\fBmalloc\fR(3C) functions are a trade-off between performance and space-efficiency.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
The
|
||||||
|
\fBmtmalloc\fR(3MALLOC) functions provide fast, concurrent \fBmalloc()\fR implementations that are not space-efficient.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
The \fBlibumem\fR functions provide a fast, concurrent allocation implementation that in most cases is more space-efficient than
|
||||||
|
\fBmtmalloc\fR(3MALLOC).
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
143
1.0.1/umem_base.h
Normal file
143
1.0.1/umem_base.h
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UMEM_BASE_H
|
||||||
|
#define _UMEM_BASE_H
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)umem_base.h 1.4 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include <umem_impl.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
extern size_t pagesize;
|
||||||
|
#undef PAGESIZE
|
||||||
|
#define PAGESIZE pagesize
|
||||||
|
|
||||||
|
/*
|
||||||
|
* umem.c: non-tunables
|
||||||
|
*/
|
||||||
|
extern vmem_t *umem_memalign_arena;
|
||||||
|
|
||||||
|
extern int umem_ready;
|
||||||
|
extern thread_t umem_init_thr; /* the thread doing the init */
|
||||||
|
|
||||||
|
extern int umem_init(void); /* do umem's initialization */
|
||||||
|
/* #pragma rarely_called(umem_init) */
|
||||||
|
|
||||||
|
extern umem_log_header_t *umem_transaction_log;
|
||||||
|
extern umem_log_header_t *umem_content_log;
|
||||||
|
extern umem_log_header_t *umem_failure_log;
|
||||||
|
extern umem_log_header_t *umem_slab_log;
|
||||||
|
|
||||||
|
extern mutex_t umem_init_lock;
|
||||||
|
|
||||||
|
extern mutex_t umem_cache_lock;
|
||||||
|
extern umem_cache_t umem_null_cache;
|
||||||
|
|
||||||
|
extern mutex_t umem_flags_lock;
|
||||||
|
|
||||||
|
extern mutex_t umem_update_lock;
|
||||||
|
extern cond_t umem_update_cv;
|
||||||
|
extern volatile thread_t umem_st_update_thr;
|
||||||
|
extern thread_t umem_update_thr;
|
||||||
|
extern struct timeval umem_update_next;
|
||||||
|
|
||||||
|
extern volatile hrtime_t umem_reap_next;
|
||||||
|
extern volatile uint32_t umem_reaping;
|
||||||
|
#define UMEM_REAP_DONE 0x00000000 /* inactive */
|
||||||
|
#define UMEM_REAP_ADDING 0x00000001 /* umem_reap() is active */
|
||||||
|
#define UMEM_REAP_ACTIVE 0x00000002 /* update thread is reaping */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* umem.c: tunables
|
||||||
|
*/
|
||||||
|
extern uint32_t umem_max_ncpus;
|
||||||
|
|
||||||
|
extern uint32_t umem_stack_depth;
|
||||||
|
extern uint32_t umem_reap_interval;
|
||||||
|
extern uint32_t umem_update_interval;
|
||||||
|
extern uint32_t umem_depot_contention;
|
||||||
|
extern uint32_t umem_abort;
|
||||||
|
extern uint32_t umem_output;
|
||||||
|
extern uint32_t umem_logging;
|
||||||
|
extern uint32_t umem_mtbf;
|
||||||
|
extern size_t umem_transaction_log_size;
|
||||||
|
extern size_t umem_content_log_size;
|
||||||
|
extern size_t umem_failure_log_size;
|
||||||
|
extern size_t umem_slab_log_size;
|
||||||
|
extern size_t umem_content_maxsave;
|
||||||
|
extern size_t umem_lite_minsize;
|
||||||
|
extern size_t umem_lite_maxalign;
|
||||||
|
extern size_t umem_maxverify;
|
||||||
|
extern size_t umem_minfirewall;
|
||||||
|
|
||||||
|
extern uint32_t umem_flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* umem.c: Internal aliases (to avoid PLTs)
|
||||||
|
*/
|
||||||
|
extern void *_umem_alloc(size_t size, int umflags);
|
||||||
|
extern void *_umem_zalloc(size_t size, int umflags);
|
||||||
|
extern void _umem_free(void *buf, size_t size);
|
||||||
|
|
||||||
|
extern void *_umem_cache_alloc(umem_cache_t *cache, int flags);
|
||||||
|
extern void _umem_cache_free(umem_cache_t *cache, void *buffer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* umem.c: private interfaces
|
||||||
|
*/
|
||||||
|
extern void umem_type_init(caddr_t, size_t, size_t);
|
||||||
|
extern int umem_get_max_ncpus(void);
|
||||||
|
extern void umem_process_updates(void);
|
||||||
|
extern void umem_cache_applyall(void (*)(umem_cache_t *));
|
||||||
|
extern void umem_cache_update(umem_cache_t *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* umem_fork.c: private interfaces
|
||||||
|
*/
|
||||||
|
extern void umem_forkhandler_init(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* umem_update_thread.c
|
||||||
|
*/
|
||||||
|
extern int umem_create_update_thread(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* envvar.c:
|
||||||
|
*/
|
||||||
|
void umem_setup_envvars(int);
|
||||||
|
void umem_process_envvars(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _UMEM_BASE_H */
|
815
1.0.1/umem_cache_create.3
Normal file
815
1.0.1/umem_cache_create.3
Normal file
|
@ -0,0 +1,815 @@
|
||||||
|
'\" te
|
||||||
|
.\" CDDL HEADER START
|
||||||
|
.\"
|
||||||
|
.\" The contents of this file are subject to the terms of the
|
||||||
|
.\" Common Development and Distribution License (the "License").
|
||||||
|
.\" You may not use this file except in compliance with the License.
|
||||||
|
.\"
|
||||||
|
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
.\" or http://www.opensolaris.org/os/licensing.
|
||||||
|
.\" See the License for the specific language governing permissions
|
||||||
|
.\" and limitations under the License.
|
||||||
|
.\"
|
||||||
|
.\" When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
.\" If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
.\" fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
.\" information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
.\"
|
||||||
|
.\" CDDL HEADER END
|
||||||
|
.\" Copyright (c) 2003, Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
.TH umem_cache_create 3MALLOC "4 Nov 2003" "SunOS 5.11" "Memory Allocation Library Functions"
|
||||||
|
.SH NAME
|
||||||
|
umem_cache_create, umem_cache_destroy, umem_cache_alloc, umem_cache_free \- allocation cache manipulation
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
cc [ \fIflag \&.\|.\|.\fR ] \fIfile\fR\&.\|.\|. \fB-lumem\fR [ \fIlibrary \&.\|.\|.\fR ]
|
||||||
|
#include <umem.h>
|
||||||
|
|
||||||
|
\fBumem_cache_t *\fR\fBumem_cache_create\fR(\fBchar *\fR\fIdebug_name\fR, \fBsize_t\fR \fIbufsize\fR,
|
||||||
|
\fBsize_t\fR \fIalign\fR, \fBumem_constructor_t *\fR\fIconstructor\fR,
|
||||||
|
\fBumem_destructor_t *\fR\fIdestructor\fR, \fBumem_reclaim_t *\fR\fIreclaim\fR,
|
||||||
|
\fBvoid *\fR\fIcallback_data\fR, \fBvmem_t *\fR\fIsource\fR, \fBint\fR \fIcflags\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid\fR \fBumem_cache_destroy\fR(\fBumem_cache_t *\fR\fIcache\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid *\fR\fBumem_cache_alloc\fR(\fBumem_cache_t *\fR\fIcache\fR, \fBint\fR \fIflags\fR);
|
||||||
|
.fi
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBvoid\fR \fBumem_cache_free\fR(\fBumem_cache_t *\fR\fIcache\fR, \fBvoid *\fR\fIbuffer\fR);
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
|
||||||
|
.LP
|
||||||
|
These functions create, destroy, and use an "object cache". An object cache is a collection of buffers of a single size, with optional content caching enabled by the use of callbacks (see \fBCache Callbacks\fR). Object caches are MT-Safe. Multiple allocations and freeing of
|
||||||
|
memory from different threads can proceed simultaneously. Object caches are faster and use less space per buffer than
|
||||||
|
\fBmalloc\fR(3MALLOC) and
|
||||||
|
\fBumem_alloc\fR(3MALLOC). For more information about object caching, see "The Slab Allocator: An Object-Caching Kernel Memory Allocator" and "Magazines
|
||||||
|
and vmem: Extending the Slab Allocator to Many CPUs and Arbitrary Resources".
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBumem_cache_create()\fR function creates object caches. Once a cache has been created, objects can be requested from and returned to the cache using \fBumem_cache_alloc()\fR and \fBumem_cache_free()\fR, respectively. A cache with no outstanding
|
||||||
|
buffers can be destroyed with \fBumem_cache_destroy()\fR.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SS Creating and Destroying Caches
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBumem_cache_create()\fR function creates a cache of objects and takes as arguments the following:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIdebug_name\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 15n
|
||||||
|
.rt
|
||||||
|
A human-readable name for debugging purposes.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIbufsize\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 15n
|
||||||
|
.rt
|
||||||
|
The size, in bytes, of the buffers in this cache.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIalign\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 15n
|
||||||
|
.rt
|
||||||
|
The minimum alignment required for buffers in this cache. This parameter must be a power of 2. If 0, it is replaced with the minimum required alignment for the current architecture.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIconstructor\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 15n
|
||||||
|
.rt
|
||||||
|
The callback to construct an object.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIdestructor\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 15n
|
||||||
|
.rt
|
||||||
|
The callback to destroy an object.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIreclaim\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 15n
|
||||||
|
.rt
|
||||||
|
The callback to reclaim objects.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIcallback_data\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 15n
|
||||||
|
.rt
|
||||||
|
An opaque pointer passed to the callbacks.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIsource\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 15n
|
||||||
|
.rt
|
||||||
|
This parameter must be \fINULL\fR.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIcflags\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 15n
|
||||||
|
.rt
|
||||||
|
This parameter must be either 0 or \fBUMC_NODEBUG\fR. If \fBUMC_NODEBUG\fR, all debugging features are disabled for this cache. See
|
||||||
|
\fBumem_debug\fR(3MALLOC).
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Each cache can have up to three associated callbacks:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
.in +2
|
||||||
|
.nf
|
||||||
|
int constructor(void *buffer, void *callback_data, int flags);
|
||||||
|
void destructor(void *buffer, void *callback_data);
|
||||||
|
void reclaim(void *callback_data);
|
||||||
|
.fi
|
||||||
|
.in -2
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fIcallback_data\fR argument is always equal to the value passed to \fBumem_cache_create()\fR, thereby allowing a client to use the same callback functions for multiple caches, but with customized behavior.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The reclaim callback is called when the umem function is requesting more memory from the operating system. This callback can be used by clients who retain objects longer than they are strictly needed (for example, caching non-active state). A typical reclaim callback might return to the
|
||||||
|
cache ten per cent of the unneeded buffers.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The constructor and destructor callbacks enable the management of buffers with the constructed state. The constructor takes as arguments a buffer with undefined contents, some callback data, and the flags to use for any allocations. This callback should transform the buffer into the constructed
|
||||||
|
state.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The destructor callback takes as an argument a constructed object and prepares it for return to the general pool of memory. The destructor should undo any state that the constructor created. For debugging, the destructor can also check that the buffer is in the constructed state, to catch
|
||||||
|
incorrectly freed buffers. See
|
||||||
|
\fBumem_debug\fR(3MALLOC) for further information on debugging support.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBumem_cache_destroy()\fR function destroys an object cache. If the cache has any outstanding allocations, the behavior is undefined.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SS Allocating Objects
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBumem_cache_alloc()\fR function takes as arguments:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIcache\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 7n
|
||||||
|
.rt
|
||||||
|
a cache pointer
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIflags\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 7n
|
||||||
|
.rt
|
||||||
|
flags that determine the behavior if \fBumem_cache_alloc()\fR is unable to fulfill the allocation request
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.LP
|
||||||
|
If successful, \fBumem_cache_alloc()\fR returns a pointer to the beginning of an object of \fIbufsize\fR length.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
There are three cases to consider:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
A new buffer needed to be allocated. If the cache was created with a constructor, it is applied to the buffer and the resulting object is returned.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
The object cache was able to use a previously freed buffer. If the cache was created with a constructor, the object is returned unchanged from when it was freed.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
The allocation of a new buffer failed. The \fIflags\fR argument determines the behavior:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBUMEM_DEFAULT\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 14n
|
||||||
|
.rt
|
||||||
|
The \fBumem_cache_alloc()\fR function returns \fINULL\fR if the allocation fails.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBUMEM_NOFAIL\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 14n
|
||||||
|
.rt
|
||||||
|
The \fBumem_cache_alloc()\fR function cannot return \fINULL\fR. A callback is used to determine what action occurs. See
|
||||||
|
\fBumem_alloc\fR(3MALLOC) for more information.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SS Freeing Objects
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBumem_cache_free()\fR function takes as arguments:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIcache\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 7n
|
||||||
|
.rt
|
||||||
|
a cache pointer
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fIbuf\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 7n
|
||||||
|
.rt
|
||||||
|
a pointer previously returned from \fBumem_cache_alloc()\fR. This argument must not be \fINULL\fR.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.LP
|
||||||
|
If the cache was created with a constructor callback, the object must be returned to the constructed state before it is freed.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Undefined behavior results if an object is freed multiple times, if an object is modified after it is freed, or if an object is freed to a cache other than the one from which it was allocated.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SS Caches with Constructors
|
||||||
|
|
||||||
|
.LP
|
||||||
|
When a constructor callback is in use, there is essentially a contract between the cache and its clients. The cache guarantees that all objects returned from \fBumem_cache_alloc()\fR will be in the constructed state, and the client guarantees that it will return the object
|
||||||
|
to the constructed state before handing it to \fBumem_cache_free()\fR.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH RETURN VALUES
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Upon failure, the \fBumem_cache_create()\fR function returns a null pointer.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH ERRORS
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBumem_cache_create()\fR function will fail if:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBEAGAIN\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 8n
|
||||||
|
.rt
|
||||||
|
There is not enough memory available to allocate the cache data structure.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBEINVAL\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 8n
|
||||||
|
.rt
|
||||||
|
The \fIdebug_name\fR argument is \fINULL\fR, the \fIalign\fR argument is not a power of two or is larger than the system pagesize, or the \fIbufsize\fR argument is 0.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBENOMEM\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 8n
|
||||||
|
.rt
|
||||||
|
The \fBlibumem\fR library could not be initialized, or the \fIbufsize\fR argument is too large and its use would cause integer overflow to occur.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH EXAMPLES
|
||||||
|
.LP
|
||||||
|
\fBExample 1 \fRUse a fixed-size structure with no constructor callback.
|
||||||
|
|
||||||
|
.LP
|
||||||
|
.in +2
|
||||||
|
.nf
|
||||||
|
#include <umem.h>
|
||||||
|
|
||||||
|
typedef struct my_obj {
|
||||||
|
long my_data1;
|
||||||
|
} my_obj_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* my_objs can be freed at any time. The contents of
|
||||||
|
* my_data1 is undefined at allocation time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
umem_cache_t *my_obj_cache;
|
||||||
|
|
||||||
|
\&...
|
||||||
|
my_obj_cache = umem_cache_create("my_obj", sizeof (my_obj_t),
|
||||||
|
0, NULL, NULL, NULL, NULL, NULL, 0);
|
||||||
|
\&...
|
||||||
|
my_obj_t *cur = umem_cache_alloc(my_obj_cache, UMEM_DEFAULT);
|
||||||
|
\&...
|
||||||
|
/* use cur */
|
||||||
|
\&...
|
||||||
|
umem_cache_free(my_obj_cache, cur);
|
||||||
|
\&...
|
||||||
|
.fi
|
||||||
|
.in -2
|
||||||
|
.LP
|
||||||
|
\fBExample 2 \fRUse an object with a mutex.
|
||||||
|
|
||||||
|
.LP
|
||||||
|
.in +2
|
||||||
|
.nf
|
||||||
|
#define _REENTRANT
|
||||||
|
#include <synch.h>
|
||||||
|
#include <umem.h>
|
||||||
|
|
||||||
|
typedef struct my_obj {
|
||||||
|
mutex_t my_mutex;
|
||||||
|
long my_data;
|
||||||
|
} my_obj_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* my_objs can only be freed when my_mutex is unlocked.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
my_obj_constructor(void *buf, void *ignored, int flags)
|
||||||
|
{
|
||||||
|
my_obj_t *myobj = buf;
|
||||||
|
|
||||||
|
(void) mutex_init(&my_obj->my_mutex, USYNC_THREAD, NULL);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
my_obj_destructor(void *buf, void *ignored)
|
||||||
|
{
|
||||||
|
my_obj_t *myobj = buf;
|
||||||
|
|
||||||
|
(void) mutex_destroy(&my_obj->my_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
umem_cache_t *my_obj_cache;
|
||||||
|
|
||||||
|
\&...
|
||||||
|
my_obj_cache = umem_cache_create("my_obj", sizeof (my_obj_t),
|
||||||
|
0, my_obj_constructor, my_obj_destructor, NULL, NULL,
|
||||||
|
NULL, 0);
|
||||||
|
\&...
|
||||||
|
my_obj_t *cur = umem_cache_alloc(my_obj_cache, UMEM_DEFAULT);
|
||||||
|
cur->my_data = 0; /* cannot assume anything about my_data */
|
||||||
|
\&...
|
||||||
|
umem_cache_free(my_obj_cache, cur);
|
||||||
|
\&...
|
||||||
|
.fi
|
||||||
|
.in -2
|
||||||
|
.LP
|
||||||
|
\fBExample 3 \fRUse a more complex object with a mutex.
|
||||||
|
|
||||||
|
.LP
|
||||||
|
.in +2
|
||||||
|
.nf
|
||||||
|
#define _REENTRANT
|
||||||
|
#include <assert.h>
|
||||||
|
#include <synch.h>
|
||||||
|
#include <umem.h>
|
||||||
|
|
||||||
|
typedef struct my_obj {
|
||||||
|
mutex_t my_mutex;
|
||||||
|
cond_t my_cv;
|
||||||
|
struct bar *my_barlist;
|
||||||
|
unsigned my_refcount;
|
||||||
|
} my_obj_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* my_objs can only be freed when my_barlist == NULL,
|
||||||
|
* my_refcount == 0, there are no waiters on my_cv, and
|
||||||
|
* my_mutex is unlocked.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
my_obj_constructor(void *buf, void *ignored, int flags)
|
||||||
|
{
|
||||||
|
my_obj_t *myobj = buf;
|
||||||
|
|
||||||
|
(void) mutex_init(&my_obj->my_mutex, USYNC_THREAD, NULL);
|
||||||
|
(void) cond_init(&my_obj->my_cv, USYNC_THREAD, NULL);
|
||||||
|
myobj->my_barlist = NULL;
|
||||||
|
myobj->my_refcount = 0;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
my_obj_destructor(void *buf, void *ignored)
|
||||||
|
{
|
||||||
|
my_obj_t *myobj = buf;
|
||||||
|
|
||||||
|
assert(myobj->my_refcount == 0);
|
||||||
|
assert(myobj->my_barlist == NULL);
|
||||||
|
(void) cond_destroy(&my_obj->my_cv);
|
||||||
|
(void) mutex_destroy(&my_obj->my_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
umem_cache_t *my_obj_cache;
|
||||||
|
|
||||||
|
\&...
|
||||||
|
my_obj_cache = umem_cache_create("my_obj", sizeof (my_obj_t),
|
||||||
|
0, my_obj_constructor, my_obj_destructor, NULL, NULL,
|
||||||
|
NULL, 0);
|
||||||
|
\&...
|
||||||
|
my_obj_t *cur = umem_cache_alloc(my_obj_cache, UMEM_DEFAULT);
|
||||||
|
\&...
|
||||||
|
/* use cur */
|
||||||
|
\&...
|
||||||
|
umem_cache_free(my_obj_cache, cur);
|
||||||
|
\&...
|
||||||
|
.fi
|
||||||
|
.in -2
|
||||||
|
.LP
|
||||||
|
\fBExample 4 \fRUse objects with a subordinate buffer while reusing callbacks.
|
||||||
|
|
||||||
|
.LP
|
||||||
|
.in +2
|
||||||
|
.nf
|
||||||
|
#include assert.h>
|
||||||
|
#include umem.h>
|
||||||
|
|
||||||
|
typedef struct my_obj {
|
||||||
|
char *my_buffer;
|
||||||
|
size_t my_size;
|
||||||
|
} my_obj_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* my_size and the my_buffer pointer should never be changed
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
my_obj_constructor(void *buf, void *arg, int flags)
|
||||||
|
{
|
||||||
|
size_t sz = (size_t)arg;
|
||||||
|
|
||||||
|
my_obj_t *myobj = buf;
|
||||||
|
|
||||||
|
if ((myobj->my_buffer = umem_alloc(sz, flags)) == NULL)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
my_size = sz;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
my_obj_destructor(void *buf, void *arg)
|
||||||
|
{
|
||||||
|
size_t sz = (size_t)arg;
|
||||||
|
|
||||||
|
my_obj_t *myobj = buf;
|
||||||
|
|
||||||
|
assert(sz == buf->my_size);
|
||||||
|
umem_free(myobj->my_buffer, sz);
|
||||||
|
}
|
||||||
|
|
||||||
|
\&...
|
||||||
|
umem_cache_t *my_obj_4k_cache;
|
||||||
|
umem_cache_t *my_obj_8k_cache;
|
||||||
|
\&...
|
||||||
|
my_obj_cache_4k = umem_cache_create("my_obj_4k", sizeof (my_obj_t),
|
||||||
|
0, my_obj_constructor, my_obj_destructor, NULL,
|
||||||
|
(void *)4096, NULL, 0);
|
||||||
|
|
||||||
|
my_obj_cache_8k = umem_cache_create("my_obj_8k", sizeof (my_obj_t),
|
||||||
|
0, my_obj_constructor, my_obj_destructor, NULL,
|
||||||
|
(void *)8192, NULL, 0);
|
||||||
|
\&...
|
||||||
|
my_obj_t *my_obj_4k = umem_cache_alloc(my_obj_4k_cache,
|
||||||
|
UMEM_DEFAULT);
|
||||||
|
my_obj_t *my_obj_8k = umem_cache_alloc(my_obj_8k_cache,
|
||||||
|
UMEM_DEFAULT);
|
||||||
|
/* no assumptions should be made about the contents
|
||||||
|
of the buffers */
|
||||||
|
\&...
|
||||||
|
/* make sure to return them to the correct cache */
|
||||||
|
umem_cache_free(my_obj_4k_cache, my_obj_4k);
|
||||||
|
umem_cache_free(my_obj_8k_cache, my_obj_8k);
|
||||||
|
\&...
|
||||||
|
.fi
|
||||||
|
.in -2
|
||||||
|
|
||||||
|
.LP
|
||||||
|
See the \fBEXAMPLES\fR section of
|
||||||
|
\fBumem_alloc\fR(3MALLOC) for examples involving the \fBUMEM_NOFAIL\fR flag.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH ATTRIBUTES
|
||||||
|
|
||||||
|
.LP
|
||||||
|
See
|
||||||
|
\fBattributes\fR(5) for descriptions of the following attributes:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.TS
|
||||||
|
tab() box;
|
||||||
|
cw(2.75i) |cw(2.75i)
|
||||||
|
lw(2.75i) |lw(2.75i)
|
||||||
|
.
|
||||||
|
ATTRIBUTE TYPEATTRIBUTE VALUE
|
||||||
|
_
|
||||||
|
Interface StabilityEvolving
|
||||||
|
_
|
||||||
|
MT-LevelMT-Safe
|
||||||
|
.TE
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
|
||||||
|
.LP
|
||||||
|
|
||||||
|
\fBsetcontext\fR(2),
|
||||||
|
\fBatexit\fR(3C),
|
||||||
|
\fBlibumem\fR(3LIB),
|
||||||
|
\fBlongjmp\fR(3C),
|
||||||
|
\fBswapcontext\fR(3C),
|
||||||
|
\fBthr_exit\fR(3C),
|
||||||
|
\fBumem_alloc\fR(3MALLOC),
|
||||||
|
\fBumem_debug\fR(3MALLOC),
|
||||||
|
\fBattributes\fR(5)
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Bonwick, Jeff, "The Slab Allocator: An Object-Caching Kernel Memory Allocator", Proceedings of the Summer 1994 Usenix Conference.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Bonwick, Jeff and Jonathan Adams, "Magazines and vmem: Extending the Slab Allocator to Many CPUs and Arbitrary Resources", Proceedings of the Summer 2001 Usenix Conference.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH WARNINGS
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Any of the following can cause undefined results:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Destroying a cache that has outstanding allocated buffers.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Using a cache after it has been destroyed.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Calling \fBumem_cache_free()\fR on the same buffer multiple times.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Passing a \fINULL\fR pointer to \fBumem_cache_free()\fR.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Writing past the end of a buffer.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Reading from or writing to a buffer after it has been freed.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
Performing \fBUMEM_NOFAIL\fR allocations from an
|
||||||
|
\fBatexit\fR(3C) handler.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Per-cache callbacks can be called from a variety of contexts. The use of functions that modify the active context, such as
|
||||||
|
\fBsetcontext\fR(2),
|
||||||
|
\fBswapcontext\fR(3C), and
|
||||||
|
\fBthr_exit\fR(3C),
|
||||||
|
or functions that are unsafe for use in multithreaded applications, such as
|
||||||
|
\fBlongjmp\fR(3C) and
|
||||||
|
\fBsiglongjmp\fR(3C), result in undefined behavior.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
A constructor callback that performs allocations must pass its \fIflags\fR argument unchanged to
|
||||||
|
\fBumem_alloc\fR(3MALLOC) and \fBumem_cache_alloc()\fR. Any allocations made with a different flags argument results in undefined behavior. The constructor must correctly handle the failure of any allocations it makes.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH NOTES
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Object caches make the following guarantees about objects:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
If the cache has a constructor callback, it is applied to every object before it is returned from \fBumem_cache_alloc()\fR for the first time.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
If the cache has a constructor callback, an object passed to \fBumem_cache_free()\fR and later returned from \fBumem_cache_alloc()\fR is not modified between the two events.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.RS +4
|
||||||
|
.TP
|
||||||
|
.ie t \(bu
|
||||||
|
.el o
|
||||||
|
If the cache has a destructor, it is applied to all objects before their underlying storage is returned.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.LP
|
||||||
|
No other guarantees are made. In particular, even if there are buffers recently freed to the cache, \fBumem_cache_alloc()\fR can fail.
|
||||||
|
.sp
|
||||||
|
|
275
1.0.1/umem_debug.3
Normal file
275
1.0.1/umem_debug.3
Normal file
|
@ -0,0 +1,275 @@
|
||||||
|
'\" te
|
||||||
|
.\" CDDL HEADER START
|
||||||
|
.\"
|
||||||
|
.\" The contents of this file are subject to the terms of the
|
||||||
|
.\" Common Development and Distribution License (the "License").
|
||||||
|
.\" You may not use this file except in compliance with the License.
|
||||||
|
.\"
|
||||||
|
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
.\" or http://www.opensolaris.org/os/licensing.
|
||||||
|
.\" See the License for the specific language governing permissions
|
||||||
|
.\" and limitations under the License.
|
||||||
|
.\"
|
||||||
|
.\" When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
.\" If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
.\" fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
.\" information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
.\"
|
||||||
|
.\" CDDL HEADER END
|
||||||
|
.\" Copyright (c) 2002, Sun Microsystems, Inc. All Rights Reserved.
|
||||||
|
.TH umem_debug 3MALLOC "26 July 2002" "SunOS 5.11" "Memory Allocation Library Functions"
|
||||||
|
.SH NAME
|
||||||
|
umem_debug \- debugging features of the umem library
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.LP
|
||||||
|
.nf
|
||||||
|
\fBcc\fR [ \fIflag\fR\&.\|.\|. ] \fIfile\fR\&.\|.\|. \fB-lumem\fR [ \fIlibrary\fR\&.\|.\|. ]
|
||||||
|
#include <\fBumem.h\fR>
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.SH DESCRIPTION
|
||||||
|
|
||||||
|
.LP
|
||||||
|
The \fBlibumem\fR library provides debugging features that detect memory leaks, buffer overruns, multiple frees, use of uninitialized data, use of freed data, and many other common programming errors. The activation of the run-time debugging features is controlled by environment variables.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
When the library detects an error, it writes a description of the error to an internal buffer that is readable with the \fB::umem_status\fR
|
||||||
|
\fBmdb\fR(1) \fIdcmd\fR and then calls
|
||||||
|
\fBabort\fR(3C).
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH ENVIRONMENT VARIABLES
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fBUMEM_DEBUG\fR
|
||||||
|
.ad
|
||||||
|
.RS 14n
|
||||||
|
.rt
|
||||||
|
This variable contains a list of comma-separated options. Unrecognized options are ignored. Possible options include:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBaudit\fR[=\fIframes\fR]\fR
|
||||||
|
.ad
|
||||||
|
.RS 18n
|
||||||
|
.rt
|
||||||
|
This option enables the recording of auditing information, including thread ID, high-resolution time stamp, and stack trace for the last action (allocation or free) on every allocation. If transaction logging
|
||||||
|
(see UMEM_LOGGING) is enabled, this auditing information is also logged.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
The \fIframes\fR parameter sets the number of stack frames recorded in the auditing structure. The upper bound for frames is implementation-defined. If a larger value is requested, the upper bound is used instead.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
If \fIframes\fR is not specified or is not an integer, the default value of 15 is used.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
This option also enables the \fBguards\fR option.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBcontents\fR[=\fIcount\fR]\fR
|
||||||
|
.ad
|
||||||
|
.RS 18n
|
||||||
|
.rt
|
||||||
|
If auditing and contents logging (see UMEM_LOGGING) are enabled, the first \fIcount\fR bytes of each buffer are logged when they are freed. If a buffer is shorter than \fIcount\fR bytes, it is logged in its entirety.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
If \fIcount\fR is not specified or is not an integer, the default value of 256 is used.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBdefault\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 18n
|
||||||
|
.rt
|
||||||
|
This option is equivalent to \fBaudit\fR,\fBcontents\fR,\fBguards\fR.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBguards\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 18n
|
||||||
|
.rt
|
||||||
|
This option enables filling allocated and freed buffers with special patterns to help detect the use of uninitialized data and previously freed buffers. It also enables an 8-byte redzone after each buffer that contains \fB0xfeedfacefeedfaceULL\fR.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
When an object is freed, it is filled with \fB0xdeadbeef\fR. When an object is allocated, the \fB0xdeadbeef\fR pattern is verified and replaced with \fB0xbaddcafe\fR. The redzone is checked every time a buffer is allocated or freed.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
For caches with either constructors or destructors, or both,
|
||||||
|
\fBumem_cache_alloc\fR(3MALLOC) and
|
||||||
|
\fBumem_cache_free\fR(3MALLOC) apply the cache's constructor and destructor, respectively, instead of caching constructed objects. The presence of
|
||||||
|
\fBassert\fR(3C)s
|
||||||
|
in the destructor verifying that the buffer is in the constructed state can be used to detect any objects returned in an improper state. See
|
||||||
|
\fBumem_cache_create\fR(3MALLOC) for
|
||||||
|
details.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBverbose\fR\fR
|
||||||
|
.ad
|
||||||
|
.RS 18n
|
||||||
|
.rt
|
||||||
|
The library writes error descriptions to standard error before aborting. These messages are not localized.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fBUMEM_LOGGING\fR
|
||||||
|
.ad
|
||||||
|
.RS 14n
|
||||||
|
.rt
|
||||||
|
To be enabled, this variable should be set to a comma-separated list of in-memory logs. The logs available are:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBtransaction\fR[=\fIsize\fR]\fR
|
||||||
|
.ad
|
||||||
|
.RS 20n
|
||||||
|
.rt
|
||||||
|
If the \fBaudit\fR debugging option is set (see \fBUMEM_DEBUG\fR), the audit structures from previous transactions are entered into this log.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBcontents\fR[=\fIsize\fR]\fR
|
||||||
|
.ad
|
||||||
|
.RS 20n
|
||||||
|
.rt
|
||||||
|
If the \fBaudit\fR debugging option is set, the contents of objects are recorded in this log as they are freed.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
If the "contents" debugging option was not set, 256 bytes of each freed buffer are saved.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.ne 2
|
||||||
|
.mk
|
||||||
|
.na
|
||||||
|
\fB\fBfail\fR[=\fIsize\fR]\fR
|
||||||
|
.ad
|
||||||
|
.RS 20n
|
||||||
|
.rt
|
||||||
|
Records are entered into this log for every failed allocation.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
For any of these options, if \fIsize\fR is not specified, the default value of 64k is used. The \fIsize\fR parameter must be an integer that can be qualified with K, M, G, or T to specify kilobytes, megabytes, gigabytes, or terabytes, respectively.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
Logs that are not listed or that have either a size of 0 or an invalid size are disabled.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.sp
|
||||||
|
The log is disabled if during initialization the requested amount of storage cannot be allocated.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
.SH ATTRIBUTES
|
||||||
|
|
||||||
|
.LP
|
||||||
|
See
|
||||||
|
\fBattributes\fR(5) for descriptions of the following attributes:
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
|
||||||
|
.sp
|
||||||
|
.TS
|
||||||
|
tab() box;
|
||||||
|
cw(2.75i) |cw(2.75i)
|
||||||
|
lw(2.75i) |lw(2.75i)
|
||||||
|
.
|
||||||
|
ATTRIBUTE TYPEATTRIBUTE VALUE
|
||||||
|
_
|
||||||
|
Interface StabilityUnstable
|
||||||
|
_
|
||||||
|
MT-LevelMT-Safe
|
||||||
|
.TE
|
||||||
|
|
||||||
|
.SH SEE ALSO
|
||||||
|
|
||||||
|
.LP
|
||||||
|
|
||||||
|
\fBmdb\fR(1),
|
||||||
|
\fBabort\fR(3C),
|
||||||
|
\fBsignal\fR(3C),
|
||||||
|
\fBumem_cache_create\fR(3MALLOC),
|
||||||
|
\fBattributes\fR(5)
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH WARNINGS
|
||||||
|
|
||||||
|
.LP
|
||||||
|
When \fBlibumem\fR aborts the process using
|
||||||
|
\fBabort\fR(3C), any existing signal handler for \fBSIGABRT\fR is called. If the signal handler performs allocations, undefined
|
||||||
|
behavior can result.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.SH NOTES
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Some of the debugging features work only for allocations smaller than 16 kilobytes in size. Allocations larger than 16 kilobytes could have reduced support.
|
||||||
|
.sp
|
||||||
|
|
||||||
|
.LP
|
||||||
|
Activating any of the library's debugging features could significantly increase the library's memory footprint and decrease its performance.
|
||||||
|
.sp
|
||||||
|
|
177
1.0.1/umem_fail.c
Normal file
177
1.0.1/umem_fail.c
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)umem_fail.c 1.4 05/06/08 SMI" */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Failure routines for libumem (not standalone)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
static volatile int umem_exiting = 0;
|
||||||
|
#define UMEM_EXIT_ABORT 1
|
||||||
|
|
||||||
|
static mutex_t umem_exit_lock = DEFAULTMUTEX; /* protects umem_exiting */
|
||||||
|
|
||||||
|
static int
|
||||||
|
firstexit(int type)
|
||||||
|
{
|
||||||
|
if (umem_exiting)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
(void) mutex_lock(&umem_exit_lock);
|
||||||
|
if (umem_exiting) {
|
||||||
|
(void) mutex_unlock(&umem_exit_lock);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
umem_exiting = type;
|
||||||
|
(void) mutex_unlock(&umem_exit_lock);
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can't use abort(3C), since it closes all of the standard library
|
||||||
|
* FILEs, which can call free().
|
||||||
|
*
|
||||||
|
* In addition, we can't just raise(SIGABRT), since the current handler
|
||||||
|
* might do allocation. We give them once chance, though.
|
||||||
|
*/
|
||||||
|
static void __NORETURN
|
||||||
|
umem_do_abort(void)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
abort();
|
||||||
|
#else
|
||||||
|
if (firstexit(UMEM_EXIT_ABORT)) {
|
||||||
|
(void) raise(SIGABRT);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
#if defined(__FreeBSD__)
|
||||||
|
sigset_t set;
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
sa.sa_handler = SIG_DFL;
|
||||||
|
(void) sigaction(SIGABRT, &sa, NULL);
|
||||||
|
(void) sigemptyset (&set);
|
||||||
|
(void) sigaddset (&set, SIGABRT);
|
||||||
|
(void) sigprocmask (SIG_UNBLOCK, &set, NULL);
|
||||||
|
(void) raise (SIGABRT);
|
||||||
|
#else
|
||||||
|
(void) signal(SIGABRT, SIG_DFL);
|
||||||
|
(void) sigrelse(SIGABRT);
|
||||||
|
(void) raise(SIGABRT);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SKIP_FRAMES 1 /* skip the panic frame */
|
||||||
|
#define ERR_STACK_FRAMES 128
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_stacktrace(void)
|
||||||
|
{
|
||||||
|
uintptr_t cur_stack[ERR_STACK_FRAMES];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we are in a signal context, checking for it will recurse
|
||||||
|
*/
|
||||||
|
uint_t nframes = getpcstack(cur_stack, ERR_STACK_FRAMES, 0);
|
||||||
|
uint_t idx;
|
||||||
|
|
||||||
|
if (nframes > SKIP_FRAMES) {
|
||||||
|
umem_printf("stack trace:\n");
|
||||||
|
|
||||||
|
for (idx = SKIP_FRAMES; idx < nframes; idx++) {
|
||||||
|
(void) print_sym((void *)cur_stack[idx]);
|
||||||
|
umem_printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
umem_panic(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
umem_vprintf(format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
if (format[strlen(format)-1] != '\n')
|
||||||
|
umem_error_enter("\n");
|
||||||
|
|
||||||
|
#ifdef ECELERITY
|
||||||
|
va_start(va, format);
|
||||||
|
ec_debug_vprintf(DCRITICAL, DMEM, format, va);
|
||||||
|
va_end(va);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
print_stacktrace();
|
||||||
|
|
||||||
|
umem_do_abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
umem_err_recoverable(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
umem_vprintf(format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
if (format[strlen(format)-1] != '\n')
|
||||||
|
umem_error_enter("\n");
|
||||||
|
|
||||||
|
print_stacktrace();
|
||||||
|
|
||||||
|
if (umem_abort > 0)
|
||||||
|
umem_do_abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
__umem_assert_failed(const char *assertion, const char *file, int line)
|
||||||
|
{
|
||||||
|
umem_panic("Assertion failed: %s, file %s, line %d\n",
|
||||||
|
assertion, file, line);
|
||||||
|
umem_do_abort();
|
||||||
|
/*NOTREACHED*/
|
||||||
|
return (0);
|
||||||
|
}
|
214
1.0.1/umem_fork.c
Normal file
214
1.0.1/umem_fork.c
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)umem_fork.c 1.3 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
/* #include "mtlib.h" */
|
||||||
|
#include "umem_base.h"
|
||||||
|
#include "vmem_base.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following functions are for pre- and post-fork1(2) handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
umem_lockup_cache(umem_cache_t *cp)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
int ncpus = cp->cache_cpu_mask + 1;
|
||||||
|
|
||||||
|
for (idx = 0; idx < ncpus; idx++)
|
||||||
|
(void) mutex_lock(&cp->cache_cpu[idx].cc_lock);
|
||||||
|
|
||||||
|
(void) mutex_lock(&cp->cache_depot_lock);
|
||||||
|
(void) mutex_lock(&cp->cache_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
umem_release_cache(umem_cache_t *cp)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
int ncpus = cp->cache_cpu_mask + 1;
|
||||||
|
|
||||||
|
(void) mutex_unlock(&cp->cache_lock);
|
||||||
|
(void) mutex_unlock(&cp->cache_depot_lock);
|
||||||
|
|
||||||
|
for (idx = 0; idx < ncpus; idx++)
|
||||||
|
(void) mutex_unlock(&cp->cache_cpu[idx].cc_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
umem_lockup_log_header(umem_log_header_t *lhp)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
if (lhp == NULL)
|
||||||
|
return;
|
||||||
|
for (idx = 0; idx < umem_max_ncpus; idx++)
|
||||||
|
(void) mutex_lock(&lhp->lh_cpu[idx].clh_lock);
|
||||||
|
|
||||||
|
(void) mutex_lock(&lhp->lh_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
umem_release_log_header(umem_log_header_t *lhp)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
if (lhp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
(void) mutex_unlock(&lhp->lh_lock);
|
||||||
|
|
||||||
|
for (idx = 0; idx < umem_max_ncpus; idx++)
|
||||||
|
(void) mutex_unlock(&lhp->lh_cpu[idx].clh_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
umem_lockup(void)
|
||||||
|
{
|
||||||
|
umem_cache_t *cp;
|
||||||
|
|
||||||
|
(void) mutex_lock(&umem_init_lock);
|
||||||
|
/*
|
||||||
|
* If another thread is busy initializing the library, we must
|
||||||
|
* wait for it to complete (by calling umem_init()) before allowing
|
||||||
|
* the fork() to proceed.
|
||||||
|
*/
|
||||||
|
if (umem_ready == UMEM_READY_INITING && umem_init_thr != thr_self()) {
|
||||||
|
(void) mutex_unlock(&umem_init_lock);
|
||||||
|
(void) umem_init();
|
||||||
|
(void) mutex_lock(&umem_init_lock);
|
||||||
|
}
|
||||||
|
(void) mutex_lock(&umem_cache_lock);
|
||||||
|
(void) mutex_lock(&umem_update_lock);
|
||||||
|
(void) mutex_lock(&umem_flags_lock);
|
||||||
|
|
||||||
|
umem_lockup_cache(&umem_null_cache);
|
||||||
|
for (cp = umem_null_cache.cache_prev; cp != &umem_null_cache;
|
||||||
|
cp = cp->cache_prev)
|
||||||
|
umem_lockup_cache(cp);
|
||||||
|
|
||||||
|
umem_lockup_log_header(umem_transaction_log);
|
||||||
|
umem_lockup_log_header(umem_content_log);
|
||||||
|
umem_lockup_log_header(umem_failure_log);
|
||||||
|
umem_lockup_log_header(umem_slab_log);
|
||||||
|
|
||||||
|
(void) cond_broadcast(&umem_update_cv);
|
||||||
|
|
||||||
|
vmem_sbrk_lockup();
|
||||||
|
vmem_lockup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
umem_release(void)
|
||||||
|
{
|
||||||
|
umem_cache_t *cp;
|
||||||
|
|
||||||
|
vmem_release();
|
||||||
|
vmem_sbrk_release();
|
||||||
|
|
||||||
|
umem_release_log_header(umem_slab_log);
|
||||||
|
umem_release_log_header(umem_failure_log);
|
||||||
|
umem_release_log_header(umem_content_log);
|
||||||
|
umem_release_log_header(umem_transaction_log);
|
||||||
|
|
||||||
|
for (cp = umem_null_cache.cache_next; cp != &umem_null_cache;
|
||||||
|
cp = cp->cache_next)
|
||||||
|
umem_release_cache(cp);
|
||||||
|
umem_release_cache(&umem_null_cache);
|
||||||
|
|
||||||
|
(void) mutex_unlock(&umem_flags_lock);
|
||||||
|
(void) mutex_unlock(&umem_update_lock);
|
||||||
|
(void) mutex_unlock(&umem_cache_lock);
|
||||||
|
(void) mutex_unlock(&umem_init_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
umem_release_child(void)
|
||||||
|
{
|
||||||
|
umem_cache_t *cp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean up the update state
|
||||||
|
*/
|
||||||
|
umem_update_thr = 0;
|
||||||
|
|
||||||
|
if (umem_st_update_thr != thr_self()) {
|
||||||
|
umem_st_update_thr = 0;
|
||||||
|
umem_reaping = UMEM_REAP_DONE;
|
||||||
|
|
||||||
|
for (cp = umem_null_cache.cache_next; cp != &umem_null_cache;
|
||||||
|
cp = cp->cache_next) {
|
||||||
|
if (cp->cache_uflags & UMU_NOTIFY)
|
||||||
|
cp->cache_uflags &= ~UMU_NOTIFY;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the cache is active, we just re-add it to
|
||||||
|
* the update list. This will re-do any active
|
||||||
|
* updates on the cache, but that won't break
|
||||||
|
* anything.
|
||||||
|
*
|
||||||
|
* The worst that can happen is a cache has
|
||||||
|
* its magazines rescaled twice, instead of once.
|
||||||
|
*/
|
||||||
|
if (cp->cache_uflags & UMU_ACTIVE) {
|
||||||
|
umem_cache_t *cnext, *cprev;
|
||||||
|
|
||||||
|
ASSERT(cp->cache_unext == NULL &&
|
||||||
|
cp->cache_uprev == NULL);
|
||||||
|
|
||||||
|
cp->cache_uflags &= ~UMU_ACTIVE;
|
||||||
|
cp->cache_unext = cnext = &umem_null_cache;
|
||||||
|
cp->cache_uprev = cprev =
|
||||||
|
umem_null_cache.cache_uprev;
|
||||||
|
cnext->cache_uprev = cp;
|
||||||
|
cprev->cache_unext = cp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
umem_release();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
umem_forkhandler_init(void)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
/*
|
||||||
|
* There is no way to unregister these atfork functions,
|
||||||
|
* but we don't need to. The dynamic linker and libc take
|
||||||
|
* care of unregistering them if/when the library is unloaded.
|
||||||
|
*/
|
||||||
|
(void) pthread_atfork(umem_lockup, umem_release, umem_release_child);
|
||||||
|
#endif
|
||||||
|
}
|
424
1.0.1/umem_impl.h
Normal file
424
1.0.1/umem_impl.h
Normal file
|
@ -0,0 +1,424 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UMEM_IMPL_H
|
||||||
|
#define _UMEM_IMPL_H
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)umem_impl.h 1.6 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include <umem.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SYSMACROS_H
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_SYS_TIME_H
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/vmem.h>
|
||||||
|
#ifdef HAVE_THREAD_H
|
||||||
|
# include <thread.h>
|
||||||
|
#else
|
||||||
|
# include "sol_compat.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* umem memory allocator: implementation-private data structures
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal flags for umem_cache_create
|
||||||
|
*/
|
||||||
|
#define UMC_QCACHE 0x00100000
|
||||||
|
#define UMC_INTERNAL 0x80000000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cache flags
|
||||||
|
*/
|
||||||
|
#define UMF_AUDIT 0x00000001 /* transaction auditing */
|
||||||
|
#define UMF_DEADBEEF 0x00000002 /* deadbeef checking */
|
||||||
|
#define UMF_REDZONE 0x00000004 /* redzone checking */
|
||||||
|
#define UMF_CONTENTS 0x00000008 /* freed-buffer content logging */
|
||||||
|
#define UMF_CHECKSIGNAL 0x00000010 /* abort when in signal context */
|
||||||
|
#define UMF_NOMAGAZINE 0x00000020 /* disable per-cpu magazines */
|
||||||
|
#define UMF_FIREWALL 0x00000040 /* put all bufs before unmapped pages */
|
||||||
|
#define UMF_LITE 0x00000100 /* lightweight debugging */
|
||||||
|
|
||||||
|
#define UMF_HASH 0x00000200 /* cache has hash table */
|
||||||
|
#define UMF_RANDOMIZE 0x00000400 /* randomize other umem_flags */
|
||||||
|
|
||||||
|
#define UMF_BUFTAG (UMF_DEADBEEF | UMF_REDZONE)
|
||||||
|
#define UMF_TOUCH (UMF_BUFTAG | UMF_LITE | UMF_CONTENTS)
|
||||||
|
#define UMF_RANDOM (UMF_TOUCH | UMF_AUDIT | UMF_NOMAGAZINE)
|
||||||
|
#define UMF_DEBUG (UMF_RANDOM | UMF_FIREWALL)
|
||||||
|
|
||||||
|
#define UMEM_STACK_DEPTH umem_stack_depth
|
||||||
|
|
||||||
|
#define UMEM_FREE_PATTERN 0xdeadbeefdeadbeefULL
|
||||||
|
#define UMEM_UNINITIALIZED_PATTERN 0xbaddcafebaddcafeULL
|
||||||
|
#define UMEM_REDZONE_PATTERN 0xfeedfacefeedfaceULL
|
||||||
|
#define UMEM_REDZONE_BYTE 0xbb
|
||||||
|
|
||||||
|
#define UMEM_FATAL_FLAGS (UMEM_NOFAIL)
|
||||||
|
#define UMEM_SLEEP_FLAGS (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Redzone size encodings for umem_alloc() / umem_free(). We encode the
|
||||||
|
* allocation size, rather than storing it directly, so that umem_free()
|
||||||
|
* can distinguish frees of the wrong size from redzone violations.
|
||||||
|
*/
|
||||||
|
#define UMEM_SIZE_ENCODE(x) (251 * (x) + 1)
|
||||||
|
#define UMEM_SIZE_DECODE(x) ((x) / 251)
|
||||||
|
#define UMEM_SIZE_VALID(x) ((x) % 251 == 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The bufctl (buffer control) structure keeps some minimal information
|
||||||
|
* about each buffer: its address, its slab, and its current linkage,
|
||||||
|
* which is either on the slab's freelist (if the buffer is free), or
|
||||||
|
* on the cache's buf-to-bufctl hash table (if the buffer is allocated).
|
||||||
|
* In the case of non-hashed, or "raw", caches (the common case), only
|
||||||
|
* the freelist linkage is necessary: the buffer address is at a fixed
|
||||||
|
* offset from the bufctl address, and the slab is at the end of the page.
|
||||||
|
*
|
||||||
|
* NOTE: bc_next must be the first field; raw buffers have linkage only.
|
||||||
|
*/
|
||||||
|
typedef struct umem_bufctl {
|
||||||
|
struct umem_bufctl *bc_next; /* next bufctl struct */
|
||||||
|
void *bc_addr; /* address of buffer */
|
||||||
|
struct umem_slab *bc_slab; /* controlling slab */
|
||||||
|
} umem_bufctl_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The UMF_AUDIT version of the bufctl structure. The beginning of this
|
||||||
|
* structure must be identical to the normal bufctl structure so that
|
||||||
|
* pointers are interchangeable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define UMEM_BUFCTL_AUDIT_SIZE_DEPTH(frames) \
|
||||||
|
((size_t)(&((umem_bufctl_audit_t *)0)->bc_stack[frames]))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* umem_bufctl_audits must be allocated from a UMC_NOHASH cache, so we
|
||||||
|
* require that 2 of them, plus 2 buftags, plus a umem_slab_t, all fit on
|
||||||
|
* a single page.
|
||||||
|
*
|
||||||
|
* For ILP32, this is about 1000 frames.
|
||||||
|
* For LP64, this is about 490 frames.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define UMEM_BUFCTL_AUDIT_ALIGN 32
|
||||||
|
|
||||||
|
#define UMEM_BUFCTL_AUDIT_MAX_SIZE \
|
||||||
|
(P2ALIGN((PAGESIZE - sizeof (umem_slab_t))/2 - \
|
||||||
|
sizeof (umem_buftag_t), UMEM_BUFCTL_AUDIT_ALIGN))
|
||||||
|
|
||||||
|
#define UMEM_MAX_STACK_DEPTH \
|
||||||
|
((UMEM_BUFCTL_AUDIT_MAX_SIZE - \
|
||||||
|
UMEM_BUFCTL_AUDIT_SIZE_DEPTH(0)) / sizeof (uintptr_t))
|
||||||
|
|
||||||
|
typedef struct umem_bufctl_audit {
|
||||||
|
struct umem_bufctl *bc_next; /* next bufctl struct */
|
||||||
|
void *bc_addr; /* address of buffer */
|
||||||
|
struct umem_slab *bc_slab; /* controlling slab */
|
||||||
|
umem_cache_t *bc_cache; /* controlling cache */
|
||||||
|
hrtime_t bc_timestamp; /* transaction time */
|
||||||
|
thread_t bc_thread; /* thread doing transaction */
|
||||||
|
struct umem_bufctl *bc_lastlog; /* last log entry */
|
||||||
|
void *bc_contents; /* contents at last free */
|
||||||
|
int bc_depth; /* stack depth */
|
||||||
|
uintptr_t bc_stack[1]; /* pc stack */
|
||||||
|
} umem_bufctl_audit_t;
|
||||||
|
|
||||||
|
#define UMEM_LOCAL_BUFCTL_AUDIT(bcpp) \
|
||||||
|
*(bcpp) = (umem_bufctl_audit_t *) \
|
||||||
|
alloca(UMEM_BUFCTL_AUDIT_SIZE)
|
||||||
|
|
||||||
|
#define UMEM_BUFCTL_AUDIT_SIZE \
|
||||||
|
UMEM_BUFCTL_AUDIT_SIZE_DEPTH(UMEM_STACK_DEPTH)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A umem_buftag structure is appended to each buffer whenever any of the
|
||||||
|
* UMF_BUFTAG flags (UMF_DEADBEEF, UMF_REDZONE, UMF_VERIFY) are set.
|
||||||
|
*/
|
||||||
|
typedef struct umem_buftag {
|
||||||
|
uint64_t bt_redzone; /* 64-bit redzone pattern */
|
||||||
|
umem_bufctl_t *bt_bufctl; /* bufctl */
|
||||||
|
intptr_t bt_bxstat; /* bufctl ^ (alloc/free) */
|
||||||
|
} umem_buftag_t;
|
||||||
|
|
||||||
|
#define UMEM_BUFTAG(cp, buf) \
|
||||||
|
((umem_buftag_t *)((char *)(buf) + (cp)->cache_buftag))
|
||||||
|
|
||||||
|
#define UMEM_BUFCTL(cp, buf) \
|
||||||
|
((umem_bufctl_t *)((char *)(buf) + (cp)->cache_bufctl))
|
||||||
|
|
||||||
|
#define UMEM_BUF(cp, bcp) \
|
||||||
|
((void *)((char *)(bcp) - (cp)->cache_bufctl))
|
||||||
|
|
||||||
|
#define UMEM_SLAB(cp, buf) \
|
||||||
|
((umem_slab_t *)P2END((uintptr_t)(buf), (cp)->cache_slabsize) - 1)
|
||||||
|
|
||||||
|
#define UMEM_CPU_CACHE(cp, cpu) \
|
||||||
|
(umem_cpu_cache_t *)((char *)cp + cpu->cpu_cache_offset)
|
||||||
|
|
||||||
|
#define UMEM_MAGAZINE_VALID(cp, mp) \
|
||||||
|
(((umem_slab_t *)P2END((uintptr_t)(mp), PAGESIZE) - 1)->slab_cache == \
|
||||||
|
(cp)->cache_magtype->mt_cache)
|
||||||
|
|
||||||
|
#define UMEM_SLAB_MEMBER(sp, buf) \
|
||||||
|
((size_t)(buf) - (size_t)(sp)->slab_base < \
|
||||||
|
(sp)->slab_cache->cache_slabsize)
|
||||||
|
|
||||||
|
#define UMEM_BUFTAG_ALLOC 0xa110c8edUL
|
||||||
|
#define UMEM_BUFTAG_FREE 0xf4eef4eeUL
|
||||||
|
|
||||||
|
typedef struct umem_slab {
|
||||||
|
struct umem_cache *slab_cache; /* controlling cache */
|
||||||
|
void *slab_base; /* base of allocated memory */
|
||||||
|
struct umem_slab *slab_next; /* next slab on freelist */
|
||||||
|
struct umem_slab *slab_prev; /* prev slab on freelist */
|
||||||
|
struct umem_bufctl *slab_head; /* first free buffer */
|
||||||
|
long slab_refcnt; /* outstanding allocations */
|
||||||
|
long slab_chunks; /* chunks (bufs) in this slab */
|
||||||
|
} umem_slab_t;
|
||||||
|
|
||||||
|
#define UMEM_HASH_INITIAL 64
|
||||||
|
|
||||||
|
#define UMEM_HASH(cp, buf) \
|
||||||
|
((cp)->cache_hash_table + \
|
||||||
|
(((uintptr_t)(buf) >> (cp)->cache_hash_shift) & (cp)->cache_hash_mask))
|
||||||
|
|
||||||
|
typedef struct umem_magazine {
|
||||||
|
void *mag_next;
|
||||||
|
void *mag_round[1]; /* one or more rounds */
|
||||||
|
} umem_magazine_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The magazine types for fast per-cpu allocation
|
||||||
|
*/
|
||||||
|
typedef struct umem_magtype {
|
||||||
|
int mt_magsize; /* magazine size (number of rounds) */
|
||||||
|
int mt_align; /* magazine alignment */
|
||||||
|
size_t mt_minbuf; /* all smaller buffers qualify */
|
||||||
|
size_t mt_maxbuf; /* no larger buffers qualify */
|
||||||
|
umem_cache_t *mt_cache; /* magazine cache */
|
||||||
|
} umem_magtype_t;
|
||||||
|
|
||||||
|
#if (defined(__PTHREAD_MUTEX_SIZE__) && __PTHREAD_MUTEX_SIZE__ >= 24) || defined(UMEM_PTHREAD_MUTEX_TOO_BIG)
|
||||||
|
#define UMEM_CPU_CACHE_SIZE 128 /* must be power of 2 */
|
||||||
|
#else
|
||||||
|
#define UMEM_CPU_CACHE_SIZE 64 /* must be power of 2 */
|
||||||
|
#endif
|
||||||
|
#define UMEM_CPU_PAD (UMEM_CPU_CACHE_SIZE - sizeof (mutex_t) - \
|
||||||
|
2 * sizeof (uint_t) - 2 * sizeof (void *) - 4 * sizeof (int))
|
||||||
|
#define UMEM_CACHE_SIZE(ncpus) \
|
||||||
|
((size_t)(&((umem_cache_t *)0)->cache_cpu[ncpus]))
|
||||||
|
|
||||||
|
typedef struct umem_cpu_cache {
|
||||||
|
mutex_t cc_lock; /* protects this cpu's local cache */
|
||||||
|
uint_t cc_alloc; /* allocations from this cpu */
|
||||||
|
uint_t cc_free; /* frees to this cpu */
|
||||||
|
umem_magazine_t *cc_loaded; /* the currently loaded magazine */
|
||||||
|
umem_magazine_t *cc_ploaded; /* the previously loaded magazine */
|
||||||
|
int cc_rounds; /* number of objects in loaded mag */
|
||||||
|
int cc_prounds; /* number of objects in previous mag */
|
||||||
|
int cc_magsize; /* number of rounds in a full mag */
|
||||||
|
int cc_flags; /* CPU-local copy of cache_flags */
|
||||||
|
#if (!defined(_LP64) || defined(UMEM_PTHREAD_MUTEX_TOO_BIG)) && !defined(_WIN32)
|
||||||
|
/* on win32, UMEM_CPU_PAD evaluates to zero, and the MS compiler
|
||||||
|
* won't allow static initialization of arrays containing structures
|
||||||
|
* that contain zero size arrays */
|
||||||
|
char cc_pad[UMEM_CPU_PAD]; /* for nice alignment (32-bit) */
|
||||||
|
#endif
|
||||||
|
} umem_cpu_cache_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The magazine lists used in the depot.
|
||||||
|
*/
|
||||||
|
typedef struct umem_maglist {
|
||||||
|
umem_magazine_t *ml_list; /* magazine list */
|
||||||
|
long ml_total; /* number of magazines */
|
||||||
|
long ml_min; /* min since last update */
|
||||||
|
long ml_reaplimit; /* max reapable magazines */
|
||||||
|
uint64_t ml_alloc; /* allocations from this list */
|
||||||
|
} umem_maglist_t;
|
||||||
|
|
||||||
|
#define UMEM_CACHE_NAMELEN 31
|
||||||
|
|
||||||
|
struct umem_cache {
|
||||||
|
/*
|
||||||
|
* Statistics
|
||||||
|
*/
|
||||||
|
uint64_t cache_slab_create; /* slab creates */
|
||||||
|
uint64_t cache_slab_destroy; /* slab destroys */
|
||||||
|
uint64_t cache_slab_alloc; /* slab layer allocations */
|
||||||
|
uint64_t cache_slab_free; /* slab layer frees */
|
||||||
|
uint64_t cache_alloc_fail; /* total failed allocations */
|
||||||
|
uint64_t cache_buftotal; /* total buffers */
|
||||||
|
uint64_t cache_bufmax; /* max buffers ever */
|
||||||
|
uint64_t cache_rescale; /* # of hash table rescales */
|
||||||
|
uint64_t cache_lookup_depth; /* hash lookup depth */
|
||||||
|
uint64_t cache_depot_contention; /* mutex contention count */
|
||||||
|
uint64_t cache_depot_contention_prev; /* previous snapshot */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cache properties
|
||||||
|
*/
|
||||||
|
char cache_name[UMEM_CACHE_NAMELEN + 1];
|
||||||
|
size_t cache_bufsize; /* object size */
|
||||||
|
size_t cache_align; /* object alignment */
|
||||||
|
umem_constructor_t *cache_constructor;
|
||||||
|
umem_destructor_t *cache_destructor;
|
||||||
|
umem_reclaim_t *cache_reclaim;
|
||||||
|
void *cache_private; /* opaque arg to callbacks */
|
||||||
|
vmem_t *cache_arena; /* vmem source for slabs */
|
||||||
|
int cache_cflags; /* cache creation flags */
|
||||||
|
int cache_flags; /* various cache state info */
|
||||||
|
int cache_uflags; /* UMU_* flags */
|
||||||
|
uint32_t cache_mtbf; /* induced alloc failure rate */
|
||||||
|
umem_cache_t *cache_next; /* forward cache linkage */
|
||||||
|
umem_cache_t *cache_prev; /* backward cache linkage */
|
||||||
|
umem_cache_t *cache_unext; /* next in update list */
|
||||||
|
umem_cache_t *cache_uprev; /* prev in update list */
|
||||||
|
uint32_t cache_cpu_mask; /* mask for cpu offset */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slab layer
|
||||||
|
*/
|
||||||
|
mutex_t cache_lock; /* protects slab layer */
|
||||||
|
size_t cache_chunksize; /* buf + alignment [+ debug] */
|
||||||
|
size_t cache_slabsize; /* size of a slab */
|
||||||
|
size_t cache_bufctl; /* buf-to-bufctl distance */
|
||||||
|
size_t cache_buftag; /* buf-to-buftag distance */
|
||||||
|
size_t cache_verify; /* bytes to verify */
|
||||||
|
size_t cache_contents; /* bytes of saved content */
|
||||||
|
size_t cache_color; /* next slab color */
|
||||||
|
size_t cache_mincolor; /* maximum slab color */
|
||||||
|
size_t cache_maxcolor; /* maximum slab color */
|
||||||
|
size_t cache_hash_shift; /* get to interesting bits */
|
||||||
|
size_t cache_hash_mask; /* hash table mask */
|
||||||
|
umem_slab_t *cache_freelist; /* slab free list */
|
||||||
|
umem_slab_t cache_nullslab; /* end of freelist marker */
|
||||||
|
umem_cache_t *cache_bufctl_cache; /* source of bufctls */
|
||||||
|
umem_bufctl_t **cache_hash_table; /* hash table base */
|
||||||
|
/*
|
||||||
|
* Depot layer
|
||||||
|
*/
|
||||||
|
mutex_t cache_depot_lock; /* protects depot */
|
||||||
|
umem_magtype_t *cache_magtype; /* magazine type */
|
||||||
|
umem_maglist_t cache_full; /* full magazines */
|
||||||
|
umem_maglist_t cache_empty; /* empty magazines */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Per-CPU layer
|
||||||
|
*/
|
||||||
|
umem_cpu_cache_t cache_cpu[1]; /* cache_cpu_mask + 1 entries */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct umem_cpu_log_header {
|
||||||
|
mutex_t clh_lock;
|
||||||
|
char *clh_current;
|
||||||
|
size_t clh_avail;
|
||||||
|
int clh_chunk;
|
||||||
|
int clh_hits;
|
||||||
|
char clh_pad[UMEM_CPU_CACHE_SIZE -
|
||||||
|
sizeof (mutex_t) - sizeof (char *) -
|
||||||
|
sizeof (size_t) - 2 * sizeof (int)];
|
||||||
|
} umem_cpu_log_header_t;
|
||||||
|
|
||||||
|
typedef struct umem_log_header {
|
||||||
|
mutex_t lh_lock;
|
||||||
|
char *lh_base;
|
||||||
|
int *lh_free;
|
||||||
|
size_t lh_chunksize;
|
||||||
|
int lh_nchunks;
|
||||||
|
int lh_head;
|
||||||
|
int lh_tail;
|
||||||
|
int lh_hits;
|
||||||
|
umem_cpu_log_header_t lh_cpu[1]; /* actually umem_max_ncpus */
|
||||||
|
} umem_log_header_t;
|
||||||
|
|
||||||
|
typedef struct umem_cpu {
|
||||||
|
uint32_t cpu_cache_offset;
|
||||||
|
uint32_t cpu_number;
|
||||||
|
} umem_cpu_t;
|
||||||
|
|
||||||
|
#define UMEM_MAXBUF 16384
|
||||||
|
|
||||||
|
#define UMEM_ALIGN 8 /* min guaranteed alignment */
|
||||||
|
#define UMEM_ALIGN_SHIFT 3 /* log2(UMEM_ALIGN) */
|
||||||
|
#define UMEM_VOID_FRACTION 8 /* never waste more than 1/8 of slab */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For 64 bits, buffers >= 16 bytes must be 16-byte aligned
|
||||||
|
*/
|
||||||
|
#ifdef _LP64
|
||||||
|
#define UMEM_SECOND_ALIGN 16
|
||||||
|
#else
|
||||||
|
#define UMEM_SECOND_ALIGN UMEM_ALIGN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MALLOC_MAGIC 0x3a10c000 /* 8-byte tag */
|
||||||
|
#define MEMALIGN_MAGIC 0x3e3a1000
|
||||||
|
|
||||||
|
#ifdef _LP64
|
||||||
|
#define MALLOC_SECOND_MAGIC 0x16ba7000 /* 8-byte tag, 16-aligned */
|
||||||
|
#define MALLOC_OVERSIZE_MAGIC 0x06e47000 /* 16-byte tag, _LP64 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define UMEM_MALLOC_ENCODE(type, sz) (uint32_t)((type) - (sz))
|
||||||
|
#define UMEM_MALLOC_DECODE(stat, sz) (uint32_t)((stat) + (sz))
|
||||||
|
#define UMEM_FREE_PATTERN_32 (uint32_t)(UMEM_FREE_PATTERN)
|
||||||
|
|
||||||
|
#define UMU_MAGAZINE_RESIZE 0x00000001
|
||||||
|
#define UMU_HASH_RESCALE 0x00000002
|
||||||
|
#define UMU_REAP 0x00000004
|
||||||
|
#define UMU_NOTIFY 0x08000000
|
||||||
|
#define UMU_ACTIVE 0x80000000
|
||||||
|
|
||||||
|
#define UMEM_READY_INIT_FAILED -1
|
||||||
|
#define UMEM_READY_STARTUP 1
|
||||||
|
#define UMEM_READY_INITING 2
|
||||||
|
#define UMEM_READY 3
|
||||||
|
|
||||||
|
#ifdef UMEM_STANDALONE
|
||||||
|
extern void umem_startup(caddr_t, size_t, size_t, caddr_t, caddr_t);
|
||||||
|
extern int umem_add(caddr_t, size_t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _UMEM_IMPL_H */
|
23
1.0.1/umem_test.c
Normal file
23
1.0.1/umem_test.c
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "umem.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *foo;
|
||||||
|
|
||||||
|
umem_startup(NULL, 0, 0, NULL, NULL);
|
||||||
|
|
||||||
|
foo = umem_alloc(32, UMEM_DEFAULT);
|
||||||
|
|
||||||
|
strcpy(foo, "hello there");
|
||||||
|
|
||||||
|
printf("Hello %s\n", foo);
|
||||||
|
|
||||||
|
umem_free(foo, 32);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
62
1.0.1/umem_test2.c
Normal file
62
1.0.1/umem_test2.c
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "umem.h"
|
||||||
|
|
||||||
|
static const char *TESTSTRINGS[] = {
|
||||||
|
"fred",
|
||||||
|
"fredfredfred",
|
||||||
|
"thisisabitlongerthantheotherstrings",
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890",
|
||||||
|
};
|
||||||
|
|
||||||
|
#define N_TESTSTRINGS (sizeof(TESTSTRINGS) / sizeof(TESTSTRINGS[0]))
|
||||||
|
#define N_TESTS 1000
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
char *testcases[N_TESTSTRINGS][N_TESTS + 1];
|
||||||
|
size_t len[N_TESTSTRINGS];
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
memset(testcases, 0, sizeof(testcases));
|
||||||
|
|
||||||
|
umem_startup(NULL, 0, 0, NULL, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < N_TESTSTRINGS; ++i)
|
||||||
|
{
|
||||||
|
len[i] = strlen(TESTSTRINGS[i]) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("Allocating...");
|
||||||
|
|
||||||
|
for (j = 0; j < N_TESTS; ++j)
|
||||||
|
{
|
||||||
|
for (i = 0; i < N_TESTSTRINGS; ++i)
|
||||||
|
{
|
||||||
|
testcases[i][j] = umem_alloc(len[i], UMEM_DEFAULT);
|
||||||
|
strcpy(testcases[i][j], TESTSTRINGS[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("Deallocating...");
|
||||||
|
|
||||||
|
for (j = 0; j < N_TESTS; ++j)
|
||||||
|
{
|
||||||
|
for (i = N_TESTSTRINGS - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
umem_free(testcases[i][j], len[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((j % 25) == 0)
|
||||||
|
{
|
||||||
|
puts("Reaping...");
|
||||||
|
umem_reap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
puts("Done");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
35
1.0.1/umem_test3.c
Normal file
35
1.0.1/umem_test3.c
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#include "config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
|
||||||
|
#include <malloc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void minfo(void)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
|
||||||
|
struct mallinfo mi;
|
||||||
|
mi = mallinfo();
|
||||||
|
printf(" fordblks = %d\n", mi.fordblks);
|
||||||
|
malloc_stats();
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
minfo();
|
||||||
|
p = malloc(10);
|
||||||
|
free(p);
|
||||||
|
minfo();
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* vim:ts=2:sw=2:et:
|
||||||
|
*/
|
23
1.0.1/umem_test4
Executable file
23
1.0.1/umem_test4
Executable file
|
@ -0,0 +1,23 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# Check that LD_PRELOAD'ing libumem works. This is how it can be used
|
||||||
|
# to replace malloc for any program.
|
||||||
|
#
|
||||||
|
|
||||||
|
FILE=Makefile.am
|
||||||
|
TMPLOC=`mktemp -d /tmp/umem_test4.XXXXXX`
|
||||||
|
trap 'rm -rf $TMPLOC' 1 2 15
|
||||||
|
|
||||||
|
LD_PRELOAD=.libs/libumem.so /usr/bin/ldd /bin/ls >$TMPLOC/log 2>&1
|
||||||
|
|
||||||
|
# Check we got the expected result
|
||||||
|
ret=0
|
||||||
|
grep -E '(symbol lookup error|undefined symbol)' $TMPLOC/log >/dev/null 2>&1
|
||||||
|
if [ "$?" = "0" ]; then
|
||||||
|
# Matched = failed to load up libumem
|
||||||
|
ret=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf $TMPLOC
|
||||||
|
|
||||||
|
exit $ret
|
153
1.0.1/umem_update_thread.c
Normal file
153
1.0.1/umem_update_thread.c
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)umem_update_thread.c 1.2 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "umem_base.h"
|
||||||
|
#include "vmem_base.h"
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we use the _ version, since we don't want to be cancelled.
|
||||||
|
*/
|
||||||
|
extern int _cond_timedwait(cond_t *cv, mutex_t *mutex, const timespec_t *delay);
|
||||||
|
|
||||||
|
/*ARGSUSED*/
|
||||||
|
static THR_RETURN
|
||||||
|
THR_API umem_update_thread(void *arg)
|
||||||
|
{
|
||||||
|
struct timeval now;
|
||||||
|
int in_update = 0;
|
||||||
|
|
||||||
|
(void) mutex_lock(&umem_update_lock);
|
||||||
|
|
||||||
|
ASSERT(umem_update_thr == thr_self());
|
||||||
|
ASSERT(umem_st_update_thr == 0);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
umem_process_updates();
|
||||||
|
|
||||||
|
if (in_update) {
|
||||||
|
in_update = 0;
|
||||||
|
/*
|
||||||
|
* we wait until now to set the next update time
|
||||||
|
* so that the updates are self-throttling
|
||||||
|
*/
|
||||||
|
(void) gettimeofday(&umem_update_next, NULL);
|
||||||
|
umem_update_next.tv_sec += umem_reap_interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (umem_reaping) {
|
||||||
|
case UMEM_REAP_DONE:
|
||||||
|
case UMEM_REAP_ADDING:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UMEM_REAP_ACTIVE:
|
||||||
|
umem_reap_next = gethrtime() +
|
||||||
|
(hrtime_t)umem_reap_interval * NANOSEC;
|
||||||
|
umem_reaping = UMEM_REAP_DONE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ASSERT(umem_reaping == UMEM_REAP_DONE ||
|
||||||
|
umem_reaping == UMEM_REAP_ADDING ||
|
||||||
|
umem_reaping == UMEM_REAP_ACTIVE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void) gettimeofday(&now, NULL);
|
||||||
|
if (now.tv_sec > umem_update_next.tv_sec ||
|
||||||
|
(now.tv_sec == umem_update_next.tv_sec &&
|
||||||
|
now.tv_usec >= umem_update_next.tv_usec)) {
|
||||||
|
/*
|
||||||
|
* Time to run an update
|
||||||
|
*/
|
||||||
|
(void) mutex_unlock(&umem_update_lock);
|
||||||
|
|
||||||
|
vmem_update(NULL);
|
||||||
|
/*
|
||||||
|
* umem_cache_update can use umem_add_update to
|
||||||
|
* request further work. The update is not complete
|
||||||
|
* until all such work is finished.
|
||||||
|
*/
|
||||||
|
umem_cache_applyall(umem_cache_update);
|
||||||
|
|
||||||
|
(void) mutex_lock(&umem_update_lock);
|
||||||
|
in_update = 1;
|
||||||
|
continue; /* start processing immediately */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if there is no work to do, we wait until it is time for
|
||||||
|
* next update, or someone wakes us.
|
||||||
|
*/
|
||||||
|
if (umem_null_cache.cache_unext == &umem_null_cache) {
|
||||||
|
timespec_t abs_time;
|
||||||
|
abs_time.tv_sec = umem_update_next.tv_sec;
|
||||||
|
abs_time.tv_nsec = umem_update_next.tv_usec * 1000;
|
||||||
|
|
||||||
|
(void) _cond_timedwait(&umem_update_cv,
|
||||||
|
&umem_update_lock, &abs_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* LINTED no return statement */
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
umem_create_update_thread(void)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
sigset_t sigmask, oldmask;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ASSERT(MUTEX_HELD(&umem_update_lock));
|
||||||
|
ASSERT(umem_update_thr == 0);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
/*
|
||||||
|
* The update thread handles no signals
|
||||||
|
*/
|
||||||
|
(void) sigfillset(&sigmask);
|
||||||
|
(void) thr_sigsetmask(SIG_BLOCK, &sigmask, &oldmask);
|
||||||
|
#endif
|
||||||
|
if (thr_create(NULL, 0, umem_update_thread, NULL,
|
||||||
|
THR_BOUND | THR_DAEMON | THR_DETACHED, &umem_update_thr) == 0) {
|
||||||
|
#ifndef _WIN32
|
||||||
|
(void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
|
||||||
|
#endif
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
umem_update_thr = 0;
|
||||||
|
#ifndef _WIN32
|
||||||
|
(void) thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
|
||||||
|
#endif
|
||||||
|
return (0);
|
||||||
|
}
|
1807
1.0.1/vmem.c
Normal file
1807
1.0.1/vmem.c
Normal file
File diff suppressed because it is too large
Load diff
58
1.0.1/vmem_base.c
Normal file
58
1.0.1/vmem_base.c
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)vmem_base.c 1.6 05/06/08 SMI" */
|
||||||
|
|
||||||
|
/* #include "mtlib.h" */
|
||||||
|
#include "config.h"
|
||||||
|
#include "vmem_base.h"
|
||||||
|
#include "umem_base.h"
|
||||||
|
|
||||||
|
uint_t vmem_backend = 0;
|
||||||
|
|
||||||
|
vmem_t *
|
||||||
|
vmem_heap_arena(vmem_alloc_t **allocp, vmem_free_t **freep)
|
||||||
|
{
|
||||||
|
static mutex_t arena_mutex = DEFAULTMUTEX;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow the init thread through, block others until the init completes
|
||||||
|
*/
|
||||||
|
if (umem_ready != UMEM_READY && umem_init_thr != thr_self() &&
|
||||||
|
umem_init() == 0)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
(void) mutex_lock(&arena_mutex);
|
||||||
|
if (vmem_heap == NULL)
|
||||||
|
vmem_heap_init();
|
||||||
|
(void) mutex_unlock(&arena_mutex);
|
||||||
|
|
||||||
|
if (allocp != NULL)
|
||||||
|
*allocp = vmem_heap_alloc;
|
||||||
|
if (freep != NULL)
|
||||||
|
*freep = vmem_heap_free;
|
||||||
|
return (vmem_heap);
|
||||||
|
}
|
85
1.0.1/vmem_base.h
Normal file
85
1.0.1/vmem_base.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _VMEM_BASE_H
|
||||||
|
#define _VMEM_BASE_H
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)vmem_base.h 1.3 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include <sys/vmem.h>
|
||||||
|
#include <umem.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
extern void vmem_startup(void);
|
||||||
|
extern vmem_t *vmem_init(const char *parent_name, size_t parent_quantum,
|
||||||
|
vmem_alloc_t *parent_alloc, vmem_free_t *parent_free,
|
||||||
|
const char *heap_name,
|
||||||
|
void *heap_start, size_t heap_size, size_t heap_quantum,
|
||||||
|
vmem_alloc_t *heap_alloc, vmem_free_t *heap_free);
|
||||||
|
|
||||||
|
extern void *_vmem_extend_alloc(vmem_t *vmp, void *vaddr, size_t size,
|
||||||
|
size_t alloc, int vmflag);
|
||||||
|
|
||||||
|
extern vmem_t *vmem_heap_arena(vmem_alloc_t **, vmem_free_t **);
|
||||||
|
extern void vmem_heap_init(void);
|
||||||
|
|
||||||
|
extern vmem_t *vmem_sbrk_arena(vmem_alloc_t **, vmem_free_t **);
|
||||||
|
extern vmem_t *vmem_mmap_arena(vmem_alloc_t **, vmem_free_t **);
|
||||||
|
extern vmem_t *vmem_stand_arena(vmem_alloc_t **, vmem_free_t **);
|
||||||
|
|
||||||
|
extern void vmem_update(void *);
|
||||||
|
extern void vmem_reap(void); /* vmem_populate()-safe reap */
|
||||||
|
|
||||||
|
extern size_t pagesize;
|
||||||
|
extern size_t vmem_sbrk_pagesize;
|
||||||
|
|
||||||
|
extern uint_t vmem_backend;
|
||||||
|
#define VMEM_BACKEND_SBRK 0x0000001
|
||||||
|
#define VMEM_BACKEND_MMAP 0x0000002
|
||||||
|
#define VMEM_BACKEND_STAND 0x0000003
|
||||||
|
|
||||||
|
extern vmem_t *vmem_heap;
|
||||||
|
extern vmem_alloc_t *vmem_heap_alloc;
|
||||||
|
extern vmem_free_t *vmem_heap_free;
|
||||||
|
|
||||||
|
extern void vmem_lockup(void);
|
||||||
|
extern void vmem_release(void);
|
||||||
|
|
||||||
|
extern void vmem_sbrk_lockup(void);
|
||||||
|
extern void vmem_sbrk_release(void);
|
||||||
|
|
||||||
|
extern void vmem_no_debug(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _VMEM_BASE_H */
|
186
1.0.1/vmem_mmap.c
Normal file
186
1.0.1/vmem_mmap.c
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)vmem_mmap.c 1.2 05/06/08 SMI" */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#if HAVE_SYS_MMAN_H
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SYSMACROS_H
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "vmem_base.h"
|
||||||
|
|
||||||
|
#define ALLOC_PROT PROT_READ | PROT_WRITE | PROT_EXEC
|
||||||
|
#define FREE_PROT PROT_NONE
|
||||||
|
|
||||||
|
#define ALLOC_FLAGS MAP_PRIVATE | MAP_ANON
|
||||||
|
#define FREE_FLAGS MAP_PRIVATE | MAP_ANON | MAP_NORESERVE
|
||||||
|
|
||||||
|
#ifdef MAP_ALIGN
|
||||||
|
#define CHUNKSIZE (64*1024) /* 64 kilobytes */
|
||||||
|
#else
|
||||||
|
static size_t CHUNKSIZE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static vmem_t *mmap_heap;
|
||||||
|
|
||||||
|
static void *
|
||||||
|
vmem_mmap_alloc(vmem_t *src, size_t size, int vmflags)
|
||||||
|
{
|
||||||
|
void *ret;
|
||||||
|
int old_errno = errno;
|
||||||
|
|
||||||
|
ret = vmem_alloc(src, size, vmflags);
|
||||||
|
#ifndef _WIN32
|
||||||
|
if (ret != NULL
|
||||||
|
&&
|
||||||
|
mmap(ret, size, ALLOC_PROT, ALLOC_FLAGS | MAP_FIXED, -1, 0) ==
|
||||||
|
MAP_FAILED
|
||||||
|
) {
|
||||||
|
vmem_free(src, ret, size);
|
||||||
|
vmem_reap();
|
||||||
|
|
||||||
|
ASSERT((vmflags & VM_NOSLEEP) == VM_NOSLEEP);
|
||||||
|
errno = old_errno;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
errno = old_errno;
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vmem_mmap_free(vmem_t *src, void *addr, size_t size)
|
||||||
|
{
|
||||||
|
int old_errno = errno;
|
||||||
|
#ifdef _WIN32
|
||||||
|
VirtualFree(addr, size, MEM_RELEASE);
|
||||||
|
#else
|
||||||
|
(void) mmap(addr, size, FREE_PROT, FREE_FLAGS | MAP_FIXED, -1, 0);
|
||||||
|
#endif
|
||||||
|
vmem_free(src, addr, size);
|
||||||
|
errno = old_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
vmem_mmap_top_alloc(vmem_t *src, size_t size, int vmflags)
|
||||||
|
{
|
||||||
|
void *ret;
|
||||||
|
void *buf;
|
||||||
|
int old_errno = errno;
|
||||||
|
|
||||||
|
ret = vmem_alloc(src, size, VM_NOSLEEP);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
errno = old_errno;
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Need to grow the heap
|
||||||
|
*/
|
||||||
|
#ifdef _WIN32
|
||||||
|
buf = VirtualAlloc(NULL, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
if (buf == NULL) buf = MAP_FAILED;
|
||||||
|
#else
|
||||||
|
buf = mmap(
|
||||||
|
#ifdef MAP_ALIGN
|
||||||
|
(void *)CHUNKSIZE,
|
||||||
|
#else
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
|
size, FREE_PROT, FREE_FLAGS
|
||||||
|
#ifdef MAP_ALIGN
|
||||||
|
| MAP_ALIGN
|
||||||
|
#endif
|
||||||
|
, -1, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (buf != MAP_FAILED) {
|
||||||
|
ret = _vmem_extend_alloc(src, buf, size, size, vmflags);
|
||||||
|
if (ret != NULL)
|
||||||
|
return (ret);
|
||||||
|
else {
|
||||||
|
(void) munmap(buf, size);
|
||||||
|
errno = old_errno;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Growing the heap failed. The allocation above will
|
||||||
|
* already have called umem_reap().
|
||||||
|
*/
|
||||||
|
ASSERT((vmflags & VM_NOSLEEP) == VM_NOSLEEP);
|
||||||
|
|
||||||
|
errno = old_errno;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vmem_t *
|
||||||
|
vmem_mmap_arena(vmem_alloc_t **a_out, vmem_free_t **f_out)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
SYSTEM_INFO info;
|
||||||
|
size_t pagesize;
|
||||||
|
#else
|
||||||
|
size_t pagesize = _sysconf(_SC_PAGESIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
GetSystemInfo(&info);
|
||||||
|
pagesize = info.dwPageSize;
|
||||||
|
CHUNKSIZE = info.dwAllocationGranularity;
|
||||||
|
#elif !defined(MAP_ALIGN)
|
||||||
|
CHUNKSIZE = pagesize;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (mmap_heap == NULL) {
|
||||||
|
mmap_heap = vmem_init("mmap_top",
|
||||||
|
CHUNKSIZE,
|
||||||
|
vmem_mmap_top_alloc, vmem_free,
|
||||||
|
"mmap_heap", NULL, 0, pagesize,
|
||||||
|
vmem_mmap_alloc, vmem_mmap_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_out != NULL)
|
||||||
|
*a_out = vmem_mmap_alloc;
|
||||||
|
if (f_out != NULL)
|
||||||
|
*f_out = vmem_mmap_free;
|
||||||
|
|
||||||
|
return (mmap_heap);
|
||||||
|
}
|
326
1.0.1/vmem_sbrk.c
Normal file
326
1.0.1/vmem_sbrk.c
Normal file
|
@ -0,0 +1,326 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Portions Copyright 2006-2008 Message Systems, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)vmem_sbrk.c 1.4 05/06/08 SMI" */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The structure of the sbrk backend:
|
||||||
|
*
|
||||||
|
* +-----------+
|
||||||
|
* | sbrk_top |
|
||||||
|
* +-----------+
|
||||||
|
* | (vmem_sbrk_alloc(), vmem_free())
|
||||||
|
* |
|
||||||
|
* +-----------+
|
||||||
|
* | sbrk_heap |
|
||||||
|
* +-----------+
|
||||||
|
* | | ... | (vmem_alloc(), vmem_free())
|
||||||
|
* <other arenas>
|
||||||
|
*
|
||||||
|
* The sbrk_top arena holds all controlled memory. vmem_sbrk_alloc() handles
|
||||||
|
* allocations from it, including growing the heap when we run low.
|
||||||
|
*
|
||||||
|
* Growing the heap is complicated by the fact that we have to extend the
|
||||||
|
* sbrk_top arena (using _vmem_extend_alloc()), and that can fail. Since
|
||||||
|
* other threads may be actively allocating, we can't return the memory.
|
||||||
|
*
|
||||||
|
* Instead, we put it on a doubly-linked list, sbrk_fails, which we search
|
||||||
|
* before calling sbrk().
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
/* #include "mtlib.h" */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#ifdef HAVE_SYS_SYSMACROS_H
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
#endif
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "vmem_base.h"
|
||||||
|
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
size_t vmem_sbrk_pagesize = 0; /* the preferred page size of the heap */
|
||||||
|
|
||||||
|
#define MIN_ALLOC (64*1024)
|
||||||
|
|
||||||
|
static size_t real_pagesize;
|
||||||
|
static vmem_t *sbrk_heap;
|
||||||
|
|
||||||
|
typedef struct sbrk_fail {
|
||||||
|
struct sbrk_fail *sf_next;
|
||||||
|
struct sbrk_fail *sf_prev;
|
||||||
|
void *sf_base; /* == the sbrk_fail's address */
|
||||||
|
size_t sf_size; /* the size of this buffer */
|
||||||
|
} sbrk_fail_t;
|
||||||
|
|
||||||
|
static sbrk_fail_t sbrk_fails = {
|
||||||
|
&sbrk_fails,
|
||||||
|
&sbrk_fails,
|
||||||
|
NULL,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
static mutex_t sbrk_faillock = DEFAULTMUTEX;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _sbrk_grow_aligned() aligns the old break to a low_align boundry,
|
||||||
|
* adds min_size, aligns to a high_align boundry, and calls _brk_unlocked()
|
||||||
|
* to set the new break. The low_aligned-aligned value is returned, and
|
||||||
|
* the actual space allocated is returned through actual_size.
|
||||||
|
*
|
||||||
|
* Unlike sbrk(2), _sbrk_grow_aligned takes an unsigned size, and does
|
||||||
|
* not allow shrinking the heap.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
_sbrk_grow_aligned(size_t min_size, size_t low_align, size_t high_align,
|
||||||
|
size_t *actual_size)
|
||||||
|
{
|
||||||
|
uintptr_t old_brk;
|
||||||
|
uintptr_t ret_brk;
|
||||||
|
uintptr_t high_brk;
|
||||||
|
uintptr_t new_brk;
|
||||||
|
int brk_result;
|
||||||
|
|
||||||
|
#define ALIGNSZ 16
|
||||||
|
#define BRKALIGN(x) (caddr_t)P2ROUNDUP((uintptr_t)(x), ALIGNSZ)
|
||||||
|
|
||||||
|
if ((low_align & (low_align - 1)) != 0 ||
|
||||||
|
(high_align & (high_align - 1)) != 0) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return ((void *)-1);
|
||||||
|
}
|
||||||
|
low_align = MAX(low_align, ALIGNSZ);
|
||||||
|
high_align = MAX(high_align, ALIGNSZ);
|
||||||
|
|
||||||
|
old_brk = (uintptr_t)BRKALIGN(sbrk(0));
|
||||||
|
ret_brk = P2ROUNDUP(old_brk, low_align);
|
||||||
|
high_brk = ret_brk + min_size;
|
||||||
|
new_brk = P2ROUNDUP(high_brk, high_align);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for overflow
|
||||||
|
*/
|
||||||
|
if (ret_brk < old_brk || high_brk < ret_brk || new_brk < high_brk) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return ((void *)-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
brk_result = brk((void *)new_brk);
|
||||||
|
|
||||||
|
if (brk_result != 0)
|
||||||
|
return ((void *)-1);
|
||||||
|
|
||||||
|
if (actual_size != NULL)
|
||||||
|
*actual_size = (new_brk - ret_brk);
|
||||||
|
return ((void *)ret_brk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to extend src with [pos, pos + size).
|
||||||
|
*
|
||||||
|
* If it fails, add the block to the sbrk_fails list.
|
||||||
|
*/
|
||||||
|
static void *
|
||||||
|
vmem_sbrk_extend_alloc(vmem_t *src, void *pos, size_t size, size_t alloc,
|
||||||
|
int vmflags)
|
||||||
|
{
|
||||||
|
sbrk_fail_t *fnext, *fprev, *fp;
|
||||||
|
void *ret;
|
||||||
|
|
||||||
|
ret = _vmem_extend_alloc(src, pos, size, alloc, vmflags);
|
||||||
|
if (ret != NULL)
|
||||||
|
return (ret);
|
||||||
|
|
||||||
|
fp = (sbrk_fail_t *)pos;
|
||||||
|
|
||||||
|
ASSERT(sizeof (sbrk_fail_t) <= size);
|
||||||
|
|
||||||
|
fp->sf_base = pos;
|
||||||
|
fp->sf_size = size;
|
||||||
|
|
||||||
|
(void) mutex_lock(&sbrk_faillock);
|
||||||
|
fp->sf_next = fnext = &sbrk_fails;
|
||||||
|
fp->sf_prev = fprev = sbrk_fails.sf_prev;
|
||||||
|
fnext->sf_prev = fp;
|
||||||
|
fprev->sf_next = fp;
|
||||||
|
(void) mutex_unlock(&sbrk_faillock);
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to add at least size bytes to src, using the sbrk_fails list
|
||||||
|
*/
|
||||||
|
static void *
|
||||||
|
vmem_sbrk_tryfail(vmem_t *src, size_t size, int vmflags)
|
||||||
|
{
|
||||||
|
sbrk_fail_t *fp;
|
||||||
|
|
||||||
|
(void) mutex_lock(&sbrk_faillock);
|
||||||
|
for (fp = sbrk_fails.sf_next; fp != &sbrk_fails; fp = fp->sf_next) {
|
||||||
|
if (fp->sf_size >= size) {
|
||||||
|
fp->sf_next->sf_prev = fp->sf_prev;
|
||||||
|
fp->sf_prev->sf_next = fp->sf_next;
|
||||||
|
fp->sf_next = fp->sf_prev = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) mutex_unlock(&sbrk_faillock);
|
||||||
|
|
||||||
|
if (fp != &sbrk_fails) {
|
||||||
|
ASSERT(fp->sf_base == (void *)fp);
|
||||||
|
return (vmem_sbrk_extend_alloc(src, fp, fp->sf_size, size,
|
||||||
|
vmflags));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* nothing of the right size on the freelist
|
||||||
|
*/
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
vmem_sbrk_alloc(vmem_t *src, size_t size, int vmflags)
|
||||||
|
{
|
||||||
|
extern void *_sbrk_grow_aligned(size_t min_size, size_t low_align,
|
||||||
|
size_t high_align, size_t *actual_size);
|
||||||
|
|
||||||
|
void *ret;
|
||||||
|
void *buf;
|
||||||
|
size_t buf_size;
|
||||||
|
|
||||||
|
int old_errno = errno;
|
||||||
|
|
||||||
|
ret = vmem_alloc(src, size, VM_NOSLEEP);
|
||||||
|
if (ret != NULL) {
|
||||||
|
errno = old_errno;
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The allocation failed. We need to grow the heap.
|
||||||
|
*
|
||||||
|
* First, try to use any buffers which failed earlier.
|
||||||
|
*/
|
||||||
|
if (sbrk_fails.sf_next != &sbrk_fails &&
|
||||||
|
(ret = vmem_sbrk_tryfail(src, size, vmflags)) != NULL)
|
||||||
|
return (ret);
|
||||||
|
|
||||||
|
buf_size = MAX(size, MIN_ALLOC);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* buf_size gets overwritten with the actual allocated size
|
||||||
|
*/
|
||||||
|
buf = _sbrk_grow_aligned(buf_size, real_pagesize, vmem_sbrk_pagesize,
|
||||||
|
&buf_size);
|
||||||
|
|
||||||
|
if (buf != MAP_FAILED) {
|
||||||
|
ret = vmem_sbrk_extend_alloc(src, buf, buf_size, size, vmflags);
|
||||||
|
if (ret != NULL) {
|
||||||
|
errno = old_errno;
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Growing the heap failed. The vmem_alloc() above called umem_reap().
|
||||||
|
*/
|
||||||
|
ASSERT((vmflags & VM_NOSLEEP) == VM_NOSLEEP);
|
||||||
|
|
||||||
|
errno = old_errno;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fork1() support
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vmem_sbrk_lockup(void)
|
||||||
|
{
|
||||||
|
(void) mutex_lock(&sbrk_faillock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vmem_sbrk_release(void)
|
||||||
|
{
|
||||||
|
(void) mutex_unlock(&sbrk_faillock);
|
||||||
|
}
|
||||||
|
|
||||||
|
vmem_t *
|
||||||
|
vmem_sbrk_arena(vmem_alloc_t **a_out, vmem_free_t **f_out)
|
||||||
|
{
|
||||||
|
if (sbrk_heap == NULL) {
|
||||||
|
size_t heap_size;
|
||||||
|
|
||||||
|
real_pagesize = sysconf(_SC_PAGESIZE);
|
||||||
|
|
||||||
|
heap_size = vmem_sbrk_pagesize;
|
||||||
|
|
||||||
|
if (issetugid()) {
|
||||||
|
heap_size = 0;
|
||||||
|
} else if (heap_size != 0 && !ISP2(heap_size)) {
|
||||||
|
heap_size = 0;
|
||||||
|
log_message("ignoring bad pagesize: 0x%p\n", heap_size);
|
||||||
|
}
|
||||||
|
if (heap_size <= real_pagesize) {
|
||||||
|
heap_size = real_pagesize;
|
||||||
|
} else {
|
||||||
|
#ifdef MHA_MAPSIZE_BSSBRK
|
||||||
|
struct memcntl_mha mha;
|
||||||
|
mha.mha_cmd = MHA_MAPSIZE_BSSBRK;
|
||||||
|
mha.mha_flags = 0;
|
||||||
|
mha.mha_pagesize = heap_size;
|
||||||
|
|
||||||
|
if (memcntl(NULL, 0, MC_HAT_ADVISE, (char *)&mha, 0, 0)
|
||||||
|
== -1) {
|
||||||
|
log_message("unable to set MAPSIZE_BSSBRK to "
|
||||||
|
"0x%p\n", heap_size);
|
||||||
|
heap_size = real_pagesize;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
heap_size = real_pagesize;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
vmem_sbrk_pagesize = heap_size;
|
||||||
|
|
||||||
|
sbrk_heap = vmem_init("sbrk_top", real_pagesize,
|
||||||
|
vmem_sbrk_alloc, vmem_free,
|
||||||
|
"sbrk_heap", NULL, 0, real_pagesize,
|
||||||
|
vmem_alloc, vmem_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a_out != NULL)
|
||||||
|
*a_out = vmem_alloc;
|
||||||
|
if (f_out != NULL)
|
||||||
|
*f_out = vmem_free;
|
||||||
|
|
||||||
|
return (sbrk_heap);
|
||||||
|
}
|
164
1.0.1/vmem_stand.c
Normal file
164
1.0.1/vmem_stand.c
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma ident "@(#)vmem_stand.c 1.4 05/06/08 SMI"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standalone-specific vmem routines
|
||||||
|
*
|
||||||
|
* The standalone allocator operates on a pre-existing blob of memory, the
|
||||||
|
* location and dimensions of which are set using vmem_stand_setsize(). We
|
||||||
|
* then hand out CHUNKSIZE-sized pieces of this blob, until we run out.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DEF_CHUNKSIZE (64 * 1024) /* 64K */
|
||||||
|
|
||||||
|
#define DEF_NREGIONS 2
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/sysmacros.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
#include "vmem_base.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
static vmem_t *stand_heap;
|
||||||
|
|
||||||
|
static size_t stand_chunksize;
|
||||||
|
|
||||||
|
typedef struct stand_region {
|
||||||
|
caddr_t sr_base;
|
||||||
|
caddr_t sr_curtop;
|
||||||
|
size_t sr_left;
|
||||||
|
} stand_region_t;
|
||||||
|
|
||||||
|
static stand_region_t stand_regions[DEF_NREGIONS];
|
||||||
|
static int stand_nregions;
|
||||||
|
|
||||||
|
extern void membar_producer(void);
|
||||||
|
|
||||||
|
void
|
||||||
|
vmem_stand_init(void)
|
||||||
|
{
|
||||||
|
stand_chunksize = MAX(DEF_CHUNKSIZE, pagesize);
|
||||||
|
|
||||||
|
stand_nregions = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
vmem_stand_add(caddr_t base, size_t len)
|
||||||
|
{
|
||||||
|
stand_region_t *sr = &stand_regions[stand_nregions];
|
||||||
|
|
||||||
|
ASSERT(pagesize != 0);
|
||||||
|
|
||||||
|
if (stand_nregions == DEF_NREGIONS) {
|
||||||
|
errno = ENOSPC;
|
||||||
|
return (-1); /* we don't have room -- throw it back */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We guarantee that only one call to `vmem_stand_add' will be
|
||||||
|
* active at a time, but we can't ensure that the allocator won't be
|
||||||
|
* in use while this function is being called. As such, we have to
|
||||||
|
* ensure that sr is populated and visible to other processors before
|
||||||
|
* allowing the allocator to access the new region.
|
||||||
|
*/
|
||||||
|
sr->sr_base = base;
|
||||||
|
sr->sr_curtop = (caddr_t)P2ROUNDUP((ulong_t)base, stand_chunksize);
|
||||||
|
sr->sr_left = P2ALIGN(len - (size_t)(sr->sr_curtop - sr->sr_base),
|
||||||
|
stand_chunksize);
|
||||||
|
membar_producer();
|
||||||
|
|
||||||
|
stand_nregions++;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
stand_parent_alloc(vmem_t *src, size_t size, int vmflags)
|
||||||
|
{
|
||||||
|
int old_errno = errno;
|
||||||
|
stand_region_t *sr;
|
||||||
|
size_t chksize;
|
||||||
|
void *ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((ret = vmem_alloc(src, size, VM_NOSLEEP)) != NULL) {
|
||||||
|
errno = old_errno;
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need to allocate another chunk */
|
||||||
|
chksize = roundup(size, stand_chunksize);
|
||||||
|
|
||||||
|
for (sr = stand_regions, i = 0; i < stand_nregions; i++, sr++) {
|
||||||
|
if (sr->sr_left >= chksize)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == stand_nregions) {
|
||||||
|
/*
|
||||||
|
* We don't have enough in any of our regions to satisfy the
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
errno = old_errno;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = _vmem_extend_alloc(src, sr->sr_curtop, chksize, size,
|
||||||
|
vmflags)) == NULL) {
|
||||||
|
errno = old_errno;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(sr->sr_curtop, chksize);
|
||||||
|
|
||||||
|
sr->sr_curtop += chksize;
|
||||||
|
sr->sr_left -= chksize;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
vmem_t *
|
||||||
|
vmem_stand_arena(vmem_alloc_t **a_out, vmem_free_t **f_out)
|
||||||
|
{
|
||||||
|
ASSERT(stand_nregions == 1);
|
||||||
|
|
||||||
|
stand_heap = vmem_init("stand_parent", stand_chunksize,
|
||||||
|
stand_parent_alloc, vmem_free,
|
||||||
|
"stand_heap", NULL, 0, pagesize, vmem_alloc, vmem_free);
|
||||||
|
|
||||||
|
if (a_out != NULL)
|
||||||
|
*a_out = vmem_alloc;
|
||||||
|
if (f_out != NULL)
|
||||||
|
*f_out = vmem_free;
|
||||||
|
|
||||||
|
return (stand_heap);
|
||||||
|
}
|
49
1.0.1/vmem_stand.h
Normal file
49
1.0.1/vmem_stand.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* CDDL HEADER START
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the terms of the
|
||||||
|
* Common Development and Distribution License, Version 1.0 only
|
||||||
|
* (the "License"). You may not use this file except in compliance
|
||||||
|
* with the License.
|
||||||
|
*
|
||||||
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||||
|
* or http://www.opensolaris.org/os/licensing.
|
||||||
|
* See the License for the specific language governing permissions
|
||||||
|
* and limitations under the License.
|
||||||
|
*
|
||||||
|
* When distributing Covered Code, include this CDDL HEADER in each
|
||||||
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||||
|
* If applicable, add the following below this CDDL HEADER, with the
|
||||||
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
||||||
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
||||||
|
*
|
||||||
|
* CDDL HEADER END
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
|
||||||
|
* Use is subject to license terms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _VMEM_STAND_H
|
||||||
|
#define _VMEM_STAND_H
|
||||||
|
|
||||||
|
/* #pragma ident "@(#)vmem_stand.h 1.3 05/06/08 SMI" */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* additional functions defined by the standalone backend
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void vmem_stand_init(void);
|
||||||
|
extern int vmem_stand_add(caddr_t, size_t);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _VMEM_STAND_H */
|
Loading…
Reference in a new issue