1 | /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. |
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
15 | |
16 | /* Alloc a block of locked memory */ |
17 | |
18 | #include "mysys_priv.h" |
19 | #include "mysys_err.h" |
20 | #include <my_list.h> |
21 | |
22 | #ifdef HAVE_MLOCK |
23 | #include <sys/mman.h> |
24 | |
25 | struct st_mem_list |
26 | { |
27 | LIST list; |
28 | uchar *page; |
29 | uint size; |
30 | }; |
31 | |
32 | LIST *mem_list; |
33 | |
34 | uchar *my_malloc_lock(uint size,myf MyFlags) |
35 | { |
36 | int success; |
37 | uint pagesize=sysconf(_SC_PAGESIZE); |
38 | uchar *ptr; |
39 | struct st_mem_list *element; |
40 | DBUG_ENTER("my_malloc_lock" ); |
41 | |
42 | size=((size-1) & ~(pagesize-1))+pagesize; |
43 | if (!(ptr=memalign(pagesize,size))) |
44 | { |
45 | if (MyFlags & (MY_FAE+MY_WME)) |
46 | my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_WAITTANG+ME_FATALERROR), size); |
47 | DBUG_RETURN(0); |
48 | } |
49 | success = mlock((uchar*) ptr,size); |
50 | if (success != 0 && geteuid() == 0) |
51 | { |
52 | DBUG_PRINT("warning" ,("Failed to lock memory. errno %d\n" , |
53 | errno)); |
54 | fprintf(stderr, "Warning: Failed to lock memory. errno %d\n" , |
55 | errno); |
56 | } |
57 | else |
58 | { |
59 | /* Add block in a list for munlock */ |
60 | if (!(element=(struct st_mem_list*) my_malloc(sizeof(*element),MyFlags))) |
61 | { |
62 | (void) munlock((uchar*) ptr,size); |
63 | free(ptr); |
64 | DBUG_RETURN(0); |
65 | } |
66 | element->list.data=(uchar*) element; |
67 | element->page=ptr; |
68 | element->size=size; |
69 | mysql_mutex_lock(&THR_LOCK_malloc); |
70 | mem_list=list_add(mem_list,&element->list); |
71 | mysql_mutex_unlock(&THR_LOCK_malloc); |
72 | } |
73 | DBUG_RETURN(ptr); |
74 | } |
75 | |
76 | |
77 | void my_free_lock(uchar *ptr) |
78 | { |
79 | LIST *list; |
80 | struct st_mem_list *element=0; |
81 | |
82 | mysql_mutex_lock(&THR_LOCK_malloc); |
83 | for (list=mem_list ; list ; list=list->next) |
84 | { |
85 | element=(struct st_mem_list*) list->data; |
86 | if (ptr == element->page) |
87 | { /* Found locked mem */ |
88 | (void) munlock((uchar*) ptr,element->size); |
89 | mem_list=list_delete(mem_list,list); |
90 | break; |
91 | } |
92 | } |
93 | mysql_mutex_unlock(&THR_LOCK_malloc); |
94 | my_free(element); |
95 | free(ptr); /* Free even if not locked */ |
96 | } |
97 | |
98 | #endif /* HAVE_MLOCK */ |
99 | |