- assert(! shared_region->sr_mapping_in_progress);
- /* remove it from the queue first, so no one can find it... */
- queue_remove(&vm_shared_region_queue,
- shared_region,
- vm_shared_region_t,
- sr_q);
- vm_shared_region_unlock();
- /* ... and destroy it */
- vm_shared_region_destroy(shared_region);
- shared_region = NULL;
+ uint64_t deadline;
+
+ if (shared_region->sr_timer_call == NULL) {
+ /* hold one reference for the timer */
+ assert(! shared_region->sr_mapping_in_progress);
+ shared_region->sr_ref_count++;
+
+ /* set up the timer */
+ shared_region->sr_timer_call = thread_call_allocate(
+ (thread_call_func_t) vm_shared_region_timeout,
+ (thread_call_param_t) shared_region);
+
+ /* schedule the timer */
+ clock_interval_to_deadline(shared_region_destroy_delay,
+ 1000 * 1000 * 1000,
+ &deadline);
+ thread_call_enter_delayed(shared_region->sr_timer_call,
+ deadline);
+
+ SHARED_REGION_TRACE_DEBUG(
+ ("shared_region: deallocate(%p): armed timer\n",
+ shared_region));
+
+ vm_shared_region_unlock();
+ } else {
+ /* timer expired: let go of this shared region */
+
+ /*
+ * Remove it from the queue first, so no one can find
+ * it...
+ */
+ queue_remove(&vm_shared_region_queue,
+ shared_region,
+ vm_shared_region_t,
+ sr_q);
+ vm_shared_region_unlock();
+ /* ... and destroy it */
+ vm_shared_region_destroy(shared_region);
+ shared_region = NULL;
+ }