- total = 0;
- for (mp = maps;;)
- {
- unsigned long start, end;
-
- start = (unsigned long) mp->pr_vaddr;
- end = start + mp->pr_size;
- if (start == 0 && end == 0)
- break;
- mp++;
- if (start <= auxmap_start && auxmap_end - 1 <= end - 1)
- /* Consider [start,end-1] \ [auxmap_start,auxmap_end-1]
- = [start,auxmap_start-1] u [auxmap_end,end-1]. */
- total += (end - start) - memneed;
- else
- total += end - start;
- }
- munmap (auxmap, memneed);
- close (fd);
- return total;
-
- fail1:
- munmap (auxmap, memneed);
- fail2:
- close (fd);
- return 0;
-
-#elif defined __APPLE__ && defined __MACH__ /* MacOS X */
-
- task_t task = mach_task_self ();
- vm_address_t address;
- vm_size_t size;
- vm_address_t total = 0;
-
- for (address = VM_MIN_ADDRESS;; address += size)
- {
- int more;
- mach_port_t object_name;
- /* In MacOS X 10.5, the types vm_address_t, vm_offset_t, vm_size_t have
- 32 bits in 32-bit processes and 64 bits in 64-bit processes. Whereas
- mach_vm_address_t and mach_vm_size_t are always 64 bits large.
- MacOS X 10.5 has three vm_region like methods:
- - vm_region. It has arguments that depend on whether the current
- process is 32-bit or 64-bit. When linking dynamically, this
- function exists only in 32-bit processes. Therefore we use it only
- in 32-bit processes.
- - vm_region_64. It has arguments that depend on whether the current
- process is 32-bit or 64-bit. It interprets a flavor
- VM_REGION_BASIC_INFO as VM_REGION_BASIC_INFO_64, which is
- dangerous since 'struct vm_region_basic_info_64' is larger than
- 'struct vm_region_basic_info'; therefore let's write
- VM_REGION_BASIC_INFO_64 explicitly.
- - mach_vm_region. It has arguments that are 64-bit always. This
- function is useful when you want to access the VM of a process
- other than the current process.
- In 64-bit processes, we could use vm_region_64 or mach_vm_region.
- I choose vm_region_64 because it uses the same types as vm_region,
- resulting in less conditional code. */
-# if defined __ppc64__ || defined __x86_64__
- struct vm_region_basic_info_64 info;
- mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
-
- more = (vm_region_64 (task, &address, &size, VM_REGION_BASIC_INFO_64,
- (vm_region_info_t)&info, &info_count, &object_name)
- == KERN_SUCCESS);
-# else
- struct vm_region_basic_info info;
- mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
-
- more = (vm_region (task, &address, &size, VM_REGION_BASIC_INFO,
- (vm_region_info_t)&info, &info_count, &object_name)
- == KERN_SUCCESS);
-# endif
- if (object_name != MACH_PORT_NULL)
- mach_port_deallocate (mach_task_self (), object_name);
- if (!more)
- break;
- total += size;
- }
- return total;
-
-#elif (defined _WIN32 || defined __WIN32__) || defined __CYGWIN__
- /* Windows platform. Use the native Windows API. */
-
- MEMORY_BASIC_INFORMATION info;
- unsigned long address = 0;
- unsigned long total = 0;
-
- while (VirtualQuery ((void*)address, &info, sizeof(info)) == sizeof(info))
- {
- if (info.State != MEM_FREE)
- /* Ignore areas where info.Protect has the undocumented value 0.
- This is needed, so that on Cygwin, areas used by malloc() are
- distinguished from areas reserved for future malloc(). */
- if (info.Protect != 0)
- total += info.RegionSize;
- address = (unsigned long)info.BaseAddress + info.RegionSize;
- }
- return total;
-
-#elif defined __BEOS__
- /* Use the BeOS specific API. */
-
- area_info info;
- int32 cookie;
- unsigned long total = 0;
-
- cookie = 0;
- while (get_next_area_info (0, &cookie, &info) == B_OK)
- {
- unsigned long start, end;
-
- start = (unsigned long) info.address;
- end = start + info.size;
-
- total += end - start;
- }