143 |
|
|
144 |
struct user_pager_info |
struct user_pager_info |
145 |
{ |
{ |
|
display_t display; |
|
|
struct pager *p; |
|
146 |
size_t memobj_npages; |
size_t memobj_npages; |
147 |
vm_address_t memobj_pages[0]; |
vm_address_t memobj_pages[0]; |
148 |
}; |
}; |
193 |
|
|
194 |
struct cons_display *user; |
struct cons_display *user; |
195 |
|
|
196 |
struct user_pager_info *upi; |
struct pager *pager; |
197 |
memory_object_t memobj; |
memory_object_t memobj; |
198 |
|
|
199 |
/* A list of ports to send file change notifications to. */ |
/* A list of ports to send file change notifications to. */ |
274 |
vm_address_t *offset, |
vm_address_t *offset, |
275 |
vm_size_t *size) |
vm_size_t *size) |
276 |
{ |
{ |
|
display_t display = upi->display; |
|
277 |
*offset = 0; |
*offset = 0; |
278 |
*size = display->upi->memobj_npages * vm_page_size; |
*size = upi->memobj_npages * vm_page_size; |
279 |
return 0; |
return 0; |
280 |
} |
} |
281 |
|
|
402 |
struct modreq *tmp; |
struct modreq *tmp; |
403 |
for (; mr; mr = tmp) |
for (; mr; mr = tmp) |
404 |
{ |
{ |
405 |
|
mach_port_t old; |
406 |
|
/* Cancel the dead-name notification. */ |
407 |
|
mach_port_request_notification (mach_task_self (), mr->port, |
408 |
|
MACH_NOTIFY_DEAD_NAME, 0, |
409 |
|
MACH_PORT_NULL, |
410 |
|
MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); |
411 |
|
mach_port_deallocate (mach_task_self (), old); |
412 |
|
|
413 |
|
/* Deallocate the user's port. */ |
414 |
mach_port_deallocate (mach_task_self (), mr->port); |
mach_port_deallocate (mach_task_self (), mr->port); |
415 |
tmp = mr->next; |
tmp = mr->next; |
416 |
free (mr); |
free (mr); |
417 |
} |
} |
418 |
} |
} |
419 |
|
|
420 |
void do_mach_notify_port_deleted (void) { assert (0); } |
/* A port deleted notification is generated when we deallocate the |
421 |
|
user's notify port before it is dead. */ |
422 |
|
error_t |
423 |
|
do_mach_notify_port_deleted (mach_port_t notify, mach_port_t name) |
424 |
|
{ |
425 |
|
/* As we cancel the dead-name notification before deallocating the |
426 |
|
port, this should not happen. */ |
427 |
|
assert (0); |
428 |
|
} |
429 |
|
|
430 |
|
/* We request dead name notifications for the user ports. */ |
431 |
|
error_t |
432 |
|
do_mach_notify_dead_name (mach_port_t notify, mach_port_t dead_name) |
433 |
|
{ |
434 |
|
struct notify *notify_port = ports_lookup_port (notify_bucket, |
435 |
|
notify, notify_class); |
436 |
|
struct display *display; |
437 |
|
struct modreq **preq; |
438 |
|
struct modreq *req; |
439 |
|
|
440 |
|
if (!notify_port) |
441 |
|
return EOPNOTSUPP; |
442 |
|
|
443 |
|
display = notify_port->display; |
444 |
|
mutex_lock (&display->lock); |
445 |
|
|
446 |
|
/* Find request in pending queue. */ |
447 |
|
preq = &display->filemod_reqs_pending; |
448 |
|
while (*preq && (*preq)->port != dead_name) |
449 |
|
preq = &(*preq)->next; |
450 |
|
if (! *preq) |
451 |
|
{ |
452 |
|
/* Find request in queue. */ |
453 |
|
preq = &display->filemod_reqs; |
454 |
|
while (*preq && (*preq)->port != dead_name) |
455 |
|
preq = &(*preq)->next; |
456 |
|
} |
457 |
|
|
458 |
|
if (*preq) |
459 |
|
{ |
460 |
|
req = *preq; |
461 |
|
*preq = req->next; |
462 |
|
|
463 |
|
mach_port_deallocate (mach_task_self (), req->port); |
464 |
|
free (req); |
465 |
|
} |
466 |
|
mutex_unlock (&display->lock); |
467 |
|
|
468 |
|
/* Drop gratuitous extra reference that the notification creates. */ |
469 |
|
mach_port_deallocate (mach_task_self (), dead_name); |
470 |
|
|
471 |
|
return 0; |
472 |
|
} |
473 |
|
|
474 |
void do_mach_notify_port_destroyed (void) { assert (0); } |
void do_mach_notify_port_destroyed (void) { assert (0); } |
475 |
void do_mach_notify_no_senders (void) { assert (0); } |
|
476 |
void do_mach_notify_dead_name (void) { assert (0); } |
error_t |
477 |
|
do_mach_notify_no_senders (mach_port_t port, mach_port_mscount_t count) |
478 |
|
{ |
479 |
|
return ports_do_mach_notify_no_senders (port, count); |
480 |
|
} |
481 |
|
|
482 |
kern_return_t |
kern_return_t |
483 |
do_mach_notify_send_once (mach_port_t notify) |
do_mach_notify_send_once (mach_port_t notify) |
484 |
{ |
{ |
485 |
/* XXX Not sure when this is called. */ |
return 0; |
|
assert (0); |
|
486 |
} |
} |
487 |
|
|
488 |
kern_return_t |
kern_return_t |
535 |
notify); |
notify); |
536 |
if (err && err != MACH_SEND_WILL_NOTIFY) |
if (err && err != MACH_SEND_WILL_NOTIFY) |
537 |
{ |
{ |
538 |
|
mach_port_t old; |
539 |
*preq = req->next; |
*preq = req->next; |
540 |
mutex_unlock (&display->lock); |
mutex_unlock (&display->lock); |
541 |
|
|
542 |
|
/* Cancel the dead-name notification. */ |
543 |
|
mach_port_request_notification (mach_task_self (), req->port, |
544 |
|
MACH_NOTIFY_DEAD_NAME, 0, |
545 |
|
MACH_PORT_NULL, |
546 |
|
MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); |
547 |
|
mach_port_deallocate (mach_task_self (), old); |
548 |
|
|
549 |
mach_port_deallocate (mach_task_self (), req->port); |
mach_port_deallocate (mach_task_self (), req->port); |
550 |
free (req); |
free (req); |
551 |
ports_port_deref (notify_port); |
ports_port_deref (notify_port); |
587 |
{ |
{ |
588 |
error_t err; |
error_t err; |
589 |
struct modreq *req; |
struct modreq *req; |
590 |
|
mach_port_t notify_port; |
591 |
|
mach_port_t old; |
592 |
|
|
593 |
mutex_lock (&display->lock); |
mutex_lock (&display->lock); |
594 |
err = nowait_file_changed (notify, 0, FILE_CHANGED_NULL, 0, 0, MACH_PORT_NULL); |
err = nowait_file_changed (notify, 0, FILE_CHANGED_NULL, 0, 0, |
595 |
|
MACH_PORT_NULL); |
596 |
if (err) |
if (err) |
597 |
{ |
{ |
598 |
mutex_unlock (&display->lock); |
mutex_unlock (&display->lock); |
599 |
return err; |
return err; |
600 |
} |
} |
601 |
|
|
602 |
req = malloc (sizeof (struct modreq)); |
req = malloc (sizeof (struct modreq)); |
603 |
if (!req) |
if (!req) |
604 |
{ |
{ |
605 |
mutex_unlock (&display->lock); |
mutex_unlock (&display->lock); |
606 |
return errno; |
return errno; |
607 |
} |
} |
608 |
|
|
609 |
|
notify_port = ports_get_right (display->notify_port); |
610 |
|
|
611 |
|
/* Request dead-name notification for the user's port. */ |
612 |
|
err = mach_port_request_notification (mach_task_self (), notify, |
613 |
|
MACH_NOTIFY_DEAD_NAME, 0, |
614 |
|
notify_port, |
615 |
|
MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); |
616 |
|
if (err) |
617 |
|
{ |
618 |
|
free (req); |
619 |
|
mutex_unlock (&display->lock); |
620 |
|
return err; |
621 |
|
} |
622 |
|
assert (old == MACH_PORT_NULL); |
623 |
|
|
624 |
req->port = notify; |
req->port = notify; |
625 |
req->pending = 0; |
req->pending = 0; |
626 |
req->next = display->filemod_reqs; |
req->next = display->filemod_reqs; |
662 |
} |
} |
663 |
else |
else |
664 |
{ |
{ |
665 |
|
mach_port_t old; |
666 |
|
|
667 |
|
/* Cancel the dead-name notification. */ |
668 |
|
mach_port_request_notification (mach_task_self (), req->port, |
669 |
|
MACH_NOTIFY_DEAD_NAME, 0, |
670 |
|
MACH_PORT_NULL, 0, &old); |
671 |
|
mach_port_deallocate (mach_task_self (), old); |
672 |
mach_port_deallocate (mach_task_self (), req->port); |
mach_port_deallocate (mach_task_self (), req->port); |
673 |
free (req); |
free (req); |
674 |
} |
} |
880 |
{ |
{ |
881 |
error_t err; |
error_t err; |
882 |
struct cons_display *user; |
struct cons_display *user; |
883 |
|
struct user_pager_info *upi; |
884 |
|
|
885 |
int npages = (round_page (sizeof (struct cons_display) + |
int npages = (round_page (sizeof (struct cons_display) + |
886 |
sizeof (conchar_t) * width * lines)) / vm_page_size; |
sizeof (conchar_t) * width * lines)) / vm_page_size; |
887 |
|
|
888 |
display->upi = calloc (1, sizeof (struct user_pager_info) |
upi = calloc (1, sizeof (struct user_pager_info) |
889 |
+ sizeof (vm_address_t) * npages); |
+ sizeof (vm_address_t) * npages); |
890 |
if (!display->upi) |
if (!upi) |
891 |
return MACH_PORT_NULL; |
return MACH_PORT_NULL; |
892 |
display->upi->display = display; |
upi->memobj_npages = npages; |
|
display->upi->memobj_npages = npages; |
|
893 |
/* 1 & MOCD correct? */ |
/* 1 & MOCD correct? */ |
894 |
display->upi->p = pager_create (display->upi, pager_bucket, |
display->pager = pager_create (upi, pager_bucket, |
895 |
1, MEMORY_OBJECT_COPY_DELAY); |
1, MEMORY_OBJECT_COPY_DELAY); |
896 |
if (display->upi->p == 0) |
if (display->pager == 0) |
897 |
{ |
{ |
898 |
free (display->upi); |
free (upi); |
899 |
return errno; |
return errno; |
900 |
} |
} |
901 |
display->memobj = pager_get_port (display->upi->p); |
display->memobj = pager_get_port (display->pager); |
902 |
ports_port_deref (display->upi->p); |
ports_port_deref (display->pager); |
903 |
|
|
904 |
mach_port_insert_right (mach_task_self (), display->memobj, display->memobj, |
mach_port_insert_right (mach_task_self (), display->memobj, display->memobj, |
905 |
MACH_MSG_TYPE_MAKE_SEND); |
MACH_MSG_TYPE_MAKE_SEND); |
906 |
|
|
907 |
err = vm_map (mach_task_self (), |
err = vm_map (mach_task_self (), |
908 |
(vm_address_t *) &user, |
(vm_address_t *) &user, |
909 |
(vm_size_t) display->upi->memobj_npages * vm_page_size, |
(vm_size_t) npages * vm_page_size, |
910 |
(vm_address_t) 0, |
(vm_address_t) 0, |
911 |
1 /* ! (flags & MAP_FIXED) */, |
1 /* ! (flags & MAP_FIXED) */, |
912 |
display->memobj, 0 /* (vm_offset_t) offset */, |
display->memobj, 0 /* (vm_offset_t) offset */, |
914 |
VM_PROT_READ | VM_PROT_WRITE, |
VM_PROT_READ | VM_PROT_WRITE, |
915 |
VM_PROT_READ | VM_PROT_WRITE, |
VM_PROT_READ | VM_PROT_WRITE, |
916 |
VM_INHERIT_NONE); |
VM_INHERIT_NONE); |
917 |
|
|
918 |
if (err) |
if (err) |
919 |
{ |
{ |
920 |
/* UPI will be cleaned up by libpager. */ |
/* UPI will be cleaned up by libpager. */ |
947 |
user_destroy (display_t display) |
user_destroy (display_t display) |
948 |
{ |
{ |
949 |
/* The pager will be deallocated by libpager. */ |
/* The pager will be deallocated by libpager. */ |
950 |
|
vm_deallocate (mach_task_self (), (vm_offset_t) display->user, |
951 |
|
pager_get_upi (display->pager)->memobj_npages * vm_page_size); |
952 |
mach_port_deallocate (mach_task_self (), display->memobj); |
mach_port_deallocate (mach_task_self (), display->memobj); |
953 |
} |
} |
954 |
|
|
2000 |
void |
void |
2001 |
display_destroy (display_t display) |
display_destroy (display_t display) |
2002 |
{ |
{ |
2003 |
|
mutex_lock (&display->lock); |
2004 |
if (display->filemod_reqs_pending) |
if (display->filemod_reqs_pending) |
2005 |
free_modreqs (display->filemod_reqs_pending); |
{ |
2006 |
|
free_modreqs (display->filemod_reqs_pending); |
2007 |
|
display->filemod_reqs_pending = NULL; |
2008 |
|
} |
2009 |
if (display->filemod_reqs) |
if (display->filemod_reqs) |
2010 |
free_modreqs (display->filemod_reqs); |
{ |
2011 |
|
free_modreqs (display->filemod_reqs); |
2012 |
|
display->filemod_reqs = NULL; |
2013 |
|
} |
2014 |
ports_destroy_right (display->notify_port); |
ports_destroy_right (display->notify_port); |
2015 |
output_deinit (&display->output); |
output_deinit (&display->output); |
2016 |
user_destroy (display); |
user_destroy (display); |
2017 |
|
mutex_unlock (&display->lock); |
2018 |
|
|
2019 |
/* We can not free the display structure here, because it might |
/* We can not free the display structure here, because it might |
2020 |
still be needed by pending modification requests when msg |
still be needed by pending modification requests when msg |
2021 |
accepted notifications are handled. So we have to wait until all |
accepted notifications are handled. So we have to wait until all |