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
msync(void * addr,size_t length,int flags)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