OSSP CVS Repository

ossp - Check-in [52]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 52
Date: 2000-Jun-19 08:59:36 (local)
2000-Jun-19 06:59:36 (UTC)
User:rse
Branch:
Comment: *** empty log message ***
Tickets:
Inspections:
Files:
ossp-pkg/mm/ChangeLog      added-> 1.13
ossp-pkg/mm/README      added-> 1.64
ossp-pkg/mm/THANKS      added-> 1.8
ossp-pkg/mm/mm-config.1      added-> 1.13
ossp-pkg/mm/mm.3      added-> 1.33
ossp-pkg/mm/mm.pod      added-> 1.16
ossp-pkg/mm/mm_alloc.c      added-> 1.14
ossp-pkg/mm/mm_test.c      added-> 1.7
ossp-pkg/mm/mm_vers.c      added-> 1.34

ossp-pkg/mm/ChangeLog -> 1.13

*** /dev/null    Sun Apr 28 16:11:00 2024
--- -    Sun Apr 28 16:14:29 2024
***************
*** 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 <hsu@FreeBSD.ORG>, 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 <trawickj@bellsouth.net>]
+ 
+   *) 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 <sys/shm.h> conflicted with the Sun vendor includes (which
+      unfortunately use the defines).
+      [Ralf S. Engelschall, Jeff Beard <jeff@cyberxape.com>]
+ 
+  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 <sascha@schumann.cx>]
+      
+   *) Added BS2000 support for <sys/shm.h> stuff.
+      [Martin Kraemer <martin.kraemer@mch.sni.de>]
+      
+   *) Added an include for <fcntl.h> to maximum shared mem segment size
+      check in aclocal.m4. This especially fixes compile problems under for
+      Solaris 8.
+      [Alexander Demenchuk <alder@untech.com>, Greg Gears <gears@netair.com>]
+ 
+   *) Fixed a warning under IRIX related to size_t comparisons
+      [Ralf S. Engelschall]
+ 
+   *) Added support for IBM OS/390
+      [Jeff Trawick <trawick@ibm.net>]
+ 
+   *) 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 <trawick@ibm.net>]
+ 
+   *) Added platform support for the esoteric Unix look-alike BeOS
+      [David Reid" <dreid@jetnet.co.uk>]
+ 
+   *) 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
+ 


ossp-pkg/mm/README -> 1.64

*** /dev/null    Sun Apr 28 16:11:00 2024
--- -    Sun Apr 28 16:14:29 2024
***************
*** 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
+ 


ossp-pkg/mm/THANKS -> 1.8

*** /dev/null    Sun Apr 28 16:11:00 2024
--- -    Sun Apr 28 16:14:29 2024
***************
*** 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          <ra@intraregio.net>
+     o  Robert Belleman             <robbel@wins.uva.nl>
+     o  Ryan Bloom                  <rbb@apache.org>
+     o  Volker Borchert             <bt@teknon.de>
+     o  William Campbell            <william@stand.demon.co.uk>
+     o  Richard Cardwell            <ricc@hplb.hpl.hp.com>
+     o  Jeff Clark                  <hotwire@hoser.com>
+     o  Eric Cholet                 <cholet@logilune.com>
+     o  Alexander Demenchuk         <alder@untech.com>
+     o  Jason Dillon                <jason@planet57.com>
+     o  Joe France                  <france@sysar.com>
+     o  Richard Furda               <riso@best.ca>
+     o  Dean Gaudet                 <dgaudet@arctic.org>
+     o  Greg Gears                  <gears@netair.com>
+     o  Ask Bjoern Hansen           <ask@netcetera.dk>
+     o  Jeffrey Hsu                 <hsu@FreeBSD.ORG>
+     o  Robin Hunt                  <robin@sharenet.co.za>
+     o  Markus Kilbinger            <kilbi@rad.rwth-aachen.de>
+     o  Kristian Köhntopp           <kk@netuse.de>
+     o  Jim Jagielski               <jim@jagunet.com>
+     o  Bob Jones                   <jonesr@pjm.com>
+     o  Mats Josefsson              <matjos@rsv.se>
+     o  Sergey Kachanovsky          <ranger@tversu.ru>
+     o  Martin Kraemer              <martin.kraemer@mch.sni.de>
+     o  Mike Latinovich             <mlatin@boing.skysys.org>
+     o  Rasmus Lerdorf              <rasmus@lerdorf.on.ca>
+     o  Dave Malhotra               <davem@glue.umd.edu>
+     o  Christophe Massiot          <massiot@via.ecp.fr>
+     o  Thomas J. Menini            <menini@lvip.net>
+     o  Patrick                     <puzzled@symplex.net>
+     o  Charles Randall             <crandall@matchlogic.com> 
+     o  David Rees                  <drees@ucsd.edu>
+     o  Martin Rosenbach            <Rosenbach@seninn.verwalt-berlin.de>
+     o  David Reid                  <dreid@jetnet.co.uk>
+     o  Scott Rothgaber             <scott@easley.net>
+     o  Saeid Sadeghi               <Saeid.Sadeghi@unilever.com>
+     o  Mehul N. Sanghvi            <mehul@kirsun.ne.mediaone.net>
+     o  Joaquim Sanmarti            <qss@gtd.es>
+     o  Sascha Schumann             <sascha@schumann.cx>
+     o  Dan Sullivan                <sullivan@epa.gov>
+     o  Jeff Trawick                <trawick@ibm.net>
+     o  Tom Vaughan                 <tvaughan@aventail.com>
+     o  Kai Voigt                   <k@123.org>
+     o  Martin Waterworth           <m.waterworth@qut.edu.au>
+     o  Rick Watson                 <rick@akbar.cc.utexas.edu>
+     o  Mark Wilkie                 <mark@exceptionmedia.com>
+     o  Cliff Woolley               <jwoolley@wlu.edu>
+ 


ossp-pkg/mm/mm-config.1 -> 1.13

*** /dev/null    Sun Apr 28 16:11:00 2024
--- -    Sun Apr 28 16:14:29 2024
***************
*** 0 ****
--- 1,280 ----
+ .rn '' }`
+ ''' $RCSfile: mm-config.1,v $$Revision: 1.13 $$Date: 2000/06/20 06:59:36 $
+ '''
+ ''' $Log: mm-config.1,v $
+ ''' 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-config> - 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"
+ 


ossp-pkg/mm/mm.3 -> 1.33

*** /dev/null    Sun Apr 28 16:11:00 2024
--- -    Sun Apr 28 16:14:29 2024
***************
*** 0 ****
--- 1,758 ----
+ .rn '' }`
+ ''' $RCSfile$$Revision$$Date$
+ '''
+ ''' $Log$
+ '''
+ .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 <rse@engelschall.com> 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 <crandall@matchlogic.com> 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<MM - Shared Memory Library>"
+ 
+ .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"
+ 


ossp-pkg/mm/mm.pod -> 1.16

*** /dev/null    Sun Apr 28 16:11:00 2024
--- -    Sun Apr 28 16:14:29 2024
***************
*** 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 <rse@engelschall.com>."
+ ##
+ ## 4. Redistributions of any form whatsoever must retain the following
+ ##    acknowledgment:
+ ##    "This product includes software developed by
+ ##     Ralf S. Engelschall <rse@engelschall.com>."
+ ##
+ ## 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<MM - Shared Memory Library>
+ 
+ =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<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. 
+ 
+ The abbreviation B<MM> is historically and originally comes from the phrase
+ ``I<memory mapped>'' 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<Global Malloc-Replacement API>
+ 
+ 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<heap> based data structures to I<shared memory>
+ 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<MM_>', i.e. `C<malloc>' becomes `C<MM_malloc>', `C<strdup>' becomes
+ `C<MM_strdup>', etc. This API internally uses just a global `C<MM *>' pool for
+ calling the corresponding functions (those with prefix `C<mm_>') of the
+ I<Standard Malloc-Style API>.
+ 
+ =item B<Standard Malloc-Style API>
+ 
+ This is the standard high-level memory allocation API. Its interface is
+ similar to the I<Global Malloc-Replacement API> but it uses an explicit `C<MM *>'
+ pool to operate on. That is why every function of this API has an argument of
+ type `C<MM *>' 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<Low-Level Shared Memory API> for creating the underlaying shared memory
+ segment.
+ 
+ =item B<Low-Level Shared Memory API>
+ 
+ This is the basis of the whole B<MM> library. It provides low-level functions
+ for creating shared memory segments with mutual exclusion (in short I<mutex>)
+ 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<MM> 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<MM> 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<Advantage:> maximum portable.
+ I<Disadvantage:> needs a temporary file on the filesystem.
+ 
+ =item mmap(2) via POSIX.1 shm_open(3) on temporary file (MMPOSX)
+ 
+ I<Advantage:> standardized by POSIX.1 and theoretically portable.
+ I<Disadvantage:> needs a temporary file on the filesystem and is
+ is usually not available on existing Unix platform.
+ 
+ =item SVR4-style mmap(2) on C</dev/zero> device (MMZERO)
+ 
+ I<Advantage:> widely available and mostly portable on SVR4 platforms.
+ I<Disadvantage:> needs the C</dev/zero> device and a mmap(2)
+ which supports memory mapping through this device.
+ 
+ =item SysV IPC shmget(2) (IPCSHM)
+ 
+ I<Advantage:> does not need a temporary file or external device.
+ I<Disadvantage:> 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<MAP_ANON> facility (MMANON)
+ 
+ I<Advantage:> does not need a temporary file or external device.
+ I<Disadvantage:> 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<MM> 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<Advantage:> exists on a lot of platforms, especially on older Unix
+ derivates.  I<Disadvantage:> 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<Advantage:> exists on a lot of platforms and does not need a temporary file.
+ I<Disadvantage:> 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<Advantage:> exists on a lot of platforms and is also the most powerful
+ variant (although not always the fastest one). I<Disadvantage:> needs a
+ temporary file.
+ 
+ =back
+ 
+ =head2 MEMORY ALLOCATION STRATEGY
+ 
+ The memory allocation strategy the I<Standard Malloc-Style API> functions use
+ internally is the following:
+ 
+ =over 4
+ 
+ =item B<Allocation>
+ 
+ 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<best fit> 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<out of memory> error occurs).
+ 
+ =item B<Deallocation>
+ 
+ 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<splay> 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<SYNOPSIS> section above              .
+ 
+ =head2 Global Malloc-Replacement API
+ 
+ =over 4
+ 
+ =item int B<MM_create>(size_t I<size>, const char *I<file>);
+ 
+ This initializes the global shared memory pool with I<size> and I<file> and
+ has to be called I<before> any fork(2) operations are performed by the
+ application.
+ 
+ =item int B<MM_permission>(mode_t I<mode>, uid_t I<owner>, gid_t I<group>);
+ 
+ This sets the filesystem I<mode>, I<owner> and I<group> 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<MM_destroy>(void);
+ 
+ This destroys the global shared memory pool and should be called I<after> all
+ child processes were killed.
+ 
+ =item int B<MM_lock>(mm_lock_mode I<mode>);
+ 
+ This locks the global shared memory pool for the current process in order to
+ perform either shared/read-only (I<mode> is C<MM_LOCK_RD>) or
+ exclusive/read-write (I<mode> is C<MM_LOCK_RW>) critical operations inside the
+ global shared memory pool.
+ 
+ =item int B<MM_unlock>(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<MM_malloc>(size_t I<size>);
+ 
+ Identical to the POSIX.1 malloc(3) function but instead of allocating
+ memory from the I<heap> it allocates it from the global shared memory pool.
+ 
+ =item void B<MM_free>(void *I<ptr>);
+ 
+ Identical to the POSIX.1 free(3) function but instead of deallocating
+ memory in the I<heap> it deallocates it in the global shared memory pool.
+ 
+ =item void *B<MM_realloc>(void *I<ptr>, size_t I<size>);
+ 
+ Identical to the POSIX.1 realloc(3) function but instead of reallocating
+ memory in the I<heap> it reallocates it inside the global shared memory pool.
+ 
+ =item void *B<MM_calloc>(size_t I<number>, size_t I<size>);
+ 
+ Identical to the POSIX.1 calloc(3) function but instead of allocating and
+ initializing memory from the I<heap> it allocates and initializes it from the
+ global shared memory pool.
+ 
+ =item char *B<MM_strdup>(const char *I<str>);
+ 
+ Identical to the POSIX.1 strdup(3) function but instead of creating the
+ string copy in the I<heap> it creates it in the global shared memory pool.
+ 
+ =item size_t B<MM_sizeof>(const void *I<ptr>);
+ 
+ This function returns the size in bytes of the chunk starting at I<ptr> when
+ I<ptr> was previously allocated with MM_malloc(3). The result is undefined
+ if I<ptr> was not previously allocated with MM_malloc(3).
+ 
+ =item size_t B<MM_maxsize>(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_available>(void);
+ 
+ Returns the amount in bytes of still available (free) memory in the global
+ shared memory pool.
+ 
+ =item char *B<MM_error>(void);
+ 
+ Returns the last error message which occurred inside the B<MM> library.
+ 
+ =back
+ 
+ =head2 Standard Malloc-Style API
+ 
+ =over 4
+ 
+ =item MM *B<mm_create>(size_t I<size>, const char *I<file>);
+ 
+ This creates a shared memory pool which has space for approximately a total of
+ I<size> bytes with the help of I<file>. Here I<file> 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<MM> 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<NULL> is returned.  A I<size> 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_permission>(MM *I<mm>, mode_t I<mode>, uid_t I<owner>, gid_t I<group>);
+ 
+ This sets the filesystem I<mode>, I<owner> and I<group> for the shared memory
+ pool I<mm> (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_destroy>(MM *I<mm>);
+ 
+ This destroys the complete shared memory pool I<mm> 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_lock>(MM *I<mm>, mm_lock_mode I<mode>);
+ 
+ This locks the shared memory pool I<mm> for the current process in order to
+ perform either shared/read-only (I<mode> is C<MM_LOCK_RD>) or
+ exclusive/read-write (I<mode> is C<MM_LOCK_RW>) critical operations inside the
+ global shared memory pool.
+ 
+ =item int B<mm_unlock>(MM *I<mm>);
+ 
+ This unlocks the shared memory pool I<mm> for the current process after
+ critical operations were performed inside the global shared memory pool.
+ 
+ =item void *B<mm_malloc>(MM *I<mm>, size_t I<size>);
+ 
+ This function allocates I<size> bytes from the shared memory pool I<mm> and
+ returns either a (virtual memory word aligned) pointer to it or C<NULL> 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<heap> it allocates it
+ from the shared memory segment underlaying I<mm>.
+ 
+ =item void B<mm_free>(MM *I<mm>, void *I<ptr>);
+ 
+ This deallocates the chunk starting at I<ptr> in the shared memory pool I<mm>.
+ It behaves like the POSIX.1 free(3) function but instead of deallocating
+ memory from the I<heap> it deallocates it from the shared memory segment
+ underlaying I<mm>.
+ 
+ =item void *B<mm_realloc>(MM *I<mm>, void *I<ptr>, size_t I<size>);
+ 
+ This function reallocates the chunk starting at I<ptr> inside the shared
+ memory pool I<mm> with the new size of I<size> bytes.  It behaves like the
+ POSIX.1 realloc(3) function but instead of reallocating memory in the
+ I<heap> it reallocates it in the shared memory segment underlaying I<mm>.
+ 
+ =item void *B<mm_calloc>(MM *I<mm>, size_t I<number>, size_t I<size>);
+ 
+ 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<number>
+ objects, each I<size> bytes in length from the shared memory pool I<mm>.  The
+ result is identical to calling mm_malloc(3) with an argument of ``I<number> *
+ I<size>'', with the exception that the allocated memory is initialized to nul
+ bytes.
+ 
+ =item char *B<mm_strdup>(MM *I<mm>, const char *I<str>);
+ 
+ This function behaves like the POSIX.1 strdup(3) function.  It allocates
+ sufficient memory inside the shared memory pool I<mm> for a copy of the string
+ I<str>, 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<NULL> is returned.
+ 
+ =item size_t B<mm_sizeof>(const void *I<ptr>);
+ 
+ This function returns the size in bytes of the chunk starting at I<ptr> when
+ I<ptr> was previously allocated with mm_malloc(3). The result is undefined
+ when I<ptr> was not previously allocated with mm_malloc(3).
+ 
+ =item size_t B<mm_maxsize>(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_available>(MM *I<mm>);
+ 
+ Returns the amount in bytes of still available (free) memory in the 
+ shared memory pool I<mm>.
+ 
+ =item char *B<mm_error>(void);
+ 
+ Returns the last error message which occurred inside the B<MM> library.
+ 
+ =item void B<mm_display_info>(MM *I<mm>);
+ 
+ This is debugging function which displays a summary page for the shared memory
+ pool I<mm> describing various internal sizes and counters.
+ 
+ =back
+ 
+ =head2 Low-Level Shared Memory API
+ 
+ =over 4
+ 
+ =item void *B<mm_core_create>(size_t I<size>, const char *I<file>);
+ 
+ This creates a shared memory area which is at least I<size> bytes in size with
+ the help of I<file>. The value I<size> has to be greater than 0 and less or
+ equal the value returned by mm_core_maxsegsize(3). Here I<file> 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<NULL> in case of an error.
+ The application is guaranteed to be able to access the shared memory segment
+ from byte 0 to byte I<size>-1 starting at the returned address.
+ 
+ =item int B<mm_core_permission>(void *I<core>, mode_t I<mode>, uid_t I<owner>, gid_t I<group>);
+ 
+ This sets the filesystem I<mode>, I<owner> and I<group> for the shared memory
+ segment I<code> (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_core_delete>(void *I<core>);
+ 
+ This deletes a shared memory segment I<core> (as previously returned by a
+ mm_core_create(3) call). After this operation, accessing the segment starting
+ at I<core> is no longer allowed and will usually lead to a segmentation fault.
+ 
+ =item int B<mm_core_lock>(const void *I<core>, mm_lock_mode I<mode>);
+ 
+ This function acquires an advisory lock for the current process on the shared
+ memory segment I<core> for either shared/read-only (I<mode> is C<MM_LOCK_RD>)
+ or exclusive/read-write (I<mode> is C<MM_LOCK_RW>) critical operations between
+ fork(2)'ed child processes.
+ 
+ =item int B<mm_core_unlock>(const void *I<core>);
+ 
+ This function releases a previously acquired advisory lock for the current
+ process on the shared memory segment I<core>.
+ 
+ =item size_t B<mm_core_size>(const void *I<core>);
+ 
+ This returns the size in bytes of I<core>. 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<core> itself. 
+ 
+ =item size_t B<mm_core_maxsegsize>(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<mm_core_align2page>(size_t I<size>);
+ 
+ This is just a utility function which can be used to align the number I<size>
+ to the next virtual memory I<page> 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<size> arguments of other
+ B<MM> library functions yourself, because this is already done internally.
+ This function is exported by the B<MM> library just for convenience reasons in
+ case an application wants to perform similar calculations for other purposes.
+ 
+ =item size_t B<mm_core_align2word>(size_t I<size>);
+ 
+ This is another utility function which can be used to align the number I<size>
+ to the next virtual memory I<word> 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<size> arguments of other B<MM>
+ library functions yourself, because this is already done internally.  This
+ function is exported by the B<MM> 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<mm_lib_error_set>(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<mm_lib_error_get>(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<mm_lib_version>(void);
+ 
+ This function returns a hex-value ``0xI<V>I<RR>I<T>I<LL>'' which describes the
+ current B<MM> library version. I<V> is the version, I<RR> the revisions, I<LL>
+ the level and I<T> the type of the level (alphalevel=0, betalevel=1,
+ patchlevel=2, etc). For instance B<MM> version 1.0.4 is encoded as 0x100204.
+ The reason for this unusual mapping is that this way the version number is
+ steadily I<increasing>.
+ 
+ =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<MM> object which means that
+ the maximum amount of memory an C<MM> 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<MM> object. This way C<MM> 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 
+ <a href="http://www.engelschall.com/sw/mm/">http://www.engelschall.com/sw/mm/</a>
+ 
+ =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<Ralf S.
+ Engelschall> <rse@engelschall.com> for use in the B<Extended API> (EAPI)
+ of the B<Apache> HTTP server project (see http://www.apache.org/), which
+ was originally invented for B<mod_ssl> (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<mm_malloc> library written in
+ October 1997 by I<Charles Randall> <crandall@matchlogic.com> for MatchLogic,
+ Inc.
+ 
+ =head1 AUTHOR
+ 
+  Ralf S. Engelschall
+  rse@engelschall.com
+  www.engelschall.com
+ 
+ =cut
+ 


ossp-pkg/mm/mm_alloc.c -> 1.14

*** /dev/null    Sun Apr 28 16:11:00 2024
--- -    Sun Apr 28 16:14:29 2024
***************
*** 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 <rse@engelschall.com>."
+  *
+  * 4. Redistributions of any form whatsoever must retain the following
+  *    acknowledgment:
+  *    "This product includes software developed by
+  *     Ralf S. Engelschall <rse@engelschall.com>."
+  *
+  * 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, "        <empty-list>\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*/


ossp-pkg/mm/mm_test.c -> 1.7

*** /dev/null    Sun Apr 28 16:11:00 2024
--- -    Sun Apr 28 16:14:29 2024
***************
*** 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 <rse@engelschall.com>."
+  *
+  * 4. Redistributions of any form whatsoever must retain the following
+  *    acknowledgment:
+  *    "This product includes software developed by
+  *     Ralf S. Engelschall <rse@engelschall.com>."
+  *
+  * 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 <stdio.h>
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+ #include <signal.h>
+ 
+ #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);
+ }
+ 


ossp-pkg/mm/mm_vers.c -> 1.34

*** /dev/null    Sun Apr 28 16:11:00 2024
--- -    Sun Apr 28 16:14:29 2024
***************
*** 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: MM 1.1.2 20-Jun-2000 $";
+ const char MM_WebID[]      = "MM/1.1.2";
+ const char MM_PlainID[]    = "1.1.2";
+ 
+ #endif

CVSTrac 2.0.1