ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/vm_alloc.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/vm_alloc.cpp (file contents):
Revision 1.28 by gbeauche, 2008-01-12T21:43:02Z vs.
Revision 1.29 by gbeauche, 2008-01-16T22:36:35Z

# Line 188 | Line 188 | void * vm_acquire(size_t size, int optio
188          if (options & VM_MAP_FIXED)
189                  return VM_MAP_FAILED;
190  
191 + #ifndef HAVE_VM_WRITE_WATCH
192 +        if (options & VM_MAP_WRITE_WATCH)
193 +                return VM_MAP_FAILED;
194 + #endif
195 +
196   #ifdef HAVE_MACH_VM
197          // vm_allocate() returns a zero-filled memory region
198          if (vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, TRUE) != KERN_SUCCESS)
# Line 207 | Line 212 | void * vm_acquire(size_t size, int optio
212          next_address = (char *)addr + size;
213   #else
214   #ifdef HAVE_WIN32_VM
215 <        if ((addr = VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == NULL)
215 >        int alloc_type = MEM_RESERVE | MEM_COMMIT;
216 >        if (options & VM_MAP_WRITE_WATCH)
217 >          alloc_type |= MEM_WRITE_WATCH;
218 >
219 >        if ((addr = VirtualAlloc(NULL, size, alloc_type, PAGE_EXECUTE_READWRITE)) == NULL)
220                  return VM_MAP_FAILED;
221   #else
222          if ((addr = calloc(size, 1)) == 0)
# Line 236 | Line 245 | int vm_acquire_fixed(void * addr, size_t
245          if (options & VM_MAP_SHARED)
246                  return -1;
247  
248 + #ifndef HAVE_VM_WRITE_WATCH
249 +        if (options & VM_MAP_WRITE_WATCH)
250 +                return -1;
251 + #endif
252 +
253   #ifdef HAVE_MACH_VM
254          // vm_allocate() returns a zero-filled memory region
255          if (vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, 0) != KERN_SUCCESS)
# Line 253 | Line 267 | int vm_acquire_fixed(void * addr, size_t
267          if (addr == NULL)
268                  return -1;
269  
270 +        int alloc_type = MEM_RESERVE | MEM_COMMIT;
271 +        if (options & VM_MAP_WRITE_WATCH)
272 +          alloc_type |= MEM_WRITE_WATCH;
273 +
274          // Allocate a possibly offset region to align on 64K boundaries
275          LPVOID req_addr = align_addr_segment(addr);
276          DWORD  req_size = align_size_segment(addr, size);
277 <        LPVOID ret_addr = VirtualAlloc(req_addr, req_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
277 >        LPVOID ret_addr = VirtualAlloc(req_addr, req_size, alloc_type, PAGE_EXECUTE_READWRITE);
278          if (ret_addr != req_addr)
279                  return -1;
280   #else
# Line 328 | Line 346 | int vm_protect(void * addr, size_t size,
346   #endif
347   }
348  
349 + /* Return the addresses of the pages that got modified in the
350 +   specified range [ ADDR, ADDR + SIZE [ since the last reset of the watch
351 +   bits. Returns 0 if successful, -1 for errors.  */
352 +
353 + int vm_get_write_watch(void * addr, size_t size,
354 +                                           void ** pages, unsigned int * n_pages,
355 +                                           int options)
356 + {
357 + #ifdef HAVE_VM_WRITE_WATCH
358 + #ifdef HAVE_WIN32_VM
359 +        DWORD flags = 0;
360 +        if (options & VM_WRITE_WATCH_RESET)
361 +                flags |= WRITE_WATCH_FLAG_RESET;
362 +
363 +        ULONG page_size;
364 +        ULONG count = *n_pages;
365 +        int ret_code = GetWriteWatch(flags, addr, size, pages, &count, &page_size);
366 +        if (ret_code != 0)
367 +                return -1;
368 +
369 +        *n_pages = count;
370 +        return 0;
371 + #endif
372 + #endif
373 +        // Unsupported
374 +        return -1;
375 + }
376 +
377 + /* Reset the write-tracking state for the specified range [ ADDR, ADDR
378 +   + SIZE [. Returns 0 if successful, -1 for errors.  */
379 +
380 + int vm_reset_write_watch(void * addr, size_t size)
381 + {
382 + #ifdef HAVE_VM_WRITE_WATCH
383 + #ifdef HAVE_WIN32_VM
384 +        int ret_code = ResetWriteWatch(addr, size);
385 +        return ret_code == 0 ? 0 : -1;
386 + #endif
387 + #endif
388 +        // Unsupported
389 +        return -1;
390 + }
391 +
392   /* Returns the size of a page.  */
393  
394   int vm_get_page_size(void)
# Line 345 | Line 406 | int vm_get_page_size(void)
406   #endif
407   }
408  
409 + #ifdef CONFIGURE_TEST_VM_WRITE_WATCH
410 + int main(void)
411 + {
412 +        int i, j;
413 +
414 +        vm_init();
415 +
416 +        vm_uintptr_t page_size = vm_get_page_size();
417 +        
418 +        char *area;
419 +        const int n_pages = 7;
420 +        const int area_size = n_pages * page_size;
421 +        const int map_options = VM_MAP_DEFAULT | VM_MAP_WRITE_WATCH;
422 +        if ((area = (char *)vm_acquire(area_size, map_options)) == VM_MAP_FAILED)
423 +                return 1;
424 +
425 +        unsigned int n_modified_pages_expected = 0;
426 +        static const int touch_page[n_pages] = { 0, 1, 1, 0, 1, 0, 1 };
427 +        for (i = 0; i < n_pages; i++) {
428 +                if (touch_page[i]) {
429 +                        area[i * page_size] = 1;
430 +                        ++n_modified_pages_expected;
431 +                }
432 +        }
433 +
434 +        char *modified_pages[n_pages];
435 +        unsigned int n_modified_pages = n_pages;
436 +        if (vm_get_write_watch(area, area_size, (void **)modified_pages, &n_modified_pages) < 0)
437 +                return 2;
438 +        if (n_modified_pages != n_modified_pages_expected)
439 +                return 3;
440 +        for (i = 0, j = 0; i < n_pages; i++) {
441 +                char v = area[i * page_size];
442 +                if ((touch_page[i] && !v) || (!touch_page[i] && v))
443 +                        return 4;
444 +                if (!touch_page[i])
445 +                        continue;
446 +                if (modified_pages[j] != (area + i * page_size))
447 +                        return 5;
448 +                ++j;
449 +        }
450 +
451 +        vm_release(area, area_size);
452 +        return 0;
453 + }
454 + #endif
455 +
456   #ifdef CONFIGURE_TEST_VM_MAP
457   #include <stdlib.h>
458   #include <signal.h>

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines