]> sourceware.org Git - glibc.git/blame - sysdeps/mach/hurd/mmap.c
Update.
[glibc.git] / sysdeps / mach / hurd / mmap.c
CommitLineData
478b92f0
UD
1/* Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
28f540f4 3
478b92f0
UD
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
28f540f4 8
478b92f0
UD
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
28f540f4 13
478b92f0
UD
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
28f540f4
RM
18
19#include <sys/types.h>
20#include <sys/mman.h>
21#include <errno.h>
22#include <hurd.h>
23#include <hurd/fd.h>
24
25/* Map addresses starting near ADDR and extending for LEN bytes. from
26 OFFSET into the file FD describes according to PROT and FLAGS. If ADDR
27 is nonzero, it is the desired mapping address. If the MAP_FIXED bit is
28 set in FLAGS, the mapping will be at ADDR exactly (which must be
29 page-aligned); otherwise the system chooses a convenient nearby address.
f2ea0f5b 30 The return value is the actual mapping address chosen or (__ptr_t) -1
28f540f4
RM
31 for errors (in which case `errno' is set). A successful `mmap' call
32 deallocates any previous mapping for the affected region. */
33
f2ea0f5b
UD
34__ptr_t
35__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
28f540f4
RM
36{
37 error_t err;
38 vm_prot_t vmprot;
39 memory_object_t memobj;
40 vm_address_t mapaddr;
65bf5fa3
RM
41 vm_size_t pageoff;
42
43 pageoff = offset & (vm_page_size - 1);
44 offset &= ~(vm_page_size - 1);
45
46 mapaddr = (vm_address_t) addr;
47 if (flags & MAP_FIXED)
48 {
49 /* A specific address is requested. It need not be page-aligned;
50 it just needs to be congruent with the object offset. */
51 if ((mapaddr & (vm_page_size - 1)) != pageoff)
f2ea0f5b 52 return (__ptr_t) (long int) __hurd_fail (EINVAL);
65bf5fa3
RM
53 else
54 /* We will add back PAGEOFF after mapping. */
55 mapaddr -= pageoff;
56 }
28f540f4
RM
57
58 vmprot = VM_PROT_NONE;
59 if (prot & PROT_READ)
60 vmprot |= VM_PROT_READ;
61 if (prot & PROT_WRITE)
62 vmprot |= VM_PROT_WRITE;
63 if (prot & PROT_EXEC)
64 vmprot |= VM_PROT_EXECUTE;
65
66 switch (flags & MAP_TYPE)
67 {
68 default:
f2ea0f5b 69 return (__ptr_t) (long int) __hurd_fail (EINVAL);
28f540f4
RM
70
71 case MAP_ANON:
72 memobj = MACH_PORT_NULL;
73 break;
74
75 case MAP_FILE:
7752137a 76 case 0: /* Allow, e.g., just MAP_SHARED. */
28f540f4
RM
77 {
78 mach_port_t robj, wobj;
79 if (err = HURD_DPORT_USE (fd, __io_map (port, &robj, &wobj)))
f2ea0f5b 80 return (__ptr_t) (long int) __hurd_dfail (fd, err);
28f540f4
RM
81 switch (prot & (PROT_READ|PROT_WRITE))
82 {
83 case PROT_READ:
84 memobj = robj;
1a3a58fd
RM
85 if (wobj != MACH_PORT_NULL)
86 __mach_port_deallocate (__mach_task_self (), wobj);
28f540f4
RM
87 break;
88 case PROT_WRITE:
89 memobj = wobj;
1a3a58fd
RM
90 if (robj != MACH_PORT_NULL)
91 __mach_port_deallocate (__mach_task_self (), robj);
28f540f4
RM
92 break;
93 case PROT_READ|PROT_WRITE:
28f540f4 94 if (robj == wobj)
1a3a58fd
RM
95 {
96 memobj = wobj;
97 /* Remove extra reference. */
98 __mach_port_deallocate (__mach_task_self (), memobj);
99 }
100 else if (wobj == MACH_PORT_NULL && /* Not writable by mapping. */
907a1bac 101 !(flags & MAP_SHARED))
1a3a58fd
RM
102 /* The file can only be mapped for reading. Since we are
103 making a private mapping, we will never try to write the
104 object anyway, so we don't care. */
105 memobj = robj;
28f540f4
RM
106 else
107 {
108 __mach_port_deallocate (__mach_task_self (), wobj);
f2ea0f5b 109 return (__ptr_t) (long int) __hurd_fail (EACCES);
28f540f4
RM
110 }
111 break;
112 }
113 break;
114 /* XXX handle MAP_NOEXTEND */
115 }
116 }
117
65bf5fa3
RM
118 /* XXX handle MAP_INHERIT */
119
28f540f4
RM
120 err = __vm_map (__mach_task_self (),
121 &mapaddr, (vm_size_t) len, (vm_address_t) 0,
7752137a 122 ! (flags & MAP_FIXED),
28f540f4 123 memobj, (vm_offset_t) offset,
65bf5fa3 124 ! (flags & MAP_SHARED),
28f540f4 125 vmprot, VM_PROT_ALL,
65bf5fa3
RM
126 (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY);
127
787e4db9
RM
128 if (err == KERN_NO_SPACE && (flags & MAP_FIXED))
129 {
130 /* XXX this is not atomic as it is in unix! */
131 /* The region is already allocated; deallocate it first. */
132 err = __vm_deallocate (__mach_task_self (), mapaddr, len);
133 if (! err)
134 err = __vm_map (__mach_task_self (),
135 &mapaddr, (vm_size_t) len, (vm_address_t) 0,
136 0, memobj, (vm_offset_t) offset,
f36f8dcf 137 ! (flags & MAP_SHARED),
787e4db9 138 vmprot, VM_PROT_ALL,
f36f8dcf
RM
139 (flags & MAP_SHARED) ? VM_INHERIT_SHARE
140 : VM_INHERIT_COPY);
787e4db9 141 }
28f540f4
RM
142
143 if (memobj != MACH_PORT_NULL)
144 __mach_port_deallocate (__mach_task_self (), memobj);
145
65bf5fa3 146 if (err)
f2ea0f5b 147 return (__ptr_t) (long int) __hurd_fail (err);
65bf5fa3
RM
148
149 /* Adjust the mapping address for the offset-within-page. */
150 mapaddr += pageoff;
151
f2ea0f5b 152 return (__ptr_t) mapaddr;
28f540f4 153}
6408bdde
RM
154
155weak_alias (__mmap, mmap)
This page took 0.087267 seconds and 5 git commands to generate.