1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
4 * University Research and Technology
5 * Corporation. All rights reserved.
6 * Copyright (c) 2004-2005 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
10 * University of Stuttgart. All rights reserved.
11 * Copyright (c) 2004-2005 The Regents of the University of California.
12 * All rights reserved.
13 * Copyright (c) 2007-2011 Oracle and/or its affiliates. All rights reserved.
14 * Copyright (c) 2009-2011 Cisco Systems, Inc. All rights reserved.
15 * Copyright (c) 2015-2016 Los Alamos National Security, LLC. All rights
16 * reserved.
17 * Copyright (c) 2016 Research Organization for Information Science
18 * and Technology (RIST). All rights reserved.
19 * $COPYRIGHT$
20 *
21 * Additional copyrights may follow
22 *
23 * $HEADER$
24 */
25
26 #include "opal_config.h"
27 #include "opal/mca/memory/memory.h"
28 #include "opal/mca/memory/base/empty.h"
29 #include "opal/memoryhooks/memory_internal.h"
30 #include "opal/constants.h"
31
32 #include <sys/types.h>
33 #include <stdlib.h>
34 #include <sys/mman.h>
35 #include <dlfcn.h>
36 #if defined(HAVE___MUNMAP)
37 /* here so we only include others if we absolutely have to */
38 #elif defined(HAVE_SYSCALL)
39 #include <sys/syscall.h>
40 #include <unistd.h>
41 #endif
42
43
44 #if defined(HAVE___MUNMAP)
45 int __munmap(caddr_t addr, size_t len);
46 #endif
47
48 static int opal_memory_malloc_open(void);
49 static int opal_memory_malloc_query(int *);
50
51 const opal_memory_base_component_2_0_0_t mca_memory_malloc_solaris_component = {
52 /* First, the mca_component_t struct containing meta information
53 about the component itself */
54 .memoryc_version = {
55 OPAL_MEMORY_BASE_VERSION_2_0_0,
56
57 /* Component name and version */
58 .mca_component_name = "malloc_solaris",
59 MCA_BASE_MAKE_VERSION(component, OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION,
60 OPAL_RELEASE_VERSION),
61
62 /* Component open and close functions */
63 .mca_open_component = opal_memory_malloc_open,
64 },
65 .memoryc_data = {
66 /* The component is checkpoint ready */
67 MCA_BASE_METADATA_PARAM_CHECKPOINT
68 },
69
70 /* This component doesn't need these functions, but need to
71 provide safe/empty register/deregister functions to call */
72 .memoryc_query = opal_memory_malloc_query,
73 .memoryc_register = opal_memory_base_component_register_empty,
74 .memoryc_deregister = opal_memory_base_component_deregister_empty,
75 .memoryc_set_alignment = opal_memory_base_component_set_alignment_empty,
76 };
77
78 /*
79 * This component exists to establish the memory hook support
80 * level available on Solaris. By default Solaris does not
81 * return memory to the system, i.e. does not unmap memory
82 * from the process space, when a user calls free(). This allows
83 * us to declare OPAL_MEMORY_FREE_SUPPORT. Additionally, by
84 * intercepting munmap we can declare OPAL_MEMORY_MUNMAP_SUPPORT.
85 *
86 * NOTE: Not releasing memory back to the system when calling
87 * free() may be unique to Solaris which is why this component
88 * was created.
89 */
90 static int
91 opal_memory_malloc_open(void)
92 {
93 opal_mem_hooks_set_support(
94 (OPAL_MEMORY_FREE_SUPPORT | OPAL_MEMORY_MUNMAP_SUPPORT));
95 return OPAL_SUCCESS;
96 }
97
98 static int opal_memory_malloc_query (int *priority)
99 {
100 *priority = 79;
101 return OPAL_SUCCESS;
102 }
103
104 /*
105 * Three ways to call munmap. Prefered is to call __munmap, which
106 * will exist if munmap is a weak symbol. If not available next try
107 * the syscall, and if that doesn't work, try looking in the dynamic
108 * libc.
109 */
110 #if USE_SOLARIS_LEGACY_MUNMAP_PROTOTYPE
111 /* We are compiling using S10 so use its munmap prototype */
112 int
113 munmap(caddr_t addr, size_t len)
114 #else
115 /* From S11 on forward munmap's addr is void * */
116 int
117 munmap(void *addr, size_t len)
118 #endif
119 {
120 #if !defined(HAVE___MUNMAP) && \
121 !defined(HAVE_SYSCALL) && defined(HAVE_DLSYM)
122 static int (*realmunmap)(void*, size_t);
123 #endif
124
125 opal_mem_hooks_release_hook(addr, len, 0);
126
127 #if defined(HAVE___MUNMAP)
128 return __munmap(addr, len);
129 #elif defined(HAVE_SYSCALL)
130 return syscall(SYS_munmap, addr, len);
131 #elif defined(HAVE_DLSYM)
132 if (NULL == realmunmap) {
133 union {
134 int (*munmap_fp)(void*, size_t);
135 void *munmap_p;
136 } tmp;
137
138 tmp.munmap_p = dlsym(RTLD_NEXT, "munmap");
139 realmunmap = tmp.munmap_fp;
140 }
141 return realmunmap(addr, len);
142 #else
143 #error "Can not determine how to call munmap"
144 #endif
145 }