/* * Xen event channels (FIFO-based ABI) * * Copyright (C) 2013 Citrix Systems R&D ltd. * * This source code is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Or, when distributed separately from the Linux kernel or * incorporated into other software packages, subject to the following * license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE.
*/
for (i = event_array_pages; i < MAX_EVENT_ARRAY_PAGES; i++) { if (!event_array[i]) break;
free_page((unsignedlong)event_array[i]);
event_array[i] = NULL;
}
}
/* * Reached the tail last time? Read the new HEAD from the * control block.
*/ if (head == 0) {
virt_rmb(); /* Ensure word is up-to-date before reading head. */
head = control_block->head[priority];
}
port = head;
word = event_word_from_port(port);
head = clear_linked(word);
/* * If the link is non-zero, there are more events in the * queue, otherwise the queue is empty. * * If the queue is empty, clear this priority from our local * copy of the ready word.
*/ if (head == 0)
clear_bit(priority, ready);
if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) { if (unlikely(!ctrl))
pr_warn("Dropping pending event for port %u\n", port); else
handle_irq_for_port(port, ctrl);
}
for_each_possible_cpu(cpu) { void *control_block = per_cpu(cpu_control_block, cpu); int ret;
if (!control_block) continue;
/* * If this CPU is offline, take the opportunity to * free the control block while it is not being * used.
*/ if (!cpu_online(cpu)) {
free_page((unsignedlong)control_block);
per_cpu(cpu_control_block, cpu) = NULL; continue;
}
ret = init_control_block(cpu, control_block);
BUG_ON(ret < 0);
}
/* * The event array starts out as empty again and is extended * as normal when events are bound. The existing pages will * be reused.
*/
event_array_pages = 0;
}
staticint evtchn_fifo_alloc_control_block(unsigned cpu)
{ void *control_block = NULL; int ret = -ENOMEM;
control_block = (void *)__get_free_page(GFP_KERNEL); if (control_block == NULL) goto error;
ret = init_control_block(cpu, control_block); if (ret < 0) goto error;
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.