~percona-dev/percona-innodb-plugin/percona-innodb-1.0

« back to all changes in this revision

Viewing changes to os/os0proc.c

  • Committer: Vadim Tkachenko
  • Date: 2008-12-01 02:05:57 UTC
  • Revision ID: vadim@percona.com-20081201020557-p7k2m94mjtdg1a83
New rw-locks

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
The interface to the operating system
 
3
process control primitives
 
4
 
 
5
(c) 1995 Innobase Oy
 
6
 
 
7
Created 9/30/1995 Heikki Tuuri
 
8
*******************************************************/
 
9
 
 
10
#include "os0proc.h"
 
11
#ifdef UNIV_NONINL
 
12
#include "os0proc.ic"
 
13
#endif
 
14
 
 
15
#include "ut0mem.h"
 
16
#include "ut0byte.h"
 
17
 
 
18
/* FreeBSD for example has only MAP_ANON, Linux has MAP_ANONYMOUS and
 
19
MAP_ANON but MAP_ANON is marked as deprecated */
 
20
#if defined(MAP_ANONYMOUS)
 
21
#define OS_MAP_ANON     MAP_ANONYMOUS
 
22
#elif defined(MAP_ANON)
 
23
#define OS_MAP_ANON     MAP_ANON
 
24
#endif
 
25
 
 
26
UNIV_INTERN ibool os_use_large_pages;
 
27
/* Large page size. This may be a boot-time option on some platforms */
 
28
UNIV_INTERN ulint os_large_page_size;
 
29
 
 
30
/********************************************************************
 
31
Converts the current process id to a number. It is not guaranteed that the
 
32
number is unique. In Linux returns the 'process number' of the current
 
33
thread. That number is the same as one sees in 'top', for example. In Linux
 
34
the thread id is not the same as one sees in 'top'. */
 
35
UNIV_INTERN
 
36
ulint
 
37
os_proc_get_number(void)
 
38
/*====================*/
 
39
{
 
40
#ifdef __WIN__
 
41
        return((ulint)GetCurrentProcessId());
 
42
#else
 
43
        return((ulint)getpid());
 
44
#endif
 
45
}
 
46
 
 
47
/********************************************************************
 
48
Allocates non-cacheable memory. */
 
49
UNIV_INTERN
 
50
void*
 
51
os_mem_alloc_nocache(
 
52
/*=================*/
 
53
                        /* out: allocated memory */
 
54
        ulint   n)      /* in: number of bytes */
 
55
{
 
56
#ifdef __WIN__
 
57
        void*   ptr;
 
58
 
 
59
        ptr = VirtualAlloc(NULL, n, MEM_COMMIT,
 
60
                           PAGE_READWRITE | PAGE_NOCACHE);
 
61
        ut_a(ptr);
 
62
 
 
63
        return(ptr);
 
64
#else
 
65
        return(ut_malloc(n));
 
66
#endif
 
67
}
 
68
 
 
69
/********************************************************************
 
70
Allocates large pages memory. */
 
71
UNIV_INTERN
 
72
void*
 
73
os_mem_alloc_large(
 
74
/*===============*/
 
75
                                        /* out: allocated memory */
 
76
        ulint*  n)                      /* in/out: number of bytes */
 
77
{
 
78
        void*   ptr;
 
79
        ulint   size;
 
80
#if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
 
81
        int shmid;
 
82
        struct shmid_ds buf;
 
83
 
 
84
        if (!os_use_large_pages || !os_large_page_size) {
 
85
                goto skip;
 
86
        }
 
87
 
 
88
        /* Align block size to os_large_page_size */
 
89
        ut_ad(ut_is_2pow(os_large_page_size));
 
90
        size = ut_2pow_round(*n + (os_large_page_size - 1),
 
91
                             os_large_page_size);
 
92
 
 
93
        shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W);
 
94
        if (shmid < 0) {
 
95
                fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate"
 
96
                        " %lu bytes. errno %d\n", size, errno);
 
97
                ptr = NULL;
 
98
        } else {
 
99
                ptr = shmat(shmid, NULL, 0);
 
100
                if (ptr == (void *)-1) {
 
101
                        fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to"
 
102
                                " attach shared memory segment, errno %d\n",
 
103
                                errno);
 
104
                }
 
105
 
 
106
                /* Remove the shared memory segment so that it will be
 
107
                automatically freed after memory is detached or
 
108
                process exits */
 
109
                shmctl(shmid, IPC_RMID, &buf);
 
110
        }
 
111
 
 
112
        if (ptr) {
 
113
                *n = size;
 
114
                ut_total_allocated_memory += size;
 
115
# ifdef UNIV_SET_MEM_TO_ZERO
 
116
                memset(ptr, '\0', size);
 
117
# endif
 
118
                return(ptr);
 
119
        }
 
120
 
 
121
        fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional"
 
122
                " memory pool\n");
 
123
skip:
 
124
#endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
 
125
 
 
126
#ifdef __WIN__
 
127
        SYSTEM_INFO     system_info;
 
128
        GetSystemInfo(&system_info);
 
129
 
 
130
        /* Align block size to system page size */
 
131
        ut_ad(ut_is_2pow(system_info.dwPageSize));
 
132
        size = *n = ut_2pow_round(*n + (system_info.dwPageSize - 1),
 
133
                                  system_info.dwPageSize);
 
134
        ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
 
135
                           PAGE_READWRITE);
 
136
        if (!ptr) {
 
137
                fprintf(stderr, "InnoDB: VirtualAlloc(%lu bytes) failed;"
 
138
                        " Windows error %lu\n",
 
139
                        (ulong) size, (ulong) GetLastError());
 
140
        } else {
 
141
                ut_total_allocated_memory += size;
 
142
        }
 
143
#elif defined __NETWARE__ || !defined OS_MAP_ANON
 
144
        size = *n;
 
145
        ptr = ut_malloc_low(size, TRUE, FALSE);
 
146
#else
 
147
# ifdef HAVE_GETPAGESIZE
 
148
        size = getpagesize();
 
149
# else
 
150
        size = UNIV_PAGE_SIZE;
 
151
# endif
 
152
        /* Align block size to system page size */
 
153
        ut_ad(ut_is_2pow(size));
 
154
        size = *n = ut_2pow_round(*n + (size - 1), size);
 
155
        ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
 
156
                   MAP_PRIVATE | OS_MAP_ANON, -1, 0);
 
157
        if (UNIV_UNLIKELY(ptr == (void*) -1)) {
 
158
                fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;"
 
159
                        " errno %lu\n",
 
160
                        (ulong) size, (ulong) errno);
 
161
                ptr = NULL;
 
162
        } else {
 
163
                ut_total_allocated_memory += size;
 
164
        }
 
165
#endif
 
166
        return(ptr);
 
167
}
 
168
 
 
169
/********************************************************************
 
170
Frees large pages memory. */
 
171
UNIV_INTERN
 
172
void
 
173
os_mem_free_large(
 
174
/*==============*/
 
175
        void    *ptr,                   /* in: pointer returned by
 
176
                                        os_mem_alloc_large() */
 
177
        ulint   size)                   /* in: size returned by
 
178
                                        os_mem_alloc_large() */
 
179
{
 
180
        ut_a(ut_total_allocated_memory >= size);
 
181
 
 
182
#if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
 
183
        if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) {
 
184
                ut_total_allocated_memory -= size;
 
185
                return;
 
186
        }
 
187
#endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
 
188
#ifdef __WIN__
 
189
        if (!VirtualFree(ptr, size, MEM_DECOMMIT | MEM_RELEASE)) {
 
190
                fprintf(stderr, "InnoDB: VirtualFree(%p, %lu) failed;"
 
191
                        " Windows error %lu\n",
 
192
                        ptr, (ulong) size, (ulong) GetLastError());
 
193
        } else {
 
194
                ut_total_allocated_memory -= size;
 
195
        }
 
196
#elif defined __NETWARE__ || !defined OS_MAP_ANON
 
197
        ut_free(ptr);
 
198
#else
 
199
        if (munmap(ptr, size)) {
 
200
                fprintf(stderr, "InnoDB: munmap(%p, %lu) failed;"
 
201
                        " errno %lu\n",
 
202
                        ptr, (ulong) size, (ulong) errno);
 
203
        } else {
 
204
                ut_total_allocated_memory -= size;
 
205
        }
 
206
#endif
 
207
}
 
208
 
 
209
/********************************************************************
 
210
Sets the priority boost for threads released from waiting within the current
 
211
process. */
 
212
UNIV_INTERN
 
213
void
 
214
os_process_set_priority_boost(
 
215
/*==========================*/
 
216
        ibool   do_boost)       /* in: TRUE if priority boost should be done,
 
217
                                FALSE if not */
 
218
{
 
219
#ifdef __WIN__
 
220
        ibool   no_boost;
 
221
 
 
222
        if (do_boost) {
 
223
                no_boost = FALSE;
 
224
        } else {
 
225
                no_boost = TRUE;
 
226
        }
 
227
 
 
228
#if TRUE != 1
 
229
# error "TRUE != 1"
 
230
#endif
 
231
 
 
232
        /* Does not do anything currently!
 
233
        SetProcessPriorityBoost(GetCurrentProcess(), no_boost);
 
234
        */
 
235
        fputs("Warning: process priority boost setting"
 
236
              " currently not functional!\n",
 
237
              stderr);
 
238
#else
 
239
        UT_NOT_USED(do_boost);
 
240
#endif
 
241
}