1 /* 2 * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include "namespace.h" 36 #include <sys/cdefs.h> 37 #include <sys/types.h> 38 #include <sys/syscall.h> 39 #include <sys/upmap.h> 40 #include <sys/time.h> 41 #include <sys/mman.h> 42 #include <sys/fcntl.h> 43 #include <errno.h> 44 #include <stdio.h> 45 #include <unistd.h> 46 #include <time.h> 47 #include <pthread.h> 48 #include "un-namespace.h" 49 #include "libc_private.h" 50 #include "upmap.h" 51 52 static pthread_mutex_t ukpmap_lock; 53 static ukpheader_t *kpmap_headers; 54 static ukpheader_t *upmap_headers; 55 static int kpmap_ok; 56 static int upmap_ok; 57 58 /* 59 * Map the requested data item from the user-kernel global shared mmap 60 * 61 * *state is set to -1 on failure, else it is left alone. 62 * *datap is set to a pointer to the item on success, else it is left alone. 63 * If type == 0 this function finalizes state, setting it to 1 if it is 0. 64 */ 65 void 66 __kpmap_map(void *datap, int *state, uint16_t type) 67 { 68 ukpheader_t *head; 69 70 if (__isthreaded) 71 _pthread_mutex_lock(&ukpmap_lock); 72 73 if (kpmap_ok <= 0) { 74 int fd; 75 76 if (kpmap_ok < 0) 77 goto failed; 78 fd = _open("/dev/kpmap", O_RDONLY); 79 if (fd < 0) { 80 kpmap_ok = -1; 81 goto failed; 82 } 83 kpmap_headers = mmap(NULL, KPMAP_MAPSIZE, 84 PROT_READ, MAP_SHARED, 85 fd, 0); 86 _close(fd); 87 if ((void *)kpmap_headers == MAP_FAILED) { 88 kpmap_ok = -1; 89 goto failed; 90 } 91 kpmap_ok = 1; 92 } 93 94 /* 95 * Special case to finalize state 96 */ 97 if (type == 0) { 98 if (*state == 0) 99 *state = 1; 100 if (__isthreaded) 101 _pthread_mutex_unlock(&ukpmap_lock); 102 return; 103 } 104 105 /* 106 * Look for type. 107 */ 108 for (head = kpmap_headers; head->type; ++head) { 109 if (head->type == type) { 110 *(void **)datap = (char *)kpmap_headers + head->offset; 111 if (__isthreaded) 112 _pthread_mutex_unlock(&ukpmap_lock); 113 return; 114 } 115 } 116 failed: 117 *state = -1; 118 if (__isthreaded) 119 _pthread_mutex_unlock(&ukpmap_lock); 120 } 121 122 /* 123 * Map the requested data item from the user-kernel per-process shared mmap 124 * 125 * *state is set to -1 on failure, else it is left alone. 126 * *datap is set to a pointer to the item on success, else it is left alone. 127 * If type == 0 this function finalizes state, setting it to 1 if it is 0. 128 */ 129 void 130 __upmap_map(void *datap, int *state, uint16_t type) 131 { 132 ukpheader_t *head; 133 134 if (__isthreaded) 135 _pthread_mutex_lock(&ukpmap_lock); 136 137 if (upmap_ok <= 0) { 138 int fd; 139 140 if (upmap_ok < 0) 141 goto failed; 142 fd = _open("/dev/upmap", O_RDWR); 143 if (fd < 0) { 144 upmap_ok = -1; 145 goto failed; 146 } 147 upmap_headers = mmap(NULL, UPMAP_MAPSIZE, 148 PROT_READ | PROT_WRITE, MAP_SHARED, 149 fd, 0); 150 _close(fd); 151 if ((void *)upmap_headers == MAP_FAILED) { 152 upmap_ok = -1; 153 goto failed; 154 } 155 upmap_ok = 1; 156 } 157 158 /* 159 * Special case to finalize state 160 */ 161 if (type == 0) { 162 if (*state == 0) 163 *state = 1; 164 if (__isthreaded) 165 _pthread_mutex_unlock(&ukpmap_lock); 166 return; 167 } 168 169 /* 170 * Look for type. 171 */ 172 for (head = upmap_headers; head->type; ++head) { 173 if (head->type == type) { 174 *(void **)datap = (char *)upmap_headers + head->offset; 175 if (__isthreaded) 176 _pthread_mutex_unlock(&ukpmap_lock); 177 return; 178 } 179 } 180 failed: 181 *state = -1; 182 if (__isthreaded) 183 _pthread_mutex_unlock(&ukpmap_lock); 184 } 185