1 | /* msync -- Synchronize mapped memory to external storage. Mach version. |
2 | Copyright (C) 2002-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <sys/types.h> |
20 | #include <sys/mman.h> |
21 | #include <errno.h> |
22 | #include <sysdep-cancel.h> |
23 | |
24 | #include <hurd/hurd.h> |
25 | |
26 | /* Synchronize the region starting at ADDR and extending LEN bytes with the |
27 | file it maps. Filesystem operations on a file being mapped are |
28 | unpredictable before this is done. */ |
29 | |
30 | int |
31 | msync (void *addr, size_t length, int flags) |
32 | { |
33 | boolean_t should_flush = flags & MS_INVALIDATE ? 1 : 0; |
34 | boolean_t should_iosync = flags & MS_ASYNC ? 0 : 1; |
35 | |
36 | vm_address_t cur = (vm_address_t) addr; |
37 | vm_address_t target = cur + length; |
38 | |
39 | vm_size_t len; |
40 | vm_prot_t prot; |
41 | vm_prot_t max_prot; |
42 | vm_inherit_t inherit; |
43 | boolean_t shared; |
44 | memory_object_name_t obj; |
45 | vm_offset_t offset; |
46 | |
47 | kern_return_t err; |
48 | int cancel_oldtype; |
49 | |
50 | while (cur < target) |
51 | { |
52 | vm_address_t begin = cur; |
53 | |
54 | err = __vm_region (__mach_task_self (), |
55 | &begin, &len, &prot, &max_prot, &inherit, |
56 | &shared, &obj, &offset); |
57 | |
58 | if (err != KERN_SUCCESS) |
59 | return __hurd_fail (err); |
60 | |
61 | if (begin > cur) |
62 | /* We were given an address before the first region, |
63 | or we found a hole. */ |
64 | cur = begin; |
65 | |
66 | if (cur >= target) |
67 | /* We were given an ending address within a hole. */ |
68 | break; |
69 | |
70 | if (MACH_PORT_VALID (obj)) |
71 | { |
72 | vm_size_t sync_len; |
73 | |
74 | if (begin + len > target) |
75 | sync_len = target - begin; |
76 | else |
77 | sync_len = len; |
78 | |
79 | cancel_oldtype = LIBC_CANCEL_ASYNC(); |
80 | err = __vm_object_sync (obj, cur - begin + offset, sync_len, |
81 | should_flush, 1, should_iosync); |
82 | LIBC_CANCEL_RESET (cancel_oldtype); |
83 | __mach_port_deallocate (__mach_task_self (), obj); |
84 | |
85 | if (err) |
86 | return __hurd_fail (err); |
87 | |
88 | } |
89 | |
90 | cur = begin + len; |
91 | } |
92 | |
93 | return 0; |
94 | } |
95 | |