~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_largepage.c

  • Committer: Brian Aker
  • Date: 2008-07-01 07:17:30 UTC
  • Revision ID: brian@tangent.org-20080701071730-y843dzfwz1nbca79
More mysys removal

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2004 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
 
 
16
 
#include "mysys_priv.h"
17
 
 
18
 
#ifdef HAVE_LARGE_PAGES
19
 
 
20
 
#ifdef HAVE_SYS_IPC_H
21
 
#include <sys/ipc.h>
22
 
#endif
23
 
 
24
 
#ifdef HAVE_SYS_SHM_H
25
 
#include <sys/shm.h>
26
 
#endif
27
 
 
28
 
static uint my_get_large_page_size_int(void);
29
 
static uchar* my_large_malloc_int(size_t size, myf my_flags);
30
 
static my_bool my_large_free_int(uchar* ptr, myf my_flags);
31
 
 
32
 
/* Gets the size of large pages from the OS */
33
 
 
34
 
uint my_get_large_page_size(void)
35
 
{
36
 
  uint size;
37
 
  DBUG_ENTER("my_get_large_page_size");
38
 
  
39
 
  if (!(size = my_get_large_page_size_int()))
40
 
    fprintf(stderr, "Warning: Failed to determine large page size\n");
41
 
 
42
 
  DBUG_RETURN(size);
43
 
}
44
 
 
45
 
/*
46
 
  General large pages allocator.
47
 
  Tries to allocate memory from large pages pool and falls back to
48
 
  my_malloc_lock() in case of failure
49
 
*/
50
 
 
51
 
uchar* my_large_malloc(size_t size, myf my_flags)
52
 
{
53
 
  uchar* ptr;
54
 
  DBUG_ENTER("my_large_malloc");
55
 
  
56
 
  if (my_use_large_pages && my_large_page_size)
57
 
  {
58
 
    if ((ptr = my_large_malloc_int(size, my_flags)) != NULL)
59
 
        DBUG_RETURN(ptr);
60
 
    if (my_flags & MY_WME)
61
 
      fprintf(stderr, "Warning: Using conventional memory pool\n");
62
 
  }
63
 
      
64
 
  DBUG_RETURN(my_malloc_lock(size, my_flags));
65
 
}
66
 
 
67
 
/*
68
 
  General large pages deallocator.
69
 
  Tries to deallocate memory as if it was from large pages pool and falls back
70
 
  to my_free_lock() in case of failure
71
 
 */
72
 
 
73
 
void my_large_free(uchar* ptr, myf my_flags __attribute__((unused)))
74
 
{
75
 
  DBUG_ENTER("my_large_free");
76
 
  
77
 
  /*
78
 
    my_large_free_int() can only fail if ptr was not allocated with
79
 
    my_large_malloc_int(), i.e. my_malloc_lock() was used so we should free it
80
 
    with my_free_lock()
81
 
  */
82
 
  if (!my_use_large_pages || !my_large_page_size ||
83
 
      !my_large_free_int(ptr, my_flags))
84
 
    my_free_lock(ptr, my_flags);
85
 
 
86
 
  DBUG_VOID_RETURN;
87
 
}
88
 
 
89
 
#ifdef HUGETLB_USE_PROC_MEMINFO
90
 
/* Linux-specific function to determine the size of large pages */
91
 
 
92
 
uint my_get_large_page_size_int(void)
93
 
{
94
 
  FILE *f;
95
 
  uint size = 0;
96
 
  char buf[256];
97
 
  DBUG_ENTER("my_get_large_page_size_int");
98
 
 
99
 
  if (!(f = my_fopen("/proc/meminfo", O_RDONLY, MYF(MY_WME))))
100
 
    goto finish;
101
 
 
102
 
  while (fgets(buf, sizeof(buf), f))
103
 
    if (sscanf(buf, "Hugepagesize: %u kB", &size))
104
 
      break;
105
 
 
106
 
  my_fclose(f, MYF(MY_WME));
107
 
  
108
 
finish:
109
 
  DBUG_RETURN(size * 1024);
110
 
}
111
 
#endif /* HUGETLB_USE_PROC_MEMINFO */
112
 
 
113
 
#if HAVE_DECL_SHM_HUGETLB
114
 
/* Linux-specific large pages allocator  */
115
 
    
116
 
uchar* my_large_malloc_int(size_t size, myf my_flags)
117
 
{
118
 
  int shmid;
119
 
  uchar* ptr;
120
 
  struct shmid_ds buf;
121
 
  DBUG_ENTER("my_large_malloc_int");
122
 
 
123
 
  /* Align block size to my_large_page_size */
124
 
  size = ((size - 1) & ~(my_large_page_size - 1)) + my_large_page_size;
125
 
  
126
 
  shmid = shmget(IPC_PRIVATE, size, SHM_HUGETLB | SHM_R | SHM_W);
127
 
  if (shmid < 0)
128
 
  {
129
 
    if (my_flags & MY_WME)
130
 
      fprintf(stderr,
131
 
              "Warning: Failed to allocate %lu bytesx from HugeTLB memory."
132
 
              " errno %d\n", (ulong) size, errno);
133
 
 
134
 
    DBUG_RETURN(NULL);
135
 
  }
136
 
 
137
 
  ptr = (uchar*) shmat(shmid, NULL, 0);
138
 
  if (ptr == (uchar *) -1)
139
 
  {
140
 
    if (my_flags& MY_WME)
141
 
      fprintf(stderr, "Warning: Failed to attach shared memory segment,"
142
 
              " errno %d\n", errno);
143
 
    shmctl(shmid, IPC_RMID, &buf);
144
 
 
145
 
    DBUG_RETURN(NULL);
146
 
  }
147
 
 
148
 
  /*
149
 
    Remove the shared memory segment so that it will be automatically freed
150
 
    after memory is detached or process exits
151
 
  */
152
 
  shmctl(shmid, IPC_RMID, &buf);
153
 
 
154
 
  DBUG_RETURN(ptr);
155
 
}
156
 
 
157
 
/* Linux-specific large pages deallocator */
158
 
 
159
 
my_bool my_large_free_int(uchar *ptr, myf my_flags __attribute__((unused)))
160
 
{
161
 
  DBUG_ENTER("my_large_free_int");
162
 
  DBUG_RETURN(shmdt(ptr) == 0);
163
 
}
164
 
#endif /* HAVE_DECL_SHM_HUGETLB */
165
 
 
166
 
#endif /* HAVE_LARGE_PAGES */