From: matt@centerline.com (Matt Landau)
Newsgroups: comp.sys.sun.misc,comp.unix.solaris,comp.unix.misc
Subject: mallopt() a no-op in SunOS 4.1.x?
Date: 29 Dec 1992 20:53:06 GMT
Organization: CenterLine Software, Inc.
Distribution: inet
NNTP-Posting-Host: 140.239.1.32

Can anyone either verify or refute the observation that mallopt, although 
it's present in the C library, seems to be a no-op in SunOS 4.1.x?

Compiling and running the attached program on a variety of systems -- an
HP/700 running HP/UX 8, a sparc running SunOS 4.1.1, and a sparc running 
Solaris 2.1 -- suggests that mallopt actually has some effect in HP/UX 
and in Solaris, but no effect at all in SunOS 4.

Run the program with no arguments to allocate 10 blocks and print their
addresses.  Then run it again with the arguments "-s 256", to make a 
call to mallopt(M_MXFAST, 256) on startup.  Observe that on the HP and
Solaris 2.1 platforms, the addresses you get back from malloc will be
different than in the no-arguments case, and that the mallinfo structure
will claim that malloc is actually using the small block allocation 
scheme.

Under SunOS 4, however, the addresses returned from malloc are the same
whether or not mallopt is used, and although mallinfo claims that some
small blocks have been allocated, this seems to be a lie, and there is
no evidence anywhere else in the mallinfo structure that small blocks 
are being used.

So, can anyone who has access to the SunOS 4.1 version of malloc verify
that mallopt is, in fact, doing nothing except causing some fields in
the mallinfo structure to be incremented?  Or is there some bug in the
mallopt usage in my test program?  Any clues?
--
 Matt Landau			Waiting for a flash of enlightenment
 matt@centerline.com			  in all this blood and thunder


---------------  cut here for mallopt test program ---------------------

#include <stdio.h>
#include <malloc.h>

typedef struct mallinfo	m_info;

/* 
 * You may want to compile with -Dcomplete for SunOS 4.1.x, where the
 * mallinfo structure has a few extra fields.
 */

#if complete

#define MINFO_FORMAT "\
total arena size = %d\n\
number of ordinary blocks = %d\n\
number of small blocks = %d\n\
number of holding blocks = %d\n\
space in holding block headers = %d\n\
space in small blocks in use = %d\n\
space in free small blocks = %d\n\
space in ordinary blocks in use = %d\n\
space in free ordinary blocks = %d\n\
cost of enabling keep option = %d\n\
max size of small blocks = %d\n\
number of small blocks in a holding block = %d\n\
small block rounding factor = %d\n\
space (including overhead) allocated in ord. blocks = %d\n\
number of ordinary blocks allocated = %d\n\
bytes used in maintaining free tree = %d\n"

#else

#define MINFO_FORMAT "\
total arena size = %d\n\
number of ordinary blocks = %d\n\
number of small blocks = %d\n\
number of holding blocks = %d\n\
space in holding block headers = %d\n\
space in small blocks in use = %d\n\
space in free small blocks = %d\n\
space in ordinary blocks in use = %d\n\
space in free ordinary blocks = %d\n\
cost of enabling keep option = %d\n"

#endif

/* getopt stuff.  why isn't this in a header file? */

extern char *optarg;
extern int optind, opterr;


main(ac, av)
int ac;
char **av;
{
    int		opt;
    int		mallopt_size  = -1;
    int		mallopt_grain = -1;
    char *	ptr;
    m_info	mi;
    int		n;

    while ((opt = getopt(ac, av, "s:g:")) != -1)
    {
	switch(opt)
	{
	  case 's':
	    mallopt_size = atoi(optarg);
	    break;

	  case 'g':
	    mallopt_grain = atoi(optarg);
	    break;

	  default:
	    fprintf(stderr, "usage: %s [-s opt_size] [-g opt_grain]\n", av[0]);
	    exit(1);
	}
    }

    
    if (mallopt_size > 0)
    {
	if (mallopt(M_MXFAST, mallopt_size) != 0)
	    fprintf(stderr, "Could not mallopt(M_MXFAST, %d)\n", mallopt_size);
	else
	    fprintf(stderr, "Mallopt size set to %d\n", mallopt_size);
    }
    
    if (mallopt_grain > 0)
    {
	if (mallopt(M_GRAIN, mallopt_grain) != 0)
	    fprintf(stderr, "Could not mallopt(M_GRAIN, %d)\n", mallopt_grain);
	else
	    fprintf(stderr, "Mallopt grain set to %d\n", mallopt_grain);
    }
    

    for (n = 0 ; n < 5 ; n++)
    {
	ptr = malloc(10);
	fprintf(stderr, "malloc(10)   = 0x%0x\n", ptr);
    }
    for (n = 0 ; n < 5 ; n++)
    {
	ptr = malloc(128);
	fprintf(stderr, "malloc(128) = 0x%0x\n", ptr);
    }
    
    mi = mallinfo();
    
    fprintf(stderr, MINFO_FORMAT, 
	    mi.arena,      		/* total space in arena */               
	    mi.ordblks,   		/* number of ordinary blocks */          
	    mi.smblks,    		/* number of small blocks */             
	    mi.hblks,     		/* number of holding blocks */           
	    mi.hblkhd,    		/* space in holding block headers */     
	    mi.usmblks,   		/* space in small blocks in use */       
	    mi.fsmblks,   		/* space in free small blocks */         
	    mi.uordblks,  		/* space in ordinary blocks in use */    
	    mi.fordblks,  		/* space in free ordinary blocks */      
	    mi.keepcost  		/* cost of enabling keep option */
#if complete
	    ,
	    mi.mxfast,    		/* max size of small blocks */          
	    mi.nlblks,    		/* number of small blocks in a holding block */
	    mi.grain,     		/* small block rounding factor */
	    mi.uordbytes, 		/* space (including overhead) allocated in ord. blocks */
	    mi.allocated, 		/* number of ordinary blocks allocated */
	    mi.treeoverhead   		/* bytes used in maintaining free tree */
#endif
	    );
		
}