~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/os/os0proc.c

  • Committer: Brian Aker
  • Date: 2010-12-18 18:24:57 UTC
  • mfrom: (1999.6.3 trunk)
  • Revision ID: brian@tangent.org-20101218182457-yi1wd0so2hml1k1w
Merge in Lee's copyright header fix

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************
 
2
 
 
3
Copyright (C) 1995, 2009, Innobase Oy. All Rights Reserved.
 
4
 
 
5
This program is free software; you can redistribute it and/or modify it under
 
6
the terms of the GNU General Public License as published by the Free Software
 
7
Foundation; version 2 of the License.
 
8
 
 
9
This program is distributed in the hope that it will be useful, but WITHOUT
 
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
12
 
 
13
You should have received a copy of the GNU General Public License along with
 
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 
15
St, Fifth Floor, Boston, MA 02110-1301 USA
 
16
 
 
17
*****************************************************************************/
 
18
 
 
19
/**************************************************//**
 
20
@file os/os0proc.c
 
21
The interface to the operating system
 
22
process control primitives
 
23
 
 
24
Created 9/30/1995 Heikki Tuuri
 
25
*******************************************************/
 
26
 
 
27
#include "os0proc.h"
 
28
#ifdef UNIV_NONINL
 
29
#include "os0proc.ic"
 
30
#endif
 
31
 
 
32
#include "ut0mem.h"
 
33
#include "ut0byte.h"
 
34
#include <errno.h>
 
35
#include <unistd.h>
 
36
 
 
37
/* FreeBSD for example has only MAP_ANON, Linux has MAP_ANONYMOUS and
 
38
MAP_ANON but MAP_ANON is marked as deprecated */
 
39
#if defined(MAP_ANONYMOUS)
 
40
#define OS_MAP_ANON     MAP_ANONYMOUS
 
41
#elif defined(MAP_ANON)
 
42
#define OS_MAP_ANON     MAP_ANON
 
43
#endif
 
44
 
 
45
UNIV_INTERN ibool os_use_large_pages;
 
46
/* Large page size. This may be a boot-time option on some platforms */
 
47
UNIV_INTERN ulint os_large_page_size;
 
48
 
 
49
/****************************************************************//**
 
50
Converts the current process id to a number. It is not guaranteed that the
 
51
number is unique. In Linux returns the 'process number' of the current
 
52
thread. That number is the same as one sees in 'top', for example. In Linux
 
53
the thread id is not the same as one sees in 'top'.
 
54
@return process id as a number */
 
55
UNIV_INTERN
 
56
ulint
 
57
os_proc_get_number(void)
 
58
/*====================*/
 
59
{
 
60
#ifdef __WIN__
 
61
        return((ulint)GetCurrentProcessId());
 
62
#else
 
63
        return((ulint)getpid());
 
64
#endif
 
65
}
 
66
 
 
67
/****************************************************************//**
 
68
Allocates large pages memory.
 
69
@return allocated memory */
 
70
UNIV_INTERN
 
71
void*
 
72
os_mem_alloc_large(
 
73
/*===============*/
 
74
        ulint*  n)                      /*!< in/out: number of bytes */
 
75
{
 
76
        void*   ptr;
 
77
        ulint   size;
 
78
#if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
 
79
        int shmid;
 
80
        struct shmid_ds buf;
 
81
 
 
82
        if (!os_use_large_pages || !os_large_page_size) {
 
83
                goto skip;
 
84
        }
 
85
 
 
86
        /* Align block size to os_large_page_size */
 
87
        ut_ad(ut_is_2pow(os_large_page_size));
 
88
        size = ut_2pow_round(*n + (os_large_page_size - 1),
 
89
                             os_large_page_size);
 
90
 
 
91
        shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W);
 
92
        if (shmid < 0) {
 
93
                fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate"
 
94
                        " %lu bytes. errno %d\n", size, errno);
 
95
                ptr = NULL;
 
96
        } else {
 
97
                ptr = shmat(shmid, NULL, 0);
 
98
                if (ptr == (void *)-1) {
 
99
                        fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to"
 
100
                                " attach shared memory segment, errno %d\n",
 
101
                                errno);
 
102
                        ptr = NULL;
 
103
                }
 
104
 
 
105
                /* Remove the shared memory segment so that it will be
 
106
                automatically freed after memory is detached or
 
107
                process exits */
 
108
                shmctl(shmid, IPC_RMID, &buf);
 
109
        }
 
110
 
 
111
        if (ptr) {
 
112
                *n = size;
 
113
                os_fast_mutex_lock(&ut_list_mutex);
 
114
                ut_total_allocated_memory += size;
 
115
                os_fast_mutex_unlock(&ut_list_mutex);
 
116
# ifdef UNIV_SET_MEM_TO_ZERO
 
117
                memset(ptr, '\0', size);
 
118
# endif
 
119
                UNIV_MEM_ALLOC(ptr, size);
 
120
                return(ptr);
 
121
        }
 
122
 
 
123
        fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional"
 
124
                " memory pool\n");
 
125
skip:
 
126
#endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
 
127
 
 
128
#ifdef __WIN__
 
129
        SYSTEM_INFO     system_info;
 
130
        GetSystemInfo(&system_info);
 
131
 
 
132
        /* Align block size to system page size */
 
133
        ut_ad(ut_is_2pow(system_info.dwPageSize));
 
134
        /* system_info.dwPageSize is only 32-bit. Casting to ulint is required
 
135
        on 64-bit Windows. */
 
136
        size = *n = ut_2pow_round(*n + (system_info.dwPageSize - 1),
 
137
                                  (ulint) system_info.dwPageSize);
 
138
        ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
 
139
                           PAGE_READWRITE);
 
140
        if (!ptr) {
 
141
                fprintf(stderr, "InnoDB: VirtualAlloc(%lu bytes) failed;"
 
142
                        " Windows error %lu\n",
 
143
                        (ulong) size, (ulong) GetLastError());
 
144
        } else {
 
145
                os_fast_mutex_lock(&ut_list_mutex);
 
146
                ut_total_allocated_memory += size;
 
147
                os_fast_mutex_unlock(&ut_list_mutex);
 
148
                UNIV_MEM_ALLOC(ptr, size);
 
149
        }
 
150
#elif !defined OS_MAP_ANON
 
151
        size = *n;
 
152
        ptr = ut_malloc_low(size, TRUE, FALSE);
 
153
#else
 
154
# ifdef HAVE_GETPAGESIZE
 
155
        size = getpagesize();
 
156
# else
 
157
        size = UNIV_PAGE_SIZE;
 
158
# endif
 
159
        /* Align block size to system page size */
 
160
        ut_ad(ut_is_2pow(size));
 
161
        size = *n = ut_2pow_round(*n + (size - 1), size);
 
162
        ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
 
163
                   MAP_PRIVATE | OS_MAP_ANON, -1, 0);
 
164
        if (UNIV_UNLIKELY(ptr == (void*) -1)) {
 
165
                fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;"
 
166
                        " errno %lu\n",
 
167
                        (ulong) size, (ulong) errno);
 
168
                ptr = NULL;
 
169
        } else {
 
170
                os_fast_mutex_lock(&ut_list_mutex);
 
171
                ut_total_allocated_memory += size;
 
172
                os_fast_mutex_unlock(&ut_list_mutex);
 
173
                UNIV_MEM_ALLOC(ptr, size);
 
174
        }
 
175
#endif
 
176
        return(ptr);
 
177
}
 
178
 
 
179
/****************************************************************//**
 
180
Frees large pages memory. */
 
181
UNIV_INTERN
 
182
void
 
183
os_mem_free_large(
 
184
/*==============*/
 
185
        void    *ptr,                   /*!< in: pointer returned by
 
186
                                        os_mem_alloc_large() */
 
187
        ulint   size)                   /*!< in: size returned by
 
188
                                        os_mem_alloc_large() */
 
189
{
 
190
        os_fast_mutex_lock(&ut_list_mutex);
 
191
        ut_a(ut_total_allocated_memory >= size);
 
192
        os_fast_mutex_unlock(&ut_list_mutex);
 
193
 
 
194
#if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
 
195
        if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) {
 
196
                os_fast_mutex_lock(&ut_list_mutex);
 
197
                ut_a(ut_total_allocated_memory >= size);
 
198
                ut_total_allocated_memory -= size;
 
199
                os_fast_mutex_unlock(&ut_list_mutex);
 
200
                UNIV_MEM_FREE(ptr, size);
 
201
                return;
 
202
        }
 
203
#endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
 
204
#ifdef __WIN__
 
205
        /* When RELEASE memory, the size parameter must be 0.
 
206
        Do not use MEM_RELEASE with MEM_DECOMMIT. */
 
207
        if (!VirtualFree(ptr, 0, MEM_RELEASE)) {
 
208
                fprintf(stderr, "InnoDB: VirtualFree(%p, %lu) failed;"
 
209
                        " Windows error %lu\n",
 
210
                        ptr, (ulong) size, (ulong) GetLastError());
 
211
        } else {
 
212
                os_fast_mutex_lock(&ut_list_mutex);
 
213
                ut_a(ut_total_allocated_memory >= size);
 
214
                ut_total_allocated_memory -= size;
 
215
                os_fast_mutex_unlock(&ut_list_mutex);
 
216
                UNIV_MEM_FREE(ptr, size);
 
217
        }
 
218
#elif !defined OS_MAP_ANON
 
219
        ut_free(ptr);
 
220
#else
 
221
        if (munmap(ptr, size)) {
 
222
                fprintf(stderr, "InnoDB: munmap(%p, %lu) failed;"
 
223
                        " errno %lu\n",
 
224
                        ptr, (ulong) size, (ulong) errno);
 
225
        } else {
 
226
                os_fast_mutex_lock(&ut_list_mutex);
 
227
                ut_a(ut_total_allocated_memory >= size);
 
228
                ut_total_allocated_memory -= size;
 
229
                os_fast_mutex_unlock(&ut_list_mutex);
 
230
                UNIV_MEM_FREE(ptr, size);
 
231
        }
 
232
#endif
 
233
}