1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
/*
* ADIOS is freely available under the terms of the BSD license described
* in the COPYING file in the top level directory of this source distribution.
*
* Copyright (c) 2008 - 2009. UT-BATTELLE, LLC. All rights reserved.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h> /* _SC_PAGE_SIZE, _SC_AVPHYS_PAGES */
#if defined(__APPLE__)
# include <mach/mach.h>
#endif
#include "buffer.h"
// buffer sizing may be problematic. To get a more accurate picture, check:
// http://chandrashekar.info/vault/linux-system-programs.html
static uint64_t adios_buffer_size_requested = 0;
static uint64_t adios_buffer_size_max = 0;
static uint64_t adios_buffer_size_remaining = 0;
static int adios_buffer_alloc_percentage = 0; // 1 = yes, 0 = no
static enum ADIOS_BUFFER_ALLOC_WHEN adios_buffer_alloc_when = ADIOS_BUFFER_ALLOC_UNKNOWN;
void adios_buffer_size_requested_set (uint64_t v) { adios_buffer_size_requested = v; }
uint64_t adios_buffer_size_requested_get (void) { return adios_buffer_size_requested; }
void adios_buffer_size_max_set (uint64_t v) { adios_buffer_size_max = v; }
void adios_buffer_size_remaining_set (uint64_t v) { adios_buffer_size_remaining = v; }
void adios_buffer_alloc_percentage_set (int v) { adios_buffer_alloc_percentage = v; }
void adios_buffer_alloc_when_set (enum ADIOS_BUFFER_ALLOC_WHEN v) { adios_buffer_alloc_when = v; }
enum ADIOS_BUFFER_ALLOC_WHEN adios_buffer_alloc_when_get (void) { return adios_buffer_alloc_when; }
#if defined (__APPLE__)
// See e.g. http://www.opensource.apple.com/source/system_cmds/system_cmds-496/vm_stat.tproj/vm_stat.c
// for the code for the vm_stat command.
// http://www.opensource.apple.com/source/xnu/xnu-792.6.61/osfmk/man/host_statistics.html?txt
// describes the host_statistics function
// Added by Dorian Krause <dorian.krause@usi.ch>
static inline size_t adios_get_avphys_pages ()
{
// Since we are only interested in the number of free pages
// it is fine to work with the "older" host_statistics()
// instead of host_statistics64(). The advantage is that the
// first function is also provided on older (e.g., Mac OS X 10.5)
// systems
vm_statistics_data_t host_info;
mach_msg_type_number_t host_info_outCnt;
// See mach/host_info.h
host_info_outCnt = HOST_VM_INFO_COUNT;
if (host_statistics(mach_host_self(),
HOST_VM_INFO,
(host_info_t)&host_info,
&host_info_outCnt) != KERN_SUCCESS ) {
fprintf (stderr, "adios_get_avphys_pages (): host_statistics failed.\n");
return 0; // Best we can do
}
// on Mac OSX 10.4 (Tiger), there is no speculative page counting
// VM_PAGE_QUERY_PAGE_SPECULATIVE is defined in 10.5's mach/vm_statistics.h (included in mach.h)
# if defined (VM_PAGE_QUERY_PAGE_SPECULATIVE)
return host_info.free_count - host_info.speculative_count;
# else
return host_info.free_count;
# endif
}
#else
// See e.g. http://chandrashekar.info/vault/linux-system-programs.html
static inline size_t adios_get_avphys_pages ()
{
return sysconf (_SC_AVPHYS_PAGES);
}
#endif
int adios_set_buffer_size ()
{
if (!adios_buffer_size_max) // not called before
{
long pagesize;
long pages;
pagesize = sysconf (_SC_PAGE_SIZE);
pages = adios_get_avphys_pages ();
if (adios_buffer_alloc_percentage)
{
adios_buffer_size_max = (pages * pagesize / 100.0)
* adios_buffer_size_requested;
}
else
{
if (pagesize * pages >= adios_buffer_size_requested)
{
// sufficient memory, do nothing
adios_buffer_size_max = adios_buffer_size_requested;
}
else
{
fprintf (stderr, "adios_allocate_buffer (): insufficient memory: "
"%llu requested, %llu available. Using "
"available.\n"
,adios_buffer_size_requested
,(uint64_t)(((uint64_t) pagesize) * pages)
);
adios_buffer_size_max = (uint64_t)((uint64_t) pagesize) * pages;
}
}
adios_buffer_size_remaining = adios_buffer_size_max;
return 1;
}
else
{
fprintf (stderr, "adios_allocate_buffer already called. "
"No changes made.\n"
);
return 0;
}
}
uint64_t adios_method_buffer_alloc (uint64_t size)
{
if (adios_buffer_size_remaining >= size)
{
adios_buffer_size_remaining -= size;
return size;
}
else
{
uint64_t remaining = adios_buffer_size_remaining;
adios_buffer_size_remaining = 0;
return remaining;
}
}
int adios_method_buffer_free (uint64_t size)
{
if (size + adios_buffer_size_remaining > adios_buffer_size_max)
{
fprintf (stderr, "ERROR: attempt to return more bytes to buffer "
"pool than were originally available\n"
);
adios_buffer_size_remaining = adios_buffer_size_max;
return 0;
}
else
{
adios_buffer_size_remaining += size;
return 1;
}
}
|