File: buffer.c

package info (click to toggle)
adios 1.3-11
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 7,376 kB
  • sloc: ansic: 48,186; sh: 9,682; cpp: 2,662; f90: 1,390; makefile: 895; python: 372; xml: 301
file content (162 lines) | stat: -rw-r--r-- 5,389 bytes parent folder | download
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;
    }
}