/* Prevent freeing of mm until we are completely finished. */
mmgrab(handler->mn.mm);
/* Unregister first so we don't get any more notifications. */
mmu_notifier_unregister(&handler->mn, handler->mn.mm);
/* * Make sure the wq delete handler is finished running. It will not * be triggered once the mmu notifiers are unregistered above.
*/
flush_work(&handler->del_work);
INIT_LIST_HEAD(&del_list);
spin_lock_irqsave(&handler->lock, flags); while ((node = rb_first_cached(&handler->root))) {
rbnode = rb_entry(node, struct mmu_rb_node, node);
rb_erase_cached(node, &handler->root); /* move from LRU list to delete list */
list_move(&rbnode->list, &del_list);
}
spin_unlock_irqrestore(&handler->lock, flags);
spin_lock_irqsave(&handler->lock, flags);
list_for_each_entry_safe(rbnode, ptr, &handler->lru_list, list) { /* refcount == 1 implies mmu_rb_handler has only rbnode ref */ if (kref_read(&rbnode->refcount) > 1) continue;
if (handler->ops->evict(handler->ops_arg, rbnode, evict_arg,
&stop)) {
__mmu_int_rb_remove(rbnode, &handler->root); /* move from LRU list to delete list */
list_move(&rbnode->list, &del_list);
} if (stop) break;
}
spin_unlock_irqrestore(&handler->lock, flags);
spin_lock_irqsave(&handler->lock, flags); for (node = __mmu_int_rb_iter_first(root, range->start, range->end-1);
node; node = ptr) { /* Guard against node removal. */
ptr = __mmu_int_rb_iter_next(node, range->start,
range->end - 1);
trace_hfi1_mmu_mem_invalidate(node); /* Remove from rb tree and lru_list. */
__mmu_int_rb_remove(node, root);
list_del_init(&node->list);
kref_put(&node->refcount, release_nolock);
}
spin_unlock_irqrestore(&handler->lock, flags);
return 0;
}
/* * Work queue function to remove all nodes that have been queued up to * be removed. The key feature is that mm->mmap_lock is not being held * and the remove callback can sleep while taking it, if needed.
*/ staticvoid handle_remove(struct work_struct *work)
{ struct mmu_rb_handler *handler = container_of(work, struct mmu_rb_handler,
del_work); struct list_head del_list; unsignedlong flags; struct mmu_rb_node *node;
/* remove anything that is queued to get removed */
spin_lock_irqsave(&handler->lock, flags);
list_replace_init(&handler->del_list, &del_list);
spin_unlock_irqrestore(&handler->lock, flags);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.