Index: ossp-pkg/mm/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/mm/ChangeLog,v co -q -kk -p'1.13' '/v/ossp/cvs/ossp-pkg/mm/ChangeLog,v' | diff -u /dev/null - -L'ossp-pkg/mm/ChangeLog' 2>/dev/null --- ossp-pkg/mm/ChangeLog +++ - 2024-05-13 17:20:33.407283915 +0200 @@ -0,0 +1,278 @@ + __ __ __ __ + | \/ | \/ | + | |\/| | |\/| | + | | | | | | | + |_| |_|_| |_| + + MM - Shared Memory Library + + ChangeLog + ========= + _ _ + / | / | + | | | | + | |_| | + __|_(_)_|__________________________________________________________ + + Changes between 1.1.1 and 1.1.2 (30-Apr-2000 to 20-Jun-2000) + + *) Fixed type-warnings related to `char' vs. `unsigned char' in mm_test.c + [Ralf S. Engelschall] + + *) Let the internal mm_insert_chunk() function detect the situation + where a chunk of memory is inserted twice (usually caused by the + application through multiple and this way illegal calls to mm_free() with + the same argument). This especially makes sure the internal list + of free chunks is not corrupted. + [Jeffrey Hsu , Ralf S. Engelschall] + + *) Fixed typos in mm.pod. + [Ralf S. Engelschall] + + *) Fixed some logic in mm's configuration that removes -g from CFLAGS. + It incorrectly collapsed " -g " to "", which leaded to invalid CFLAGS. + [Jeff Trawick ] + + *) Fixed shared memory decisions on Linux: + We now avoid using MM_SHMT_MMANON (seems to be completely + broken on 2.0), MM_SHMT_MMZERO (seems like Linux 2.0 hates this + classical combination and return EINVAL for unknown reasons) and + MM_SHMT_IPCSHM (requires that a IPC shm filesystem is mounted + since 2.3). So, technically MM_SHMT_IPCSHM is preferred if the shm + filesystem exists, else we count on MM_SHMT_MMFILE now. + [Ralf S. Engelschall] + + Changes between 1.1.0 and 1.1.1 (30-Apr-2000 to 30-Apr-2000) + + *) Fixed compilation under Solaris where the SunOS4 and BS2000 kludges + for conflicted with the Sun vendor includes (which + unfortunately use the defines). + [Ralf S. Engelschall, Jeff Beard ] + + Changes between 1.0.12 and 1.1.0 (28-Sep-1999 to 30-Apr-2000) + + *) Fixed `make test' feedback procedure in Makefile.in now that the + platform list is stored in the PORTING file. + [Ralf S. Engelschall] + + *) Renamed file CHANGES to ChangeLog. + [Ralf S. Engelschall] + + *) Fixed pointer arithmentic in memset/memcpy replacements + by casting `void *' arguments to `char *'. + [Sascha Schumann ] + + *) Added BS2000 support for stuff. + [Martin Kraemer ] + + *) Added an include for to maximum shared mem segment size + check in aclocal.m4. This especially fixes compile problems under for + Solaris 8. + [Alexander Demenchuk , Greg Gears ] + + *) Fixed a warning under IRIX related to size_t comparisons + [Ralf S. Engelschall] + + *) Added support for IBM OS/390 + [Jeff Trawick ] + + *) Upgraded to GNU libtool from version 1.3.3 to 1.3.4 + and upgraded GNU shtool from version 1.4.6 to 1.4.9 + [Ralf S. Engelschall] + + *) Upgraded config.guess to GNU Pth's version and + use "/sbin/sysctl" under FreeBSD instead of just "sysctl" + [Jeff Trawick ] + + *) Added platform support for the esoteric Unix look-alike BeOS + [David Reid" ] + + *) Added `make check' as an alias for `make test' + [Ralf S. Engelschall] + + *) Adjusted copyright messages for year 2000 + [Ralf S. Engelschall] + + *) Fixed Autoconf checks for SunOS + [Ralf S. Engelschall] + + *) Fixed a bug in aclocal.m4's AC_CHECK_DEFINE macro. + [Ralf S. Engelschall] + + *) Updated the manual page (typos, fixes, etc.) + [Ralf S. Engelschall] + + *) Splitted README into README, PORTING and THANKS document. + [Ralf S. Engelschall] + + _ ___ + / | / _ \ + | || | | | + | || |_| | + __|_(_)___/________________________________________________________ + + Changes between 1.0.11 and 1.0.12 (06-Sep-1999 to 28-Sep-1999) + + *) Recreated configure with latest Autoconf 2.13.1 (snapshot) + *) Always use --mode=xxx for libtool calls to avoid problems under + situations where $CC doesn't allow libtool to guess the mode + correctly. + + Changes between 1.0.10 and 1.0.11 (27-Aug-1999 to 06-Sep-1999) + + *) Cleaned up various file permission in source tree + *) Enhanced mm-config.in: new --all option and less newlines + *) Added support --silent to libtool glue code in aclocal.m4 + *) Upgraded to GNU Pth's more recent config.{guess,sub} + *) Upgraded to GNU shtool 1.4.6 + *) Fixed --section for mm-config in Makefile.in + *) Added `void *' casts to MAP_FAILED (= -1) values to avoid + warnings under some platforms. + *) Fixed a few typos in mm.pod + + Changes between 1.0.9 and 1.0.10 (02-Jul-1999 to 27-Aug-1999) + + *) Changed "make dist" and "make snap" to use "shtool tarball" + *) Added #define KERNEL for SunOS to get SHM_R und SHM_W values. + *) Upgraded to GNU libtool 1.3.3 + *) Upgraded to GNU shtool 1.4.5 + *) Downgraded required Autoconf version to 2.12 + *) Added MM version number to test report + *) Added --enable-batch + *) Moved mm_lock_mode in mm.h to top to avoid warnings + + Changes between 1.0.8 and 1.0.9 (24-Jun-1999 to 02-Jul-1999) + + *) Fixed a nasty bug related to {MM,mm}_[un]lock(): + an additional semicolon broke the semantics. + *) Upgraded to released shtool 1.4.0 + *) Fixed `make test' + + Changes between 1.0.7 and 1.0.8 (22-Jun-1999 to 24-Jun-1999) + + *) Added important MAP_FAILED fallback also to Autoconf stuff + *) Upgraded to latest shtool 1.3.0-dev to fix two Awk problems + + Changes between 1.0.6 and 1.0.7 (06-Jun-1999 to 22-Jun-1999) + + *) Upgraded to latest shtool 1.3.0-dev + *) Avoid -g under non-debugging situation + *) Complain with a fatal error message when MM_SHM_MAXSEGSIZE + couldn't be determined. + *) Updated config.guess/config.sub + *) Fixed a nasty permission bug for the lock files: + they were opened write-only, but at least fcntl() + requires them to be opened read-write. + *) Check return value of mm_core_lock() in mm_alloc.c + + Changes between 1.0.5 and 1.0.6 (02-Jun-1999 to 06-Jun-1999) + + *) Fixed mm_malloc() function: it returned the wrong pointer when a chunk + was reused and forgot to lock/unlock the data structures. + *) Fixed internal best-fit algorithm for finding a free memory chunk: + - things got inserted out of order in the list + - when chunk is found which matches size exactly it stops immediately + - lowered chunk splitting threshold to MIN(2*size,128) + *) Moved internal definitions in mm.h to private section + + Changes between 1.0.4 and 1.0.5 (21-May-1999 to 02-Jun-1999) + + *) Fixed output of mm-config.in + *) Fixed output of configure --help + *) Upgraded to GNU libtool 1.3.2 + *) Upgraded to shtool 1.2.9 + *) Made libtool calls visible but use --quiet + *) Hint user to send feedback only on errors or for new platform + *) Removed unnecessary "elf" hint for FreeBSD from config.guess + + Changes between 1.0.3 and 1.0.4 (15-May-1999 to 21-May-1999) + + *) Fixed maximum memory size determination and internal handling + *) Documented the mm_lib_xxx() functions. + + Changes between 1.0.2 and 1.0.3 (26-Apr-1999 to 15-May-1999) + + *) Added {MM,mm,mm_core}_permission() function + *) Fixed version information and mod_ssl URL in manual page + *) Upgraded config.{guess,sub} from libtool 1.3 distribution + *) Upgraded to GNU libtool 1.3 + *) Upgraded to shtool 1.2.7 + *) Fixed public includes for xx_t types + *) Fixed mm_vers.c and shtool type inside CVS + + Changes between 1.0.1 and 1.0.2 (18-Apr-1999 to 26-Apr-1999) + + *) Upgraded to GNU libtool 1.2f + *) Upgraded to shtool 1.1.0 + + Changes between 1.0.0 and 1.0.1 (18-Mar-1999 to 18-Apr-1999) + + *) Fixed "dist" Makefile target to not distribute CVS stuff + *) Upgraded lshtool to the latest version + *) Const'ification of the API + + Changes between 1.0b6 and 1.0.0 (18-Mar-1999 to 28-Mar-1999) + + *) Finally cleaned up and polished the mm.pod manual page. + *) Fixed mm-config program + + Changes between 1.0b5 and 1.0b6 (18-Mar-1999 to 18-Mar-1999) + + *) Added {MM,mm}_maxsize() to manual page + *) Changed MM_create() signature to match mm_create() + + Changes between 1.0b4 and 1.0b5 (15-Mar-1999 to 18-Mar-1999) + + *) Make sure the maximum allocateable size takes + the overhead of the memory pool into account. + *) Fixed lshtool and this way hex version string + *) Fixed Makefile for mm_test target dependecies + *) Added {MM,mm}_maxsize() function to let one + determine in advance the maximum allocateable pool + + Changes between 1.0b3 and 1.0b4 (15-Mar-1999 to 15-Mar-1999) + + *) Added mm-config.pod manpage + *) Split mm-config --ldflags into --ldflags and --libs + *) Removed TODO and fulltest files + + Changes between 1.0b2 and 1.0b3 (13-Mar-1999 to 15-Mar-1999) + + *) Added Autoconf check for determining max shared mem segment size + *) Changed -1 to MAP_FAILED when available + *) Replaced 8KB default shared memory segment size with max size + *) Added mm_core_maxsegsize() function + *) Use a remembered offset for mmap() on temporary files + *) Imported source tree into CVS + *) Added read-only locking support + *) Fixed MMFILE and MMZERO variants + + Changes between 1.0b1 and 1.0b2 (12-Mar-1999 to 13-Mar-1999) + + *) Updated the mm.pod manual page. + *) Split README into README and LICENSE files + *) Fixed becho problems + *) Added a test suite summary + *) Added INSTALL file + *) Reduced mm_test's memory size from 1MB to 512KB + *) Fixed unsigned long and %X related warnings + + Changes between 1.0b0 and 1.0b1 (11-Mar-1999 to 12-Mar-1999) + + *) Enhanced mm_test + *) Added {MM,mm}_available() function + *) Fixed MMZERO + *) Fixed IPC Semaphore initialization + *) Added --with-{sem,shm}=TYPE options + *) Fixed "make test" and mm_memory_display() function + *) Added mm_lib.c source with mm_lib_xx() functions + + Changes between 0.9.0 and 1.0b0 (10-Mar-1999 to 11-Mar-1999) + + *) Switched to GNU Autoconf and GNU Libtool + + Changes between GENESIS and 0.9.0 (Jan-1999 to 10-Mar-1999) + + *) Created initial version on FreeBSD + *) Ported to Linux and Solaris + Index: ossp-pkg/mm/README RCS File: /v/ossp/cvs/ossp-pkg/mm/README,v co -q -kk -p'1.64' '/v/ossp/cvs/ossp-pkg/mm/README,v' | diff -u /dev/null - -L'ossp-pkg/mm/README' 2>/dev/null --- ossp-pkg/mm/README +++ - 2024-05-13 17:20:33.410172598 +0200 @@ -0,0 +1,29 @@ + __ __ __ __ + | \/ | \/ | + | |\/| | |\/| | + | | | | | | | + |_| |_|_| |_| + + MM - Shared Memory Library + Copyright (c) 1999-2000 Ralf S. Engelschall, All rights reserved. + Version 1.1.2 (20-Jun-2000) + + The MM library is a 2-layer abstraction library which simplifies the usage + of shared memory between forked (and this way strongly related) processes + under Unix platforms. On the first (lower) layer it hides all platform + dependent implementation details (allocation and locking) when dealing with + shared memory segments and on the second (higher) layer it provides a + high-level malloc(3)-style API for a convenient and well known way to work + with data-structures inside those shared memory segments. + + This library was successfully tested on FreeBSD, OpenBSD, NetBSD, BSDI, + Linux, SunOS, Solaris, Tru64, AIX, A/UX, HP-UX, ReliantUNIX, IRIX, UnixWare + and even Win32 Cygwin, BeOS and OS/390. + + The documentation and latest release can be found on + http://www.engelschall.com/sw/mm/ + + Ralf S. Engelschall + rse@engelschall.com + www.engelschall.com + Index: ossp-pkg/mm/THANKS RCS File: /v/ossp/cvs/ossp-pkg/mm/THANKS,v co -q -kk -p'1.8' '/v/ossp/cvs/ossp-pkg/mm/THANKS,v' | diff -u /dev/null - -L'ossp-pkg/mm/THANKS' 2>/dev/null --- ossp-pkg/mm/THANKS +++ - 2024-05-13 17:20:33.412845780 +0200 @@ -0,0 +1,62 @@ + __ __ __ __ + | \/ | \/ | + | |\/| | |\/| | + | | | | | | | + |_| |_|_| |_| + + MM - Shared Memory Library + + THANKS + ====== + + Credit has to be given to the following people who contributed ideas, + bugfixes, hints, gave platform feedback, etc. (in alphabetical order): + + o Ronald Appelfelder + o Robert Belleman + o Ryan Bloom + o Volker Borchert + o William Campbell + o Richard Cardwell + o Jeff Clark + o Eric Cholet + o Alexander Demenchuk + o Jason Dillon + o Joe France + o Richard Furda + o Dean Gaudet + o Greg Gears + o Ask Bjoern Hansen + o Jeffrey Hsu + o Robin Hunt + o Markus Kilbinger + o Kristian Köhntopp + o Jim Jagielski + o Bob Jones + o Mats Josefsson + o Sergey Kachanovsky + o Martin Kraemer + o Mike Latinovich + o Rasmus Lerdorf + o Dave Malhotra + o Christophe Massiot + o Thomas J. Menini + o Patrick + o Charles Randall + o David Rees + o Martin Rosenbach + o David Reid + o Scott Rothgaber + o Saeid Sadeghi + o Mehul N. Sanghvi + o Joaquim Sanmarti + o Sascha Schumann + o Dan Sullivan + o Jeff Trawick + o Tom Vaughan + o Kai Voigt + o Martin Waterworth + o Rick Watson + o Mark Wilkie + o Cliff Woolley + Index: ossp-pkg/mm/mm-config.1 RCS File: /v/ossp/cvs/ossp-pkg/mm/Attic/mm-config.1,v co -q -kk -p'1.13' '/v/ossp/cvs/ossp-pkg/mm/Attic/mm-config.1,v' | diff -u /dev/null - -L'ossp-pkg/mm/mm-config.1' 2>/dev/null --- ossp-pkg/mm/mm-config.1 +++ - 2024-05-13 17:20:33.415437840 +0200 @@ -0,0 +1,280 @@ +.rn '' }` +''' $RCSfile$$Revision$$Date$ +''' +''' $Log$ +''' Revision 1.13 2000/06/20 06:59:36 rse +''' *** empty log message *** +''' +''' +.de Sh +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp +.if t .sp .5v +.if n .sp +.. +.de Ip +.br +.ie \\n(.$>=3 .ne \\$3 +.el .ne 3 +.IP "\\$1" \\$2 +.. +.de Vb +.ft CW +.nf +.ne \\$1 +.. +.de Ve +.ft R + +.fi +.. +''' +''' +''' Set up \*(-- to give an unbreakable dash; +''' string Tr holds user defined translation string. +''' Bell System Logo is used as a dummy character. +''' +.tr \(*W-|\(bv\*(Tr +.ie n \{\ +.ds -- \(*W- +.ds PI pi +.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +.ds L" "" +.ds R" "" +''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of +''' \*(L" and \*(R", except that they are used on ".xx" lines, +''' such as .IP and .SH, which do another additional levels of +''' double-quote interpretation +.ds M" """ +.ds S" """ +.ds N" """"" +.ds T" """"" +.ds L' ' +.ds R' ' +.ds M' ' +.ds S' ' +.ds N' ' +.ds T' ' +'br\} +.el\{\ +.ds -- \(em\| +.tr \*(Tr +.ds L" `` +.ds R" '' +.ds M" `` +.ds S" '' +.ds N" `` +.ds T" '' +.ds L' ` +.ds R' ' +.ds M' ` +.ds S' ' +.ds N' ` +.ds T' ' +.ds PI \(*p +'br\} +.\" If the F register is turned on, we'll generate +.\" index entries out stderr for the following things: +.\" TH Title +.\" SH Header +.\" Sh Subsection +.\" Ip Item +.\" X<> Xref (embedded +.\" Of course, you have to process the output yourself +.\" in some meaninful fashion. +.if \nF \{ +.de IX +.tm Index:\\$1\t\\n%\t"\\$2" +.. +.nr % 0 +.rr F +.\} +.TH MM-CONFIG 1 "20-Jun-2000" "MM 1.1.2" "Shared Memory Library" +.UC +.if n .hy 0 +.if n .na +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.de CQ \" put $1 in typewriter font +.ft CW +'if n "\c +'if t \\&\\$1\c +'if n \\&\\$1\c +'if n \&" +\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 +'.ft R +.. +.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2 +. \" AM - accent mark definitions +.bd B 3 +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds ? ? +. ds ! ! +. ds / +. ds q +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10' +. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#] +.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u' +.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u' +.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#] +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +.ds oe o\h'-(\w'o'u*4/10)'e +.ds Oe O\h'-(\w'O'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds v \h'-1'\o'\(aa\(ga' +. ds _ \h'-1'^ +. ds . \h'-1'. +. ds 3 3 +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +. ds oe oe +. ds Oe OE +.\} +.rm #[ #] #H #V #F C +.SH "NAME" +\fBmm-config\fR \- MM library configuration/build utility +.SH "VERSION" +MM 1.1.2 (20-Jun-2000) +.SH "SYNOPSIS" +\fBmm-config\fR +[\fB--help\fR] +[\fB--version\fR] +[\fB--cflags\fR] +[\fB--ldflags\fR] +[\fB--libs\fR] +.SH "DESCRIPTION" +The \fBmm-config\fR program is a little helper utility for easy configuring and +building applications based on the \fImm\fR\|(3) library. It can be used to query the +C compiler and linker flags which are required to correctly compile and link +the application against the \fImm\fR\|(3) library. +.SH "OPTIONS" +\fBmm-config\fR accepts the following options: +.Ip "\fB--help\fR" 4 +Prints the short usage information. +.Ip "\fB--version\fR" 4 +Prints the version number and date of the installed \fImm\fR\|(3) library. +.Ip "\fB--cflags\fR" 4 +Prints the C compiler flags which are needed to compile the \fImm\fR\|(3)\-based +application. The output is usually added to the \f(CWCFLAGS\fR variable of the +applications \f(CWMakefile\fR. +.Ip "\fB--ldflags\fR" 4 +Prints the linker flags (\f(CW-L\fR) which are needed to link the application with +the \fImm\fR\|(3) library. The output is usually added to the \f(CWLDFLAGS\fR variable of +the applications \f(CWMakefile\fR. +.Ip "\fB--libs\fR" 4 +Prints the library flags (\f(CW-l\fR) which are needed to link the application with +the \fImm\fR\|(3) library. The output is usually added to the \f(CWLIBS\fR variable of the +applications \f(CWMakefile\fR. +.SH "EXAMPLE" +.PP +.Vb 10 +\& CC=cc +\& CFLAGS=-O `mm-config --cflags` +\& LDFLAGS=`mm-config --ldflags` +\& LIBS=-lm `mm-config --libs` +\& +\& all: foo +\& foo: foo.o +\& $(CC) $(LDFLAGS) -o foo foo.o $(LIBS) +\& foo.o: foo.c +\& $(CC) $(CFLAGS) -c foo.c +.Ve +.SH "SEE ALSO" +\fImm\fR\|(3). +.SH "AUTHOR" +.PP +.Vb 3 +\& Ralf S. Engelschall +\& rse@engelschall.com +\& www.engelschall.com +.Ve + +.rn }` '' +.IX Title "MM-CONFIG 1" +.IX Name "B - MM library configuration/build utility" + +.IX Header "NAME" + +.IX Header "VERSION" + +.IX Header "SYNOPSIS" + +.IX Header "DESCRIPTION" + +.IX Header "OPTIONS" + +.IX Item "\fB--help\fR" + +.IX Item "\fB--version\fR" + +.IX Item "\fB--cflags\fR" + +.IX Item "\fB--ldflags\fR" + +.IX Item "\fB--libs\fR" + +.IX Header "EXAMPLE" + +.IX Header "SEE ALSO" + +.IX Header "AUTHOR" + Index: ossp-pkg/mm/mm.3 RCS File: /v/ossp/cvs/ossp-pkg/mm/Attic/mm.3,v co -q -kk -p'1.33' '/v/ossp/cvs/ossp-pkg/mm/Attic/mm.3,v' | diff -u /dev/null - -L'ossp-pkg/mm/mm.3' 2>/dev/null --- ossp-pkg/mm/mm.3 +++ - 2024-05-13 17:20:33.418159076 +0200 @@ -0,0 +1,761 @@ +.rn '' }` +''' $RCSfile$$Revision$$Date$ +''' +''' $Log$ +''' Revision 1.33 2000/06/20 06:59:36 rse +''' *** empty log message *** +''' +''' +.de Sh +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp +.if t .sp .5v +.if n .sp +.. +.de Ip +.br +.ie \\n(.$>=3 .ne \\$3 +.el .ne 3 +.IP "\\$1" \\$2 +.. +.de Vb +.ft CW +.nf +.ne \\$1 +.. +.de Ve +.ft R + +.fi +.. +''' +''' +''' Set up \*(-- to give an unbreakable dash; +''' string Tr holds user defined translation string. +''' Bell System Logo is used as a dummy character. +''' +.tr \(*W-|\(bv\*(Tr +.ie n \{\ +.ds -- \(*W- +.ds PI pi +.if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +.if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +.ds L" "" +.ds R" "" +''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of +''' \*(L" and \*(R", except that they are used on ".xx" lines, +''' such as .IP and .SH, which do another additional levels of +''' double-quote interpretation +.ds M" """ +.ds S" """ +.ds N" """"" +.ds T" """"" +.ds L' ' +.ds R' ' +.ds M' ' +.ds S' ' +.ds N' ' +.ds T' ' +'br\} +.el\{\ +.ds -- \(em\| +.tr \*(Tr +.ds L" `` +.ds R" '' +.ds M" `` +.ds S" '' +.ds N" `` +.ds T" '' +.ds L' ` +.ds R' ' +.ds M' ` +.ds S' ' +.ds N' ` +.ds T' ' +.ds PI \(*p +'br\} +.\" If the F register is turned on, we'll generate +.\" index entries out stderr for the following things: +.\" TH Title +.\" SH Header +.\" Sh Subsection +.\" Ip Item +.\" X<> Xref (embedded +.\" Of course, you have to process the output yourself +.\" in some meaninful fashion. +.if \nF \{ +.de IX +.tm Index:\\$1\t\\n%\t"\\$2" +.. +.nr % 0 +.rr F +.\} +.TH mm 3 "20-Jun-2000" "MM 1.1.2" "Shared Memory Library" +.UC +.if n .hy 0 +.if n .na +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.de CQ \" put $1 in typewriter font +.ft CW +'if n "\c +'if t \\&\\$1\c +'if n \\&\\$1\c +'if n \&" +\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 +'.ft R +.. +.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2 +. \" AM - accent mark definitions +.bd B 3 +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds ? ? +. ds ! ! +. ds / +. ds q +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10' +. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +. ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#] +.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u' +.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u' +.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#] +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +.ds oe o\h'-(\w'o'u*4/10)'e +.ds Oe O\h'-(\w'O'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds v \h'-1'\o'\(aa\(ga' +. ds _ \h'-1'^ +. ds . \h'-1'. +. ds 3 3 +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +. ds oe oe +. ds Oe OE +.\} +.rm #[ #] #H #V #F C +.SH "NAME" +\fBMM \- Shared Memory Library\fR +.SH "VERSION" +MM 1.1.2 (20-Jun-2000) +.SH "SYNOPSIS" +.PP +.Vb 1 +\& #include "mm.h" +.Ve +\fB Global Malloc-Replacement API\fR +.PP +.Vb 14 +\& int \fBMM_create\fR(size_t size, const char *file); +\& int \fBMM_permission\fR(mode_t mode, uid_t owner, gid_t group); +\& void \fBMM_destroy\fR(void); +\& int \fBMM_lock\fR(mm_lock_mode mode); +\& int \fBMM_unlock\fR(void); +\& void *\fBMM_malloc\fR(size_t size); +\& void *\fBMM_realloc\fR(void *ptr, size_t size); +\& void \fBMM_free\fR(void *ptr); +\& void *\fBMM_calloc\fR(size_t number, size_t size); +\& char *\fBMM_strdup\fR(const char *str); +\& size_t \fBMM_sizeof\fR(void *ptr); +\& size_t \fBMM_maxsize\fR(void); +\& size_t \fBMM_available\fR(void); +\& char *\fBMM_error\fR(void); +.Ve +\fB Standard Malloc-Style API\fR +.PP +.Vb 15 +\& MM *\fBmm_create\fR(size_t size, char *file); +\& int \fBmm_permission\fR(MM *mm, mode_t mode, uid_t owner, gid_t group); +\& void \fBmm_destroy\fR(MM *mm); +\& int \fBmm_lock\fR(MM *mm, mm_lock_mode mode); +\& int \fBmm_unlock\fR(MM *mm); +\& void *\fBmm_malloc\fR(MM *mm, size_t size); +\& void *\fBmm_realloc\fR(MM *mm, void *ptr, size_t size); +\& void \fBmm_free\fR(MM *mm, void *ptr); +\& void *\fBmm_calloc\fR(MM *mm, size_t number, size_t size); +\& char *\fBmm_strdup\fR(MM *mm, const char *str); +\& size_t \fBmm_sizeof\fR(void *ptr); +\& size_t \fBmm_maxsize\fR(void); +\& size_t \fBmm_available\fR(MM *mm); +\& char *\fBmm_error\fR(void); +\& void \fBmm_display_info\fR(MM *mm); +.Ve +\fB Low-level Shared Memory API\fR +.PP +.Vb 9 +\& void *\fBmm_core_create\fR(size_t size, char *file); +\& int \fBmm_core_permission\fR(void *core, mode_t mode, uid_t owner, gid_t group); +\& void \fBmm_core_delete\fR(void *core); +\& int \fBmm_core_lock\fR(void *core, mm_lock_mode mode); +\& int \fBmm_core_unlock\fR(void *core); +\& size_t \fBmm_core_size\fR(void *core); +\& size_t \fBmm_core_maxsegsize\fR(void); +\& size_t \fBmm_core_align2page\fR(size_t size); +\& size_t \fBmm_core_align2click\fR(size_t size); +.Ve +\fB Internal Library API\fR +.PP +.Vb 3 +\& void \fBmm_lib_error_set\fR(unsigned int, const char *str); +\& char *\fBmm_lib_error_get\fR(void); +\& int \fBmm_lib_version\fR(void); +.Ve +.SH "DESCRIPTION" +The \fBMM\fR library is a 2-layer abstraction library which simplifies the usage +of shared memory between forked (and this way strongly related) processes +under Unix platforms. On the first (lower) layer it hides all platform +dependent implementation details (allocation and locking) when dealing with +shared memory segments and on the second (higher) layer it provides a +high-level \fImalloc\fR\|(3)\-style API for a convenient and well known way to work +with data-structures inside those shared memory segments. +.PP +The abbreviation \fBMM\fR is historically and originally comes from the phrase +``\fImemory mapped\fR'\*(R' as used by the POSIX.1 \fImmap\fR\|(2) function. Because this +facility is internally used by this library on most platforms to establish the +shared memory segments. +.Sh "\s-1LIBRARY\s0 \s-1STRUCTURE\s0" +This library is structured into three main APIs which are internally based on +each other: +.Ip "\fBGlobal Malloc-Replacement \s-1API\s0\fR" 4 +This is the most high-level \s-1API\s0 which directly can be used as replacement \s-1API\s0 +for the \s-1POSIX\s0.1 memory allocation \s-1API\s0 (\fImalloc\fR\|(2) and friends). This is +useful when converting \fIheap\fR based data structures to \fIshared memory\fR +based data structures without the need to change the code dramatically. All +which is needed is to prefix the \s-1POSIX\s0.1 memory allocation functions with +`\f(CWMM_\fR\*(R', i.e. `\f(CWmalloc\fR\*(R' becomes `\f(CWMM_malloc\fR\*(R', `\f(CWstrdup\fR\*(R' becomes +`\f(CWMM_strdup\fR\*(R', etc. This \s-1API\s0 internally uses just a global `\f(CWMM *\fR\*(R' pool for +calling the corresponding functions (those with prefix `\f(CWmm_\fR') of the +\fIStandard Malloc-Style \s-1API\s0\fR. +.Ip "\fBStandard Malloc-Style \s-1API\s0\fR" 4 +This is the standard high-level memory allocation \s-1API\s0. Its interface is +similar to the \fIGlobal Malloc-Replacement \s-1API\s0\fR but it uses an explicit `\f(CWMM *\fR\*(R' +pool to operate on. That is why every function of this \s-1API\s0 has an argument of +type `\f(CWMM *\fR\*(R' as its first argument. This \s-1API\s0 provides a comfortable way to +work with small dynamically allocated shared memory chunks inside large +statically allocated shared memory segments. It is internally based on the +\fILow-Level Shared Memory \s-1API\s0\fR for creating the underlaying shared memory +segment. +.Ip "\fBLow-Level Shared Memory \s-1API\s0\fR" 4 +This is the basis of the whole \fB\s-1MM\s0\fR library. It provides low-level functions +for creating shared memory segments with mutual exclusion (in short \fImutex\fR) +capabilities in a portable way. Internally the shared memory and mutex +facility is implemented in various platform-dependent ways. A list of +implementation variants follows under the next topic. +.Sh "\s-1SHARED\s0 \s-1MEMORY\s0 \s-1IMPLEMENTATION\s0" +Internally the shared memory facility is implemented in various +platform-dependent ways. Each way has its own advantages and disadvantages +(in addition to the fact that some variants aren't available at all on some +platforms). The \fB\s-1MM\s0\fR library's configuration procedure tries hard to make a +good decision. The implemented variants are now given for overview and +background reasons with their advantages and disadvantages and in an ascending +order, i.e. the \fB\s-1MM\s0\fR configuration mechanism chooses the last available one +in the list as the preferred variant. +.Ip "Classical mmap(2) on temporary file (\s-1MMFILE\s0)" 4 +\fIAdvantage:\fR maximum portable. +\fIDisadvantage:\fR needs a temporary file on the filesystem. +.Ip "mmap(2) via \s-1POSIX\s0.1 shm_open(3) on temporary file (\s-1MMPOSX\s0)" 4 +\fIAdvantage:\fR standardized by \s-1POSIX\s0.1 and theoretically portable. +\fIDisadvantage:\fR needs a temporary file on the filesystem and is +is usually not available on existing Unix platform. +.Ip "\s-1SVR4-\s0style mmap(2) on \f(CW/dev/zero\fR device (\s-1MMZERO\s0)" 4 +\fIAdvantage:\fR widely available and mostly portable on \s-1SVR4\s0 platforms. +\fIDisadvantage:\fR needs the \f(CW/dev/zero\fR device and a \fImmap\fR\|(2) +which supports memory mapping through this device. +.Ip "SysV \s-1IPC\s0 shmget(2) (\s-1IPCSHM\s0)" 4 +\fIAdvantage:\fR does not need a temporary file or external device. +\fIDisadvantage:\fR although available on mostly all modern Unix platforms, it has +strong restrictions like the maximum size of a single shared memory segment (can +be as small as 100KB, but depends on the platform). +.Ip "4.4BSD\-style mmap(2) via \f(CWMAP_ANON\fR facility (\s-1MMANON\s0)" 4 +\fIAdvantage:\fR does not need a temporary file or external device. +\fIDisadvantage:\fR usually only available on \s-1BSD\s0 platforms and derivatives. +.Sh "\s-1LOCKING\s0 \s-1IMPLEMENTATION\s0" +As for the shared memory facility, internally the locking facility is +implemented in various platform-dependent ways. They are again listed +in ascending order, i.e. the \fB\s-1MM\s0\fR configuration mechanism chooses the +last available one in the list as the preferred variant. The list of +implemented variants is: +.Ip "4.2BSD\-style flock(2) on temporary file (\s-1FLOCK\s0)" 4 +\fIAdvantage:\fR exists on a lot of platforms, especially on older Unix +derivates. \fIDisadvantage:\fR needs a temporary file on the filesystem and has +to re-open file-descriptors to it in \fIeach\fR\|(!) \fIfork\fR\|(2)'ed child process. +.Ip "SysV \s-1IPC\s0 semget(2) (\s-1IPCSEM\s0)" 4 +\fIAdvantage:\fR exists on a lot of platforms and does not need a temporary file. +\fIDisadvantage:\fR an unmeant termination of the application leads to a +semaphore leak because the facility does not allow a ``remove in advance'\*(R' +trick (as the \s-1IPC\s0 shared memory facility does) for safe cleanups. +.Ip "\s-1SVR4-\s0style fcntl(2) on temporary file (\s-1FCNTL\s0)" 4 +\fIAdvantage:\fR exists on a lot of platforms and is also the most powerful +variant (although not always the fastest one). \fIDisadvantage:\fR needs a +temporary file. +.Sh "\s-1MEMORY\s0 \s-1ALLOCATION\s0 \s-1STRATEGY\s0" +The memory allocation strategy the \fIStandard Malloc-Style \s-1API\s0\fR functions use +internally is the following: +.Ip "\fBAllocation\fR" 4 +If a chunk of memory has to be allocated, the internal list of free chunks +is searched for a minimal-size chunk which is larger or equal than the size of +the to be allocated chunk (a \fIbest fit\fR strategy). +.Sp +If a chunk is found which matches this best-fit criteria, but is still a lot +larger than the requested size, it is split into two chunks: One with exactly +the requested size (which is the resulting chunk given back) and one with the +remaining size (which is immediately re-inserted into the list of free +chunks). +.Sp +If no fitting chunk is found at all in the list of free chunks, a new one is +created from the spare area of the shared memory segment until the segment is +full (in which case an \fIout of memory\fR error occurs). +.Ip "\fBDeallocation\fR" 4 +If a chunk of memory has to be deallocated, it is inserted in sorted manner +into the internal list of free chunks. The insertion operation automatically +merges the chunk with a previous and/or a next free chunk if possible, i.e. +if the free chunks stay physically seamless (one after another) in memory, to +automatically form larger free chunks out of smaller ones. +.Sp +This way the shared memory segment is automatically defragmented when memory +is deallocated. +.PP +This strategy reduces memory waste and fragmentation caused by small and +frequent allocations and deallocations to a minimum. +.PP +The internal implementation of the list of free chunks is not specially +optimized (for instance by using binary search trees or even \fIsplay\fR trees, +etc), because it is assumed that the total amount of entries in the list of +free chunks is always small (caused both by the fact that shared memory +segments are usually a lot smaller than heaps and the fact that we always +defragment by merging the free chunks if possible). +.SH "API FUNCTIONS" +In the following, all API functions are described in detail The order . +directly follows the one in the \fBSYNOPSIS\fR section above . +.Sh "Global Malloc-Replacement \s-1API\s0" +.Ip "int \fBMM_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);" 4 +This initializes the global shared memory pool with \fIsize\fR and \fIfile\fR and +has to be called \fIbefore\fR any \fIfork\fR\|(2) operations are performed by the +application. +.Ip "int \fBMM_permission\fR(mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);" 4 +This sets the filesystem \fImode\fR, \fIowner\fR and \fIgroup\fR for the global shared +memory pool (has effects only if the underlaying shared memory segment +implementation is actually based on external auxiliary files). The arguments +are directly passed through to \fIchmod\fR\|(2) and \fIchown\fR\|(2). +.Ip "void \fBMM_destroy\fR(void);" 4 +This destroys the global shared memory pool and should be called \fIafter\fR all +child processes were killed. +.Ip "int \fBMM_lock\fR(mm_lock_mode \fImode\fR);" 4 +This locks the global shared memory pool for the current process in order to +perform either shared/read-only (\fImode\fR is \f(CWMM_LOCK_RD\fR) or +exclusive/read-write (\fImode\fR is \f(CWMM_LOCK_RW\fR) critical operations inside the +global shared memory pool. +.Ip "int \fBMM_unlock\fR(void);" 4 +This unlocks the global shared memory pool for the current process after the +critical operations were performed inside the global shared memory pool. +.Ip "void *\fBMM_malloc\fR(size_t \fIsize\fR);" 4 +Identical to the \s-1POSIX\s0.1 \fImalloc\fR\|(3) function but instead of allocating +memory from the \fIheap\fR it allocates it from the global shared memory pool. +.Ip "void \fBMM_free\fR(void *\fIptr\fR);" 4 +Identical to the \s-1POSIX\s0.1 \fIfree\fR\|(3) function but instead of deallocating +memory in the \fIheap\fR it deallocates it in the global shared memory pool. +.Ip "void *\fBMM_realloc\fR(void *\fIptr\fR, size_t \fIsize\fR);" 4 +Identical to the \s-1POSIX\s0.1 \fIrealloc\fR\|(3) function but instead of reallocating +memory in the \fIheap\fR it reallocates it inside the global shared memory pool. +.Ip "void *\fBMM_calloc\fR(size_t \fInumber\fR, size_t \fIsize\fR);" 4 +Identical to the \s-1POSIX\s0.1 \fIcalloc\fR\|(3) function but instead of allocating and +initializing memory from the \fIheap\fR it allocates and initializes it from the +global shared memory pool. +.Ip "char *\fBMM_strdup\fR(const char *\fIstr\fR);" 4 +Identical to the \s-1POSIX\s0.1 \fIstrdup\fR\|(3) function but instead of creating the +string copy in the \fIheap\fR it creates it in the global shared memory pool. +.Ip "size_t \fBMM_sizeof\fR(const void *\fIptr\fR);" 4 +This function returns the size in bytes of the chunk starting at \fIptr\fR when +\fIptr\fR was previously allocated with \fIMM_malloc\fR\|(3). The result is undefined +if \fIptr\fR was not previously allocated with \fIMM_malloc\fR\|(3). +.Ip "size_t \fBMM_maxsize\fR(void);" 4 +This function returns the maximum size which is allowed +as the first argument to the \fIMM_create\fR\|(3) function. +.Ip "size_t \fBMM_available\fR(void);" 4 +Returns the amount in bytes of still available (free) memory in the global +shared memory pool. +.Ip "char *\fBMM_error\fR(void);" 4 +Returns the last error message which occurred inside the \fB\s-1MM\s0\fR library. +.Sh "Standard Malloc-Style \s-1API\s0" +.Ip "\s-1MM\s0 *\fBmm_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);" 4 +This creates a shared memory pool which has space for approximately a total of +\fIsize\fR bytes with the help of \fIfile\fR. Here \fIfile\fR is a filesystem path to a +file which need not to exist (and perhaps is never created because this +depends on the platform and chosen shared memory and mutex implementation). +The return value is a pointer to a \f(CWMM\fR structure which should be treated as +opaque by the application. It describes the internals of the created shared +memory pool. In case of an error \f(CWNULL\fR is returned. A \fIsize\fR of 0 means to +allocate the maximum allowed size which is platform dependent and is between a +few \s-1KB\s0 and the soft limit of 64MB. +.Ip "int \fBmm_permission\fR(\s-1MM\s0 *\fImm\fR, mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);" 4 +This sets the filesystem \fImode\fR, \fIowner\fR and \fIgroup\fR for the shared memory +pool \fImm\fR (has effects only when the underlaying shared memory segment +implementation is actually based on external auxiliary files). The arguments +are directly passed through to \fIchmod\fR\|(2) and \fIchown\fR\|(2). +.Ip "void \fBmm_destroy\fR(\s-1MM\s0 *\fImm\fR);" 4 +This destroys the complete shared memory pool \fImm\fR and with it all chunks +which were allocated in this pool. Additionally any created files on the +filesystem corresponding the to shared memory pool are unlinked. +.Ip "int \fBmm_lock\fR(\s-1MM\s0 *\fImm\fR, mm_lock_mode \fImode\fR);" 4 +This locks the shared memory pool \fImm\fR for the current process in order to +perform either shared/read-only (\fImode\fR is \f(CWMM_LOCK_RD\fR) or +exclusive/read-write (\fImode\fR is \f(CWMM_LOCK_RW\fR) critical operations inside the +global shared memory pool. +.Ip "int \fBmm_unlock\fR(\s-1MM\s0 *\fImm\fR);" 4 +This unlocks the shared memory pool \fImm\fR for the current process after +critical operations were performed inside the global shared memory pool. +.Ip "void *\fBmm_malloc\fR(\s-1MM\s0 *\fImm\fR, size_t \fIsize\fR);" 4 +This function allocates \fIsize\fR bytes from the shared memory pool \fImm\fR and +returns either a (virtual memory word aligned) pointer to it or \f(CWNULL\fR in +case of an error (out of memory). It behaves like the \s-1POSIX\s0.1 \fImalloc\fR\|(3) +function but instead of allocating memory from the \fIheap\fR it allocates it +from the shared memory segment underlaying \fImm\fR. +.Ip "void \fBmm_free\fR(\s-1MM\s0 *\fImm\fR, void *\fIptr\fR);" 4 +This deallocates the chunk starting at \fIptr\fR in the shared memory pool \fImm\fR. +It behaves like the \s-1POSIX\s0.1 \fIfree\fR\|(3) function but instead of deallocating +memory from the \fIheap\fR it deallocates it from the shared memory segment +underlaying \fImm\fR. +.Ip "void *\fBmm_realloc\fR(\s-1MM\s0 *\fImm\fR, void *\fIptr\fR, size_t \fIsize\fR);" 4 +This function reallocates the chunk starting at \fIptr\fR inside the shared +memory pool \fImm\fR with the new size of \fIsize\fR bytes. It behaves like the +\s-1POSIX\s0.1 \fIrealloc\fR\|(3) function but instead of reallocating memory in the +\fIheap\fR it reallocates it in the shared memory segment underlaying \fImm\fR. +.Ip "void *\fBmm_calloc\fR(\s-1MM\s0 *\fImm\fR, size_t \fInumber\fR, size_t \fIsize\fR);" 4 +This is similar to \fImm_malloc\fR\|(3), but additionally clears the chunk. It behaves +like the \s-1POSIX\s0.1 \fIcalloc\fR\|(3) function. It allocates space for \fInumber\fR +objects, each \fIsize\fR bytes in length from the shared memory pool \fImm\fR. The +result is identical to calling \fImm_malloc\fR\|(3) with an argument of ``\fInumber\fR * +\fIsize\fR'\*(R', with the exception that the allocated memory is initialized to nul +bytes. +.Ip "char *\fBmm_strdup\fR(\s-1MM\s0 *\fImm\fR, const char *\fIstr\fR);" 4 +This function behaves like the \s-1POSIX\s0.1 \fIstrdup\fR\|(3) function. It allocates +sufficient memory inside the shared memory pool \fImm\fR for a copy of the string +\fIstr\fR, does the copy, and returns a pointer to it. The pointer may +subsequently be used as an argument to the function \fImm_free\fR\|(3). If +insufficient shared memory is available, \f(CWNULL\fR is returned. +.Ip "size_t \fBmm_sizeof\fR(const void *\fIptr\fR);" 4 +This function returns the size in bytes of the chunk starting at \fIptr\fR when +\fIptr\fR was previously allocated with \fImm_malloc\fR\|(3). The result is undefined +when \fIptr\fR was not previously allocated with \fImm_malloc\fR\|(3). +.Ip "size_t \fBmm_maxsize\fR(void);" 4 +This function returns the maximum size which is allowed as the first argument +to the \fImm_create\fR\|(3) function. +.Ip "size_t \fBmm_available\fR(\s-1MM\s0 *\fImm\fR);" 4 +Returns the amount in bytes of still available (free) memory in the +shared memory pool \fImm\fR. +.Ip "char *\fBmm_error\fR(void);" 4 +Returns the last error message which occurred inside the \fB\s-1MM\s0\fR library. +.Ip "void \fBmm_display_info\fR(\s-1MM\s0 *\fImm\fR);" 4 +This is debugging function which displays a summary page for the shared memory +pool \fImm\fR describing various internal sizes and counters. +.Sh "Low-Level Shared Memory \s-1API\s0" +.Ip "void *\fBmm_core_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);" 4 +This creates a shared memory area which is at least \fIsize\fR bytes in size with +the help of \fIfile\fR. The value \fIsize\fR has to be greater than 0 and less or +equal the value returned by \fImm_core_maxsegsize\fR\|(3). Here \fIfile\fR is a +filesystem path to a file which need not to exist (and perhaps is never +created because this depends on the platform and chosen shared memory and +mutex implementation). The return value is either a (virtual memory word +aligned) pointer to the shared memory segment or \f(CWNULL\fR in case of an error. +The application is guaranteed to be able to access the shared memory segment +from byte 0 to byte \fIsize\fR\-1 starting at the returned address. +.Ip "int \fBmm_core_permission\fR(void *\fIcore\fR, mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);" 4 +This sets the filesystem \fImode\fR, \fIowner\fR and \fIgroup\fR for the shared memory +segment \fIcode\fR (has effects only when the underlaying shared memory segment +implementation is actually based on external auxiliary files). The arguments +are directly passed through to \fIchmod\fR\|(2) and \fIchown\fR\|(2). +.Ip "void \fBmm_core_delete\fR(void *\fIcore\fR);" 4 +This deletes a shared memory segment \fIcore\fR (as previously returned by a +\fImm_core_create\fR\|(3) call). After this operation, accessing the segment starting +at \fIcore\fR is no longer allowed and will usually lead to a segmentation fault. +.Ip "int \fBmm_core_lock\fR(const void *\fIcore\fR, mm_lock_mode \fImode\fR);" 4 +This function acquires an advisory lock for the current process on the shared +memory segment \fIcore\fR for either shared/read-only (\fImode\fR is \f(CWMM_LOCK_RD\fR) +or exclusive/read-write (\fImode\fR is \f(CWMM_LOCK_RW\fR) critical operations between +\fIfork\fR\|(2)'ed child processes. +.Ip "int \fBmm_core_unlock\fR(const void *\fIcore\fR);" 4 +This function releases a previously acquired advisory lock for the current +process on the shared memory segment \fIcore\fR. +.Ip "size_t \fBmm_core_size\fR(const void *\fIcore\fR);" 4 +This returns the size in bytes of \fIcore\fR. This size is exactly the size which +was used for creating the shared memory area via \fImm_core_create\fR\|(3). The +function is provided just for convenience reasons to not require the +application to remember the memory size behind \fIcore\fR itself. +.Ip "size_t \fBmm_core_maxsegsize\fR(void);" 4 +This returns the number of bytes of a maximum-size shared memory segment which +is allowed to allocate via the \s-1MM\s0 library. It is between a few \s-1KB\s0 and the soft +limit of 64MB. +.Ip "size_t \fBmm_core_align2page\fR(size_t \fIsize\fR);" 4 +This is just a utility function which can be used to align the number \fIsize\fR +to the next virtual memory \fIpage\fR boundary used by the underlaying platform. +The memory page boundary under Unix platforms is usually somewhere between +2048 and 16384 bytes. You do not have to align the \fIsize\fR arguments of other +\fB\s-1MM\s0\fR library functions yourself, because this is already done internally. +This function is exported by the \fB\s-1MM\s0\fR library just for convenience reasons in +case an application wants to perform similar calculations for other purposes. +.Ip "size_t \fBmm_core_align2word\fR(size_t \fIsize\fR);" 4 +This is another utility function which can be used to align the number \fIsize\fR +to the next virtual memory \fIword\fR boundary used by the underlaying platform. +The memory word boundary under Unix platforms is usually somewhere between 4 +and 16 bytes. You do not have to align the \fIsize\fR arguments of other \fB\s-1MM\s0\fR +library functions yourself, because this is already done internally. This +function is exported by the \fB\s-1MM\s0\fR library just for convenience reasons in case +an application wants to perform simular calculations for other purposes. +.Sh "Low-Level Shared Memory \s-1API\s0" +.Ip "void \fBmm_lib_error_set\fR(unsigned int, const char *str);" 4 +This is a function which is used internally by the various \s-1MM\s0 function to set +an error string. It's usually not called directly from applications. +.Ip "char *\fBmm_lib_error_get\fR(void);" 4 +This is a function which is used internally by \fIMM_error\fR\|(3) and \fImm_error\fR\|(3) +functions to get the current error string. It is usually not called directly +from applications. +.Ip "int \fBmm_lib_version\fR(void);" 4 +This function returns a hex-value ``0x\fIV\fR\fI\s-1RR\s0\fR\fIT\fR\fI\s-1LL\s0\fR'\*(R' which describes the +current \fB\s-1MM\s0\fR library version. \fIV\fR is the version, \fI\s-1RR\s0\fR the revisions, \fI\s-1LL\s0\fR +the level and \fIT\fR the type of the level (alphalevel=0, betalevel=1, +patchlevel=2, etc). For instance \fB\s-1MM\s0\fR version 1.0.4 is encoded as 0x100204. +The reason for this unusual mapping is that this way the version number is +steadily \fIincreasing\fR. +.SH "RESTRICTIONS" +The maximum size of a continuous shared memory segment one can allocate +depends on the underlaying platform. This cannot be changed, of course. But +currently the high-level \fImalloc\fR\|(3)\-style API just uses a single shared memory +segment as the underlaying data structure for an \f(CWMM\fR object which means that +the maximum amount of memory an \f(CWMM\fR object represents also depends on the +platform. +.PP +This could be changed in later versions by allowing at least the +high-level \fImalloc\fR\|(3)\-style API to internally use multiple shared memory +segments to form the \f(CWMM\fR object. This way \f(CWMM\fR objects could have +arbitrary sizes, although the maximum size of an allocatable continous +chunk still is bounded by the maximum size of a shared memory segment. +.SH "SEE ALSO" +mm-\fIconfig\fR\|(1). +.PP +\fImalloc\fR\|(3), \fIcalloc\fR\|(3), \fIrealloc\fR\|(3), \fIstrdup\fR\|(3), \fIfree\fR\|(3), \fImmap\fR\|(2), \fIshmget\fR\|(2), +\fIshmctl\fR\|(2), \fIflock\fR\|(2), \fIfcntl\fR\|(2), \fIsemget\fR\|(2), \fIsemctl\fR\|(2), \fIsemop\fR\|(2). +.SH "HOME" +http://www.engelschall.com/sw/mm/ + +.SH "HISTORY" +This library was originally written in January 1999 by \fIRalf S. +Engelschall\fR for use in the \fBExtended API\fR (EAPI) +of the \fBApache\fR HTTP server project (see http://www.apache.org/), which +was originally invented for \fBmod_ssl\fR (see http://www.modssl.org/). +.PP +Its base idea (a malloc-style API for handling shared memory) was originally +derived from the non-publically available \fImm_malloc\fR library written in +October 1997 by \fICharles Randall\fR for MatchLogic, +Inc. +.SH "AUTHOR" +.PP +.Vb 3 +\& Ralf S. Engelschall +\& rse@engelschall.com +\& www.engelschall.com +.Ve + +.rn }` '' +.IX Title "mm 3" +.IX Name "B" + +.IX Header "NAME" + +.IX Header "VERSION" + +.IX Header "SYNOPSIS" + +.IX Header "DESCRIPTION" + +.IX Subsection "\s-1LIBRARY\s0 \s-1STRUCTURE\s0" + +.IX Item "\fBGlobal Malloc-Replacement \s-1API\s0\fR" + +.IX Item "\fBStandard Malloc-Style \s-1API\s0\fR" + +.IX Item "\fBLow-Level Shared Memory \s-1API\s0\fR" + +.IX Subsection "\s-1SHARED\s0 \s-1MEMORY\s0 \s-1IMPLEMENTATION\s0" + +.IX Item "Classical mmap(2) on temporary file (\s-1MMFILE\s0)" + +.IX Item "mmap(2) via \s-1POSIX\s0.1 shm_open(3) on temporary file (\s-1MMPOSX\s0)" + +.IX Item "\s-1SVR4-\s0style mmap(2) on \f(CW/dev/zero\fR device (\s-1MMZERO\s0)" + +.IX Item "SysV \s-1IPC\s0 shmget(2) (\s-1IPCSHM\s0)" + +.IX Item "4.4BSD\-style mmap(2) via \f(CWMAP_ANON\fR facility (\s-1MMANON\s0)" + +.IX Subsection "\s-1LOCKING\s0 \s-1IMPLEMENTATION\s0" + +.IX Item "4.2BSD\-style flock(2) on temporary file (\s-1FLOCK\s0)" + +.IX Item "SysV \s-1IPC\s0 semget(2) (\s-1IPCSEM\s0)" + +.IX Item "\s-1SVR4-\s0style fcntl(2) on temporary file (\s-1FCNTL\s0)" + +.IX Subsection "\s-1MEMORY\s0 \s-1ALLOCATION\s0 \s-1STRATEGY\s0" + +.IX Item "\fBAllocation\fR" + +.IX Item "\fBDeallocation\fR" + +.IX Header "API FUNCTIONS" + +.IX Subsection "Global Malloc-Replacement \s-1API\s0" + +.IX Item "int \fBMM_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);" + +.IX Item "int \fBMM_permission\fR(mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);" + +.IX Item "void \fBMM_destroy\fR(void);" + +.IX Item "int \fBMM_lock\fR(mm_lock_mode \fImode\fR);" + +.IX Item "int \fBMM_unlock\fR(void);" + +.IX Item "void *\fBMM_malloc\fR(size_t \fIsize\fR);" + +.IX Item "void \fBMM_free\fR(void *\fIptr\fR);" + +.IX Item "void *\fBMM_realloc\fR(void *\fIptr\fR, size_t \fIsize\fR);" + +.IX Item "void *\fBMM_calloc\fR(size_t \fInumber\fR, size_t \fIsize\fR);" + +.IX Item "char *\fBMM_strdup\fR(const char *\fIstr\fR);" + +.IX Item "size_t \fBMM_sizeof\fR(const void *\fIptr\fR);" + +.IX Item "size_t \fBMM_maxsize\fR(void);" + +.IX Item "size_t \fBMM_available\fR(void);" + +.IX Item "char *\fBMM_error\fR(void);" + +.IX Subsection "Standard Malloc-Style \s-1API\s0" + +.IX Item "\s-1MM\s0 *\fBmm_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);" + +.IX Item "int \fBmm_permission\fR(\s-1MM\s0 *\fImm\fR, mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);" + +.IX Item "void \fBmm_destroy\fR(\s-1MM\s0 *\fImm\fR);" + +.IX Item "int \fBmm_lock\fR(\s-1MM\s0 *\fImm\fR, mm_lock_mode \fImode\fR);" + +.IX Item "int \fBmm_unlock\fR(\s-1MM\s0 *\fImm\fR);" + +.IX Item "void *\fBmm_malloc\fR(\s-1MM\s0 *\fImm\fR, size_t \fIsize\fR);" + +.IX Item "void \fBmm_free\fR(\s-1MM\s0 *\fImm\fR, void *\fIptr\fR);" + +.IX Item "void *\fBmm_realloc\fR(\s-1MM\s0 *\fImm\fR, void *\fIptr\fR, size_t \fIsize\fR);" + +.IX Item "void *\fBmm_calloc\fR(\s-1MM\s0 *\fImm\fR, size_t \fInumber\fR, size_t \fIsize\fR);" + +.IX Item "char *\fBmm_strdup\fR(\s-1MM\s0 *\fImm\fR, const char *\fIstr\fR);" + +.IX Item "size_t \fBmm_sizeof\fR(const void *\fIptr\fR);" + +.IX Item "size_t \fBmm_maxsize\fR(void);" + +.IX Item "size_t \fBmm_available\fR(\s-1MM\s0 *\fImm\fR);" + +.IX Item "char *\fBmm_error\fR(void);" + +.IX Item "void \fBmm_display_info\fR(\s-1MM\s0 *\fImm\fR);" + +.IX Subsection "Low-Level Shared Memory \s-1API\s0" + +.IX Item "void *\fBmm_core_create\fR(size_t \fIsize\fR, const char *\fIfile\fR);" + +.IX Item "int \fBmm_core_permission\fR(void *\fIcore\fR, mode_t \fImode\fR, uid_t \fIowner\fR, gid_t \fIgroup\fR);" + +.IX Item "void \fBmm_core_delete\fR(void *\fIcore\fR);" + +.IX Item "int \fBmm_core_lock\fR(const void *\fIcore\fR, mm_lock_mode \fImode\fR);" + +.IX Item "int \fBmm_core_unlock\fR(const void *\fIcore\fR);" + +.IX Item "size_t \fBmm_core_size\fR(const void *\fIcore\fR);" + +.IX Item "size_t \fBmm_core_maxsegsize\fR(void);" + +.IX Item "size_t \fBmm_core_align2page\fR(size_t \fIsize\fR);" + +.IX Item "size_t \fBmm_core_align2word\fR(size_t \fIsize\fR);" + +.IX Subsection "Low-Level Shared Memory \s-1API\s0" + +.IX Item "void \fBmm_lib_error_set\fR(unsigned int, const char *str);" + +.IX Item "char *\fBmm_lib_error_get\fR(void);" + +.IX Item "int \fBmm_lib_version\fR(void);" + +.IX Header "RESTRICTIONS" + +.IX Header "SEE ALSO" + +.IX Header "HOME" + +.IX Header "HISTORY" + +.IX Header "AUTHOR" + Index: ossp-pkg/mm/mm.pod RCS File: /v/ossp/cvs/ossp-pkg/mm/mm.pod,v co -q -kk -p'1.16' '/v/ossp/cvs/ossp-pkg/mm/mm.pod,v' | diff -u /dev/null - -L'ossp-pkg/mm/mm.pod' 2>/dev/null --- ossp-pkg/mm/mm.pod +++ - 2024-05-13 17:20:33.421429156 +0200 @@ -0,0 +1,635 @@ +## ==================================================================== +## Copyright (c) 1999-2000 Ralf S. Engelschall. All rights reserved. +## +## Redistribution and use in source and binary forms, with or without +## modification, are permitted provided that the following conditions +## are met: +## +## 1. Redistributions of source code must retain the above copyright +## notice, this list of conditions and the following disclaimer. +## +## 2. Redistributions in binary form must reproduce the above copyright +## notice, this list of conditions and the following disclaimer in +## the documentation and/or other materials provided with the +## distribution. +## +## 3. All advertising materials mentioning features or use of this +## software must display the following acknowledgment: +## "This product includes software developed by +## Ralf S. Engelschall ." +## +## 4. Redistributions of any form whatsoever must retain the following +## acknowledgment: +## "This product includes software developed by +## Ralf S. Engelschall ." +## +## THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY +## EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +## PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR +## ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +## STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +## OF THE POSSIBILITY OF SUCH DAMAGE. +## ==================================================================== + +## +## mm.pod -- Manpage +## + +=pod + +=head1 NAME + +B + +=head1 VERSION + +MM MM_VERSION_STR + +=head1 SYNOPSIS + + #include "mm.h" + +B< Global Malloc-Replacement API> + + int MM_create(size_t size, const char *file); + int MM_permission(mode_t mode, uid_t owner, gid_t group); + void MM_destroy(void); + int MM_lock(mm_lock_mode mode); + int MM_unlock(void); + void *MM_malloc(size_t size); + void *MM_realloc(void *ptr, size_t size); + void MM_free(void *ptr); + void *MM_calloc(size_t number, size_t size); + char *MM_strdup(const char *str); + size_t MM_sizeof(void *ptr); + size_t MM_maxsize(void); + size_t MM_available(void); + char *MM_error(void); + +B< Standard Malloc-Style API> + + MM *mm_create(size_t size, char *file); + int mm_permission(MM *mm, mode_t mode, uid_t owner, gid_t group); + void mm_destroy(MM *mm); + int mm_lock(MM *mm, mm_lock_mode mode); + int mm_unlock(MM *mm); + void *mm_malloc(MM *mm, size_t size); + void *mm_realloc(MM *mm, void *ptr, size_t size); + void mm_free(MM *mm, void *ptr); + void *mm_calloc(MM *mm, size_t number, size_t size); + char *mm_strdup(MM *mm, const char *str); + size_t mm_sizeof(void *ptr); + size_t mm_maxsize(void); + size_t mm_available(MM *mm); + char *mm_error(void); + void mm_display_info(MM *mm); + +B< Low-level Shared Memory API> + + void *mm_core_create(size_t size, char *file); + int mm_core_permission(void *core, mode_t mode, uid_t owner, gid_t group); + void mm_core_delete(void *core); + int mm_core_lock(void *core, mm_lock_mode mode); + int mm_core_unlock(void *core); + size_t mm_core_size(void *core); + size_t mm_core_maxsegsize(void); + size_t mm_core_align2page(size_t size); + size_t mm_core_align2click(size_t size); + +B< Internal Library API> + + void mm_lib_error_set(unsigned int, const char *str); + char *mm_lib_error_get(void); + int mm_lib_version(void); + +=head1 DESCRIPTION + +The B library is a 2-layer abstraction library which simplifies the usage +of shared memory between forked (and this way strongly related) processes +under Unix platforms. On the first (lower) layer it hides all platform +dependent implementation details (allocation and locking) when dealing with +shared memory segments and on the second (higher) layer it provides a +high-level malloc(3)-style API for a convenient and well known way to work +with data-structures inside those shared memory segments. + +The abbreviation B is historically and originally comes from the phrase +``I'' as used by the POSIX.1 mmap(2) function. Because this +facility is internally used by this library on most platforms to establish the +shared memory segments. + +=head2 LIBRARY STRUCTURE + +This library is structured into three main APIs which are internally based on +each other: + +=over 4 + +=item B + +This is the most high-level API which directly can be used as replacement API +for the POSIX.1 memory allocation API (malloc(2) and friends). This is +useful when converting I based data structures to I +based data structures without the need to change the code dramatically. All +which is needed is to prefix the POSIX.1 memory allocation functions with +`C', i.e. `C' becomes `C', `C' becomes +`C', etc. This API internally uses just a global `C' pool for +calling the corresponding functions (those with prefix `C') of the +I. + +=item B + +This is the standard high-level memory allocation API. Its interface is +similar to the I but it uses an explicit `C' +pool to operate on. That is why every function of this API has an argument of +type `C' as its first argument. This API provides a comfortable way to +work with small dynamically allocated shared memory chunks inside large +statically allocated shared memory segments. It is internally based on the +I for creating the underlaying shared memory +segment. + +=item B + +This is the basis of the whole B library. It provides low-level functions +for creating shared memory segments with mutual exclusion (in short I) +capabilities in a portable way. Internally the shared memory and mutex +facility is implemented in various platform-dependent ways. A list of +implementation variants follows under the next topic. + +=back + +=head2 SHARED MEMORY IMPLEMENTATION + +Internally the shared memory facility is implemented in various +platform-dependent ways. Each way has its own advantages and disadvantages +(in addition to the fact that some variants aren't available at all on some +platforms). The B library's configuration procedure tries hard to make a +good decision. The implemented variants are now given for overview and +background reasons with their advantages and disadvantages and in an ascending +order, i.e. the B configuration mechanism chooses the last available one +in the list as the preferred variant. + +=over 4 + +=item Classical mmap(2) on temporary file (MMFILE) + +I maximum portable. +I needs a temporary file on the filesystem. + +=item mmap(2) via POSIX.1 shm_open(3) on temporary file (MMPOSX) + +I standardized by POSIX.1 and theoretically portable. +I needs a temporary file on the filesystem and is +is usually not available on existing Unix platform. + +=item SVR4-style mmap(2) on C device (MMZERO) + +I widely available and mostly portable on SVR4 platforms. +I needs the C device and a mmap(2) +which supports memory mapping through this device. + +=item SysV IPC shmget(2) (IPCSHM) + +I does not need a temporary file or external device. +I although available on mostly all modern Unix platforms, it has +strong restrictions like the maximum size of a single shared memory segment (can +be as small as 100KB, but depends on the platform). + +=item 4.4BSD-style mmap(2) via C facility (MMANON) + +I does not need a temporary file or external device. +I usually only available on BSD platforms and derivatives. + +=back + +=head2 LOCKING IMPLEMENTATION + +As for the shared memory facility, internally the locking facility is +implemented in various platform-dependent ways. They are again listed +in ascending order, i.e. the B configuration mechanism chooses the +last available one in the list as the preferred variant. The list of +implemented variants is: + +=over 4 + +=item 4.2BSD-style flock(2) on temporary file (FLOCK) + +I exists on a lot of platforms, especially on older Unix +derivates. I needs a temporary file on the filesystem and has +to re-open file-descriptors to it in each(!) fork(2)'ed child process. + +=item SysV IPC semget(2) (IPCSEM) + +I exists on a lot of platforms and does not need a temporary file. +I an unmeant termination of the application leads to a +semaphore leak because the facility does not allow a ``remove in advance'' +trick (as the IPC shared memory facility does) for safe cleanups. + +=item SVR4-style fcntl(2) on temporary file (FCNTL) + +I exists on a lot of platforms and is also the most powerful +variant (although not always the fastest one). I needs a +temporary file. + +=back + +=head2 MEMORY ALLOCATION STRATEGY + +The memory allocation strategy the I functions use +internally is the following: + +=over 4 + +=item B + +If a chunk of memory has to be allocated, the internal list of free chunks +is searched for a minimal-size chunk which is larger or equal than the size of +the to be allocated chunk (a I strategy). + +If a chunk is found which matches this best-fit criteria, but is still a lot +larger than the requested size, it is split into two chunks: One with exactly +the requested size (which is the resulting chunk given back) and one with the +remaining size (which is immediately re-inserted into the list of free +chunks). + +If no fitting chunk is found at all in the list of free chunks, a new one is +created from the spare area of the shared memory segment until the segment is +full (in which case an I error occurs). + +=item B + +If a chunk of memory has to be deallocated, it is inserted in sorted manner +into the internal list of free chunks. The insertion operation automatically +merges the chunk with a previous and/or a next free chunk if possible, i.e. +if the free chunks stay physically seamless (one after another) in memory, to +automatically form larger free chunks out of smaller ones. + +This way the shared memory segment is automatically defragmented when memory +is deallocated. + +=back + +This strategy reduces memory waste and fragmentation caused by small and +frequent allocations and deallocations to a minimum. + +The internal implementation of the list of free chunks is not specially +optimized (for instance by using binary search trees or even I trees, +etc), because it is assumed that the total amount of entries in the list of +free chunks is always small (caused both by the fact that shared memory +segments are usually a lot smaller than heaps and the fact that we always +defragment by merging the free chunks if possible). + +=head1 API FUNCTIONS + +In the following, all API functions are described in detail The order . +directly follows the one in the B section above . + +=head2 Global Malloc-Replacement API + +=over 4 + +=item int B(size_t I, const char *I); + +This initializes the global shared memory pool with I and I and +has to be called I any fork(2) operations are performed by the +application. + +=item int B(mode_t I, uid_t I, gid_t I); + +This sets the filesystem I, I and I for the global shared +memory pool (has effects only if the underlaying shared memory segment +implementation is actually based on external auxiliary files). The arguments +are directly passed through to chmod(2) and chown(2). + +=item void B(void); + +This destroys the global shared memory pool and should be called I all +child processes were killed. + +=item int B(mm_lock_mode I); + +This locks the global shared memory pool for the current process in order to +perform either shared/read-only (I is C) or +exclusive/read-write (I is C) critical operations inside the +global shared memory pool. + +=item int B(void); + +This unlocks the global shared memory pool for the current process after the +critical operations were performed inside the global shared memory pool. + +=item void *B(size_t I); + +Identical to the POSIX.1 malloc(3) function but instead of allocating +memory from the I it allocates it from the global shared memory pool. + +=item void B(void *I); + +Identical to the POSIX.1 free(3) function but instead of deallocating +memory in the I it deallocates it in the global shared memory pool. + +=item void *B(void *I, size_t I); + +Identical to the POSIX.1 realloc(3) function but instead of reallocating +memory in the I it reallocates it inside the global shared memory pool. + +=item void *B(size_t I, size_t I); + +Identical to the POSIX.1 calloc(3) function but instead of allocating and +initializing memory from the I it allocates and initializes it from the +global shared memory pool. + +=item char *B(const char *I); + +Identical to the POSIX.1 strdup(3) function but instead of creating the +string copy in the I it creates it in the global shared memory pool. + +=item size_t B(const void *I); + +This function returns the size in bytes of the chunk starting at I when +I was previously allocated with MM_malloc(3). The result is undefined +if I was not previously allocated with MM_malloc(3). + +=item size_t B(void); + +This function returns the maximum size which is allowed +as the first argument to the MM_create(3) function. + +=item size_t B(void); + +Returns the amount in bytes of still available (free) memory in the global +shared memory pool. + +=item char *B(void); + +Returns the last error message which occurred inside the B library. + +=back + +=head2 Standard Malloc-Style API + +=over 4 + +=item MM *B(size_t I, const char *I); + +This creates a shared memory pool which has space for approximately a total of +I bytes with the help of I. Here I is a filesystem path to a +file which need not to exist (and perhaps is never created because this +depends on the platform and chosen shared memory and mutex implementation). +The return value is a pointer to a C structure which should be treated as +opaque by the application. It describes the internals of the created shared +memory pool. In case of an error C is returned. A I of 0 means to +allocate the maximum allowed size which is platform dependent and is between a +few KB and the soft limit of 64MB. + +=item int B(MM *I, mode_t I, uid_t I, gid_t I); + +This sets the filesystem I, I and I for the shared memory +pool I (has effects only when the underlaying shared memory segment +implementation is actually based on external auxiliary files). The arguments +are directly passed through to chmod(2) and chown(2). + +=item void B(MM *I); + +This destroys the complete shared memory pool I and with it all chunks +which were allocated in this pool. Additionally any created files on the +filesystem corresponding the to shared memory pool are unlinked. + +=item int B(MM *I, mm_lock_mode I); + +This locks the shared memory pool I for the current process in order to +perform either shared/read-only (I is C) or +exclusive/read-write (I is C) critical operations inside the +global shared memory pool. + +=item int B(MM *I); + +This unlocks the shared memory pool I for the current process after +critical operations were performed inside the global shared memory pool. + +=item void *B(MM *I, size_t I); + +This function allocates I bytes from the shared memory pool I and +returns either a (virtual memory word aligned) pointer to it or C in +case of an error (out of memory). It behaves like the POSIX.1 malloc(3) +function but instead of allocating memory from the I it allocates it +from the shared memory segment underlaying I. + +=item void B(MM *I, void *I); + +This deallocates the chunk starting at I in the shared memory pool I. +It behaves like the POSIX.1 free(3) function but instead of deallocating +memory from the I it deallocates it from the shared memory segment +underlaying I. + +=item void *B(MM *I, void *I, size_t I); + +This function reallocates the chunk starting at I inside the shared +memory pool I with the new size of I bytes. It behaves like the +POSIX.1 realloc(3) function but instead of reallocating memory in the +I it reallocates it in the shared memory segment underlaying I. + +=item void *B(MM *I, size_t I, size_t I); + +This is similar to mm_malloc(3), but additionally clears the chunk. It behaves +like the POSIX.1 calloc(3) function. It allocates space for I +objects, each I bytes in length from the shared memory pool I. The +result is identical to calling mm_malloc(3) with an argument of ``I * +I'', with the exception that the allocated memory is initialized to nul +bytes. + +=item char *B(MM *I, const char *I); + +This function behaves like the POSIX.1 strdup(3) function. It allocates +sufficient memory inside the shared memory pool I for a copy of the string +I, does the copy, and returns a pointer to it. The pointer may +subsequently be used as an argument to the function mm_free(3). If +insufficient shared memory is available, C is returned. + +=item size_t B(const void *I); + +This function returns the size in bytes of the chunk starting at I when +I was previously allocated with mm_malloc(3). The result is undefined +when I was not previously allocated with mm_malloc(3). + +=item size_t B(void); + +This function returns the maximum size which is allowed as the first argument +to the mm_create(3) function. + +=item size_t B(MM *I); + +Returns the amount in bytes of still available (free) memory in the +shared memory pool I. + +=item char *B(void); + +Returns the last error message which occurred inside the B library. + +=item void B(MM *I); + +This is debugging function which displays a summary page for the shared memory +pool I describing various internal sizes and counters. + +=back + +=head2 Low-Level Shared Memory API + +=over 4 + +=item void *B(size_t I, const char *I); + +This creates a shared memory area which is at least I bytes in size with +the help of I. The value I has to be greater than 0 and less or +equal the value returned by mm_core_maxsegsize(3). Here I is a +filesystem path to a file which need not to exist (and perhaps is never +created because this depends on the platform and chosen shared memory and +mutex implementation). The return value is either a (virtual memory word +aligned) pointer to the shared memory segment or C in case of an error. +The application is guaranteed to be able to access the shared memory segment +from byte 0 to byte I-1 starting at the returned address. + +=item int B(void *I, mode_t I, uid_t I, gid_t I); + +This sets the filesystem I, I and I for the shared memory +segment I (has effects only when the underlaying shared memory segment +implementation is actually based on external auxiliary files). The arguments +are directly passed through to chmod(2) and chown(2). + +=item void B(void *I); + +This deletes a shared memory segment I (as previously returned by a +mm_core_create(3) call). After this operation, accessing the segment starting +at I is no longer allowed and will usually lead to a segmentation fault. + +=item int B(const void *I, mm_lock_mode I); + +This function acquires an advisory lock for the current process on the shared +memory segment I for either shared/read-only (I is C) +or exclusive/read-write (I is C) critical operations between +fork(2)'ed child processes. + +=item int B(const void *I); + +This function releases a previously acquired advisory lock for the current +process on the shared memory segment I. + +=item size_t B(const void *I); + +This returns the size in bytes of I. This size is exactly the size which +was used for creating the shared memory area via mm_core_create(3). The +function is provided just for convenience reasons to not require the +application to remember the memory size behind I itself. + +=item size_t B(void); + +This returns the number of bytes of a maximum-size shared memory segment which +is allowed to allocate via the MM library. It is between a few KB and the soft +limit of 64MB. + +=item size_t B(size_t I); + +This is just a utility function which can be used to align the number I +to the next virtual memory I boundary used by the underlaying platform. +The memory page boundary under Unix platforms is usually somewhere between +2048 and 16384 bytes. You do not have to align the I arguments of other +B library functions yourself, because this is already done internally. +This function is exported by the B library just for convenience reasons in +case an application wants to perform similar calculations for other purposes. + +=item size_t B(size_t I); + +This is another utility function which can be used to align the number I +to the next virtual memory I boundary used by the underlaying platform. +The memory word boundary under Unix platforms is usually somewhere between 4 +and 16 bytes. You do not have to align the I arguments of other B +library functions yourself, because this is already done internally. This +function is exported by the B library just for convenience reasons in case +an application wants to perform simular calculations for other purposes. + +=back + +=head2 Low-Level Shared Memory API + +=over 4 + +=item void B(unsigned int, const char *str); + +This is a function which is used internally by the various MM function to set +an error string. It's usually not called directly from applications. + +=item char *B(void); + +This is a function which is used internally by MM_error(3) and mm_error(3) +functions to get the current error string. It is usually not called directly +from applications. + +=item int B(void); + +This function returns a hex-value ``0xIIII'' which describes the +current B library version. I is the version, I the revisions, I +the level and I the type of the level (alphalevel=0, betalevel=1, +patchlevel=2, etc). For instance B version 1.0.4 is encoded as 0x100204. +The reason for this unusual mapping is that this way the version number is +steadily I. + +=back + +=head1 RESTRICTIONS + +The maximum size of a continuous shared memory segment one can allocate +depends on the underlaying platform. This cannot be changed, of course. But +currently the high-level malloc(3)-style API just uses a single shared memory +segment as the underlaying data structure for an C object which means that +the maximum amount of memory an C object represents also depends on the +platform. + +This could be changed in later versions by allowing at least the +high-level malloc(3)-style API to internally use multiple shared memory +segments to form the C object. This way C objects could have +arbitrary sizes, although the maximum size of an allocatable continous +chunk still is bounded by the maximum size of a shared memory segment. + +=head1 SEE ALSO + +mm-config(1). + +malloc(3), calloc(3), realloc(3), strdup(3), free(3), mmap(2), shmget(2), +shmctl(2), flock(2), fcntl(2), semget(2), semctl(2), semop(2). + +=head1 HOME + +=for html +http://www.engelschall.com/sw/mm/ + +=for text +http://www.engelschall.com/sw/mm/ + +=for man +http://www.engelschall.com/sw/mm/ + +=head1 HISTORY + +This library was originally written in January 1999 by I for use in the B (EAPI) +of the B HTTP server project (see http://www.apache.org/), which +was originally invented for B (see http://www.modssl.org/). + +Its base idea (a malloc-style API for handling shared memory) was originally +derived from the non-publically available I library written in +October 1997 by I for MatchLogic, +Inc. + +=head1 AUTHOR + + Ralf S. Engelschall + rse@engelschall.com + www.engelschall.com + +=cut + Index: ossp-pkg/mm/mm_alloc.c RCS File: /v/ossp/cvs/ossp-pkg/mm/mm_alloc.c,v co -q -kk -p'1.14' '/v/ossp/cvs/ossp-pkg/mm/mm_alloc.c,v' | diff -u /dev/null - -L'ossp-pkg/mm/mm_alloc.c' 2>/dev/null --- ossp-pkg/mm/mm_alloc.c +++ - 2024-05-13 17:20:33.424460015 +0200 @@ -0,0 +1,452 @@ +/* ==================================================================== + * Copyright (c) 1999-2000 Ralf S. Engelschall. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by + * Ralf S. Engelschall ." + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by + * Ralf S. Engelschall ." + * + * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +/* +** +** mm_alloc.c -- Standard Malloc-Style API +** +*/ + +#define MM_PRIVATE +#include "mm.h" + +/* + * Create a memory pool + */ +MM *mm_create(size_t usize, const char *file) +{ + MM *mm = NULL; + void *core; + size_t size; + size_t maxsize; + + /* defaults */ + maxsize = mm_maxsize(); + if (usize == 0) + usize = maxsize; + if (usize > maxsize) + usize = maxsize; + if (usize < MM_ALLOC_MINSIZE) + usize = MM_ALLOC_MINSIZE; + + /* determine size */ + size = usize+SIZEOF_mem_pool; + + /* get a shared memory area */ + if ((core = mm_core_create(size, file)) == NULL) + return NULL; + + /* fill in the memory pool structure */ + mm = (MM *)core; + mm->mp_size = size; + mm->mp_offset = SIZEOF_mem_pool; + + /* first element of list of free chunks counts existing chunks */ + mm->mp_freechunks.mc_size = 0; /* has to be 0 forever */ + mm->mp_freechunks.mc_usize = 0; /* counts chunks */ + mm->mp_freechunks.mc_u.mc_next = NULL; + + return mm; +} + +/* + * Set permissions on memory pools underlaying disk files + */ +int mm_permission(MM *mm, mode_t mode, uid_t owner, gid_t group) +{ + if (mm == NULL) + return -1; + return mm_core_permission((void *)mm, mode, owner, group); +} + +/* + * Destroy a memory pool + */ +void mm_destroy(MM *mm) +{ + if (mm == NULL) + return; + /* wipe out the whole area to be safe */ + memset(mm, 0, mm->mp_size); + /* and delete the core area */ + (void)mm_core_delete((void *)mm); + return; +} + +/* + * Lock a memory pool + */ +int mm_lock(MM *mm, mm_lock_mode mode) +{ + if (mm == NULL) + return FALSE; + return mm_core_lock((void *)mm, mode); +} + +/* + * Unlock a memory pool + */ +int mm_unlock(MM *mm) +{ + if (mm == NULL) + return FALSE; + return mm_core_unlock((void *)mm); +} + +/* + * Display debugging information + */ +void mm_display_info(MM *mm) +{ + mem_chunk *mc; + int nFree; + int nAlloc; + int i; + + if (!mm_core_lock((void *)mm, MM_LOCK_RD)) + return; + mc = &(mm->mp_freechunks); + nFree = 0; + while (mc->mc_u.mc_next != NULL) { + mc = mc->mc_u.mc_next; + nFree += mc->mc_size; + } + nAlloc = mm->mp_offset-SIZEOF_mem_pool-nFree; + + fprintf(stderr, "Information for MM\n"); + fprintf(stderr, " memory area = 0x%lx - 0x%lx\n", (unsigned long)mm, (unsigned long)(mm+mm->mp_size)); + fprintf(stderr, " memory size = %d\n", mm->mp_size); + fprintf(stderr, " memory offset = %d\n", mm->mp_offset); + fprintf(stderr, " bytes spare = %d\n", mm->mp_size-mm->mp_offset); + fprintf(stderr, " bytes free = %d (%d chunk%s)\n", + nFree, mm->mp_freechunks.mc_usize, + mm->mp_freechunks.mc_usize == 1 ? "" : "s"); + fprintf(stderr, " bytes allocated = %d\n", nAlloc); + + fprintf(stderr, " List of free chunks:\n"); + if (mm->mp_freechunks.mc_usize > 0) { + mc = &(mm->mp_freechunks); + i = 1; + while (mc->mc_u.mc_next != NULL) { + mc = mc->mc_u.mc_next; + fprintf(stderr, " chunk #%03d: 0x%lx-0x%lx (%d bytes)\n", + i++, (unsigned long)mc, (unsigned long)(mc+mc->mc_size), mc->mc_size); + } + } + else { + fprintf(stderr, " \n"); + } + mm_core_unlock((void *)mm); + return; +} + +/* + * Insert a chunk to the list of free chunks. Algorithm used is: + * Insert in sorted manner to the list and merge with previous + * and/or next chunk when possible to form larger chunks out of + * smaller ones. + */ +static void mm_insert_chunk(MM *mm, mem_chunk *mcInsert) +{ + mem_chunk *mc; + mem_chunk *mcPrev; + mem_chunk *mcNext; + + if (!mm_core_lock((void *)mm, MM_LOCK_RW)) + return; + mc = &(mm->mp_freechunks); + while (mc->mc_u.mc_next != NULL && (char *)(mc->mc_u.mc_next) < (char *)mcInsert) + mc = mc->mc_u.mc_next; + mcPrev = mc; + mcNext = mc->mc_u.mc_next; + if (mcPrev == mcInsert || mcNext == mcInsert) { + mm_core_unlock((void *)mm); + ERR(MM_ERR_ALLOC, "chunk of memory already in free list"); + return; + } + if ((char *)mcPrev+(mcPrev->mc_size) == (char *)mcInsert && + (mcNext != NULL && (char *)mcInsert+(mcInsert->mc_size) == (char *)mcNext)) { + /* merge with previous and next chunk */ + mcPrev->mc_size += mcInsert->mc_size + mcNext->mc_size; + mcPrev->mc_u.mc_next = mcNext->mc_u.mc_next; + mm->mp_freechunks.mc_usize -= 1; + } + else if ((char *)mcPrev+(mcPrev->mc_size) == (char *)mcInsert) { + /* merge with previous chunk */ + mcPrev->mc_size += mcInsert->mc_size; + } + else if (mcNext != NULL && (char *)mcInsert+(mcInsert->mc_size) == (char *)mcNext) { + /* merge with next chunk */ + mcInsert->mc_size += mcNext->mc_size; + mcInsert->mc_u.mc_next = mcNext->mc_u.mc_next; + mcPrev->mc_u.mc_next = mcInsert; + } + else { + /* no merging possible, so insert as new chunk */ + mcInsert->mc_u.mc_next = mcNext; + mcPrev->mc_u.mc_next = mcInsert; + mm->mp_freechunks.mc_usize += 1; + } + mm_core_unlock((void *)mm); + return; +} + +/* + * Retrieve a chunk from the list of free chunks. Algorithm used + * is: Search for minimal-sized chunk which is larger or equal + * than the request size. But when the retrieved chunk is still a + * lot larger than the requested size, split out the requested + * size to not waste memory. + */ +static mem_chunk *mm_retrieve_chunk(MM *mm, size_t size) +{ + mem_chunk *mc; + mem_chunk **pmcMin; + mem_chunk *mcRes; + size_t sMin; + size_t s; + + if (size == 0) + return NULL; + if (mm->mp_freechunks.mc_usize == 0) + return NULL; + if (!mm_core_lock((void *)mm, MM_LOCK_RW)) + return NULL; + + /* find best-fitting chunk */ + pmcMin = NULL; + sMin = mm->mp_size; /* initialize with maximum possible */ + mc = &(mm->mp_freechunks); + while (mc->mc_u.mc_next != NULL) { + s = mc->mc_u.mc_next->mc_size; + if (s >= size && s < sMin) { + pmcMin = &(mc->mc_u.mc_next); + sMin = s; + if (s == size) + break; + } + mc = mc->mc_u.mc_next; + } + + /* create result chunk */ + if (pmcMin == NULL) + mcRes = NULL; + else { + mcRes = *pmcMin; + if (mcRes->mc_size >= (size + min_of(2*size,128))) { + /* split out in part */ + s = mcRes->mc_size - size; + mcRes->mc_size = size; + /* add back remaining chunk part as new chunk */ + mc = (mem_chunk *)((char *)mcRes + size); + mc->mc_size = s; + mc->mc_u.mc_next = mcRes->mc_u.mc_next; + *pmcMin = mc; + } + else { + /* split out as a whole */ + *pmcMin = mcRes->mc_u.mc_next; + mm->mp_freechunks.mc_usize--; + } + } + + mm_core_unlock((void *)mm); + return mcRes; +} + +/* + * Allocate a chunk of memory + */ +void *mm_malloc(MM *mm, size_t usize) +{ + mem_chunk *mc; + size_t size; + void *vp; + + if (mm == NULL || usize == 0) + return NULL; + size = mm_core_align2word(SIZEOF_mem_chunk+usize); + if ((mc = mm_retrieve_chunk(mm, size)) != NULL) { + mc->mc_usize = usize; + return &(mc->mc_u.mc_base.mw_cp); + } + if (!mm_core_lock((void *)mm, MM_LOCK_RW)) + return NULL; + if ((mm->mp_size - mm->mp_offset) < size) { + mm_core_unlock((void *)mm); + ERR(MM_ERR_ALLOC, "out of memory"); + errno = ENOMEM; + return NULL; + } + mc = (mem_chunk *)((char *)mm + mm->mp_offset); + mc->mc_size = size; + mc->mc_usize = usize; + vp = (void *)&(mc->mc_u.mc_base.mw_cp); + mm->mp_offset += size; + mm_core_unlock((void *)mm); + return vp; +} + +/* + * Reallocate a chunk of memory + */ +void *mm_realloc(MM *mm, void *ptr, size_t usize) +{ + size_t size; + mem_chunk *mc; + void *vp; + + if (mm == NULL || usize == 0) + return NULL; + if (ptr == NULL) + return mm_malloc(mm, usize); /* POSIX.1 semantics */ + mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk); + if (usize <= mc->mc_usize) { + mc->mc_usize = usize; + return ptr; + } + size = mm_core_align2word(SIZEOF_mem_chunk+usize); + if (size <= mc->mc_size) { + mc->mc_usize = usize; + return ptr; + } + if ((vp = mm_malloc(mm, usize)) == NULL) + return NULL; + memcpy(vp, ptr, usize); + mm_free(mm, ptr); + return vp; +} + +/* + * Free a chunk of memory + */ +void mm_free(MM *mm, void *ptr) +{ + mem_chunk *mc; + + if (mm == NULL || ptr == NULL) + return; + mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk); + mm_insert_chunk(mm, mc); + return; +} + +/* + * Allocate and initialize a chunk of memory + */ +void *mm_calloc(MM *mm, size_t number, size_t usize) +{ + void *vp; + + if (mm == NULL || number*usize == 0) + return NULL; + if ((vp = mm_malloc(mm, number*usize)) == NULL) + return NULL; + memset(vp, 0, number*usize); + return vp; +} + +/* + * Duplicate a string + */ +char *mm_strdup(MM *mm, const char *str) +{ + int n; + void *vp; + + if (mm == NULL || str == NULL) + return NULL; + n = strlen(str); + if ((vp = mm_malloc(mm, n+1)) == NULL) + return NULL; + memcpy(vp, str, n+1); + return vp; +} + +/* + * Determine user size of a memory chunk + */ +size_t mm_sizeof(MM *mm, const void *ptr) +{ + mem_chunk *mc; + + if (mm == NULL || ptr == NULL) + return -1; + mc = (mem_chunk *)((char *)ptr - SIZEOF_mem_chunk); + return mc->mc_usize; +} + +/* + * Determine maximum size of an allocateable memory pool + */ +size_t mm_maxsize(void) +{ + return (mm_core_maxsegsize()-SIZEOF_mem_pool); +} + +/* + * Determine available memory + */ +size_t mm_available(MM *mm) +{ + mem_chunk *mc; + int nFree; + + if (!mm_core_lock((void *)mm, MM_LOCK_RD)) + return 0; + nFree = mm->mp_size-mm->mp_offset; + mc = &(mm->mp_freechunks); + while (mc->mc_u.mc_next != NULL) { + mc = mc->mc_u.mc_next; + nFree += mc->mc_size; + } + mm_core_unlock((void *)mm); + return nFree; +} + +/* + * Return last error string + */ +char *mm_error(void) +{ + return mm_lib_error_get(); +} + +/*EOF*/ Index: ossp-pkg/mm/mm_test.c RCS File: /v/ossp/cvs/ossp-pkg/mm/mm_test.c,v co -q -kk -p'1.7' '/v/ossp/cvs/ossp-pkg/mm/mm_test.c,v' | diff -u /dev/null - -L'ossp-pkg/mm/mm_test.c' 2>/dev/null --- ossp-pkg/mm/mm_test.c +++ - 2024-05-13 17:20:33.427243818 +0200 @@ -0,0 +1,265 @@ +/* ==================================================================== + * Copyright (c) 1999-2000 Ralf S. Engelschall. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by + * Ralf S. Engelschall ." + * + * 4. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by + * Ralf S. Engelschall ." + * + * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +/* +** +** mm_test.c -- Test Suite for MM Library +** +*/ + +#include +#include +#include +#include +#include + +#define MM_PRIVATE +#include "mm.h" + +#define FAILED_IF(expr) \ + if (expr) { \ + char *e; \ + e = mm_error(); \ + fprintf(stderr, "%s\n", e != NULL ? e : "Unknown Error"); \ + exit(1); \ + } + +int main(int argc, char *argv[]) +{ + unsigned char *core; + int i; + size_t s, s2; + pid_t pid; + int size; + MM *mm; + int n; + char *cp[1025]; + int version; + struct count_test { int count; int prev; } *ct; + + setbuf(stderr, NULL); + + /* + ** + ** Test Global Library API + ** + */ + + fprintf(stderr, "\n*** TESTING GLOBAL LIBRARY API ***\n\n"); + + fprintf(stderr, "Fetching library version\n"); + version = mm_lib_version(); + FAILED_IF(version == 0x0); + fprintf(stderr, "version = 0x%X\n", version); + + /* + ** + ** Test Low-Level Shared Memory API + ** + */ + + fprintf(stderr, "\n*** TESTING LOW-LEVEL SHARED MEMORY API ***\n"); + + fprintf(stderr, "\n=== Testing Memory Segment Access ===\n"); + + fprintf(stderr, "Creating 16KB shared memory core area\n"); + core = mm_core_create(1024*16, NULL); + FAILED_IF(core == NULL); + s = mm_core_size(core); + FAILED_IF(s == 0); + fprintf(stderr, "actually allocated core size = %d\n", s); + + fprintf(stderr, "Writing 0xF5 bytes to shared memory core area\n"); + for (i = 0; i < s; i++) { + fprintf(stderr, "write to core[%06d]\r", i); + core[i] = 0xF5; + } + fprintf(stderr, "\n"); + + fprintf(stderr, "Reading back 0xF5 bytes from shared memory core area\n"); + for (i = 0; i < s; i++) { + fprintf(stderr, "read from core[%06d]\r", i); + if (core[i] != 0xF5) { + fprintf(stderr, "Offset %d: 0xF5 not found (found 0x%X\n", i, core[i]); + exit(0); + } + } + fprintf(stderr, "\n"); + + fprintf(stderr, "Destroying shared memory core area\n"); + mm_core_delete(core); + + fprintf(stderr, "\n=== Testing Memory Locking ===\n"); + + fprintf(stderr, "Creating small shared memory core area\n"); + ct = mm_core_create(sizeof(struct count_test), NULL); + FAILED_IF(ct == NULL); + s = mm_core_size(ct); + FAILED_IF(s == 0); + fprintf(stderr, "actually allocated core size = %d\n", s); + + ct->prev = 0; + ct->count = 1; + if ((pid = fork()) == 0) { + /* child */ + while (ct->count < 32768) { + if (!mm_core_lock(ct, MM_LOCK_RW)) { + fprintf(stderr, "locking failed (child)\n"); + FAILED_IF(1); + } + if (ct->prev != (ct->count-1)) { + fprintf(stderr, "Failed, prev=%d != count=%d\n", ct->prev, ct->count); + exit(1); + } + ct->count += 1; + fprintf(stderr, "count=%06d (child )\r", ct->count); + ct->prev += 1; + if (!mm_core_unlock(ct)) { + fprintf(stderr, "locking failed (child)\n"); + FAILED_IF(1); + } + } + exit(0); + } + /* parent ... */ + while (ct->count < 32768) { + if (!mm_core_lock(ct, MM_LOCK_RW)) { + fprintf(stderr, "locking failed (parent)\n"); + FAILED_IF(1); + } + if (ct->prev != (ct->count-1)) { + fprintf(stderr, "Failed, prev=%d != count=%d\n", ct->prev, ct->count); + exit(1); + } + ct->count += 1; + fprintf(stderr, "count=%06d (parent)\r", ct->count); + ct->prev += 1; + if (!mm_core_unlock(ct)) { + fprintf(stderr, "locking failed (parent)\n"); + kill(pid, SIGTERM); + FAILED_IF(1); + } + } + waitpid(pid, NULL, 0); + fprintf(stderr, "\n"); + + fprintf(stderr, "Destroying shared memory core area\n"); + mm_core_delete(ct); + + /* + ** + ** Test Standard Malloc-style API + ** + */ + + fprintf(stderr, "\n*** TESTING STANDARD MALLOC-STYLE API ***\n"); + + fprintf(stderr, "\n=== Testing Allocation ===\n"); + + fprintf(stderr, "Creating MM object\n"); + size = mm_maxsize(); + if (size > 1024*1024*1) + size = 1024*1024*1; + mm = mm_create(size, NULL); + FAILED_IF(mm == NULL) + mm_display_info(mm); + s = mm_available(mm); + FAILED_IF(s == 0); + fprintf(stderr, "actually available bytes = %d\n", s); + + fprintf(stderr, "Allocating areas inside MM\n"); + n = 0; + for (i = 0; i < 1024; i++) + cp[i] = NULL; + for (i = 0; i < 1024; i++) { + fprintf(stderr, "total=%09d allocated=%09d add=%06d\r", s, n, (i+1)*(i+1)); + s2 = mm_available(mm); + if ((i+1)*(i+1) > s2) { + cp[i] = mm_malloc(mm, (i+1)*(i+1)); + if (cp[i] != NULL) { + fprintf(stderr, "\nExpected an out of memory situation. Hmmmmm\n"); + FAILED_IF(1); + } + break; + } + cp[i] = mm_malloc(mm, (i+1)*(i+1)); + n += (i+1)*(i+1); + FAILED_IF(cp[i] == NULL) + memset(cp[i], 0xF5, (i+1)*(i+1)); + } + mm_display_info(mm); + + fprintf(stderr, "\n=== Testing Defragmentation ===\n"); + + fprintf(stderr, "Fragmenting memory area by freeing some selected areas\n"); + for (i = 0; i < 1024; i++) { + if (i % 2 == 0) + continue; + if (cp[i] != NULL) + mm_free(mm, cp[i]); + cp[i] = NULL; + } + mm_display_info(mm); + + fprintf(stderr, "Freeing all areas\n"); + for (i = 0; i < 1024; i++) { + mm_free(mm, cp[i]); + } + mm_display_info(mm); + + fprintf(stderr, "Checking for memory leaks\n"); + s2 = mm_available(mm); + if (s != s2) { + fprintf(stderr, "Something is leaking, we've lost %d bytes\n", s - s2); + FAILED_IF(1); + } + else { + fprintf(stderr, "Fine, we have again %d bytes available\n", s2); + } + + fprintf(stderr, "Destroying MM object\n"); + mm_destroy(mm); + + /******/ + + fprintf(stderr, "\nOK - ALL TESTS SUCCESSFULLY PASSED.\n\n"); + exit(0); +} + Index: ossp-pkg/mm/mm_vers.c RCS File: /v/ossp/cvs/ossp-pkg/mm/mm_vers.c,v co -q -kk -p'1.34' '/v/ossp/cvs/ossp-pkg/mm/mm_vers.c,v' | diff -u /dev/null - -L'ossp-pkg/mm/mm_vers.c' 2>/dev/null --- ossp-pkg/mm/mm_vers.c +++ - 2024-05-13 17:20:33.429936307 +0200 @@ -0,0 +1,32 @@ +/* +** mm_vers.c -- Version Information +** [automatically generated and maintained by GNU shtool] +*/ + +#ifdef _AS_HEADER + +#ifndef _MM_VERS_C +#define _MM_VERS_C +#define MM_VERSION 0x101202 +extern const int MM_Version; +extern const char MM_VersionStr[]; +extern const char MM_Hello[]; +extern const char MM_GNUVersion[]; +extern const char MM_WhatID[]; +extern const char MM_RCSIdentID[]; +extern const char MM_WebID[]; +extern const char MM_PlainID[]; +#endif /* _MM_VERS_C */ + +#else + +const int MM_Version = 0x101202; +const char MM_VersionStr[] = "1.1.2 (20-Jun-2000)"; +const char MM_Hello[] = "This is MM, Version 1.1.2 (20-Jun-2000)"; +const char MM_GNUVersion[] = "MM Version 1.1.2"; +const char MM_WhatID[] = "@(#)MM Version 1.1.2 (20-Jun-2000)"; +const char MM_RCSIdentID[] = "$Id$"; +const char MM_WebID[] = "MM/1.1.2"; +const char MM_PlainID[] = "1.1.2"; + +#endif