mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 00:32:25 -04:00
Catch up with r193750 (OsdSynch.c locking changes):
- Preallocate some memory for ACPI tasks early enough. We cannot use malloc(9) any more because spin mutex may be held here. The reserved memory can be tuned via debug.acpi.max_tasks tunable or ACPI_MAX_TASKS in kernel configuration. The default is 32 tasks. - Implement a custom taskqueue_fast to wrap the new memory allocation. This implementation is not the fastest in the world but we are being conservative here.
This commit is contained in:
parent
a603018613
commit
3ff9febde6
3 changed files with 98 additions and 16 deletions
|
|
@ -663,6 +663,7 @@ WITNESS_SKIPSPIN opt_witness.h
|
|||
|
||||
# options for ACPI support
|
||||
ACPI_DEBUG opt_acpi.h
|
||||
ACPI_MAX_TASKS opt_acpi.h
|
||||
ACPI_MAX_THREADS opt_acpi.h
|
||||
|
||||
# ISA support
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
/*-
|
||||
* Copyright (c) 2000 Michael Smith
|
||||
* Copyright (c) 2000 BSDi
|
||||
* Copyright (c) 2007-2009 Jung-uk Kim <jkim@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
|
@ -51,6 +52,12 @@ __FBSDID("$FreeBSD$");
|
|||
#define _COMPONENT ACPI_OS_SERVICES
|
||||
ACPI_MODULE_NAME("SCHEDULE")
|
||||
|
||||
/*
|
||||
* Allow the user to tune the maximum number of tasks we may enqueue.
|
||||
*/
|
||||
static int acpi_max_tasks = ACPI_MAX_TASKS;
|
||||
TUNABLE_INT("debug.acpi.max_tasks", &acpi_max_tasks);
|
||||
|
||||
/*
|
||||
* Allow the user to tune the number of task threads we start. It seems
|
||||
* some systems have problems with increased parallelism.
|
||||
|
|
@ -64,11 +71,54 @@ struct acpi_task_ctx {
|
|||
struct task at_task;
|
||||
ACPI_OSD_EXEC_CALLBACK at_function;
|
||||
void *at_context;
|
||||
int at_flag;
|
||||
#define ACPI_TASK_USED 1
|
||||
#define ACPI_TASK_ENQUEUED 2
|
||||
};
|
||||
|
||||
TASKQUEUE_DEFINE(acpi, taskqueue_thread_enqueue, &taskqueue_acpi,
|
||||
taskqueue_start_threads(&taskqueue_acpi, acpi_max_threads, PWAIT,
|
||||
"acpi_task"));
|
||||
struct taskqueue *acpi_taskq;
|
||||
static struct acpi_task_ctx *acpi_tasks;
|
||||
static int acpi_task_count;
|
||||
static int acpi_taskq_started;
|
||||
|
||||
/*
|
||||
* Preallocate some memory for tasks early enough.
|
||||
* malloc(9) cannot be used with spin lock held.
|
||||
*/
|
||||
static void
|
||||
acpi_task_init(void *arg)
|
||||
{
|
||||
|
||||
acpi_tasks = malloc(sizeof(*acpi_tasks) * acpi_max_tasks, M_ACPITASK,
|
||||
M_WAITOK | M_ZERO);
|
||||
}
|
||||
|
||||
SYSINIT(acpi_tasks, SI_SUB_DRIVERS, SI_ORDER_FIRST, acpi_task_init, NULL);
|
||||
|
||||
/*
|
||||
* Initialize ACPI task queue.
|
||||
*/
|
||||
static void
|
||||
acpi_taskq_init(void *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
acpi_taskq = taskqueue_create_fast("acpi_task", M_NOWAIT,
|
||||
&taskqueue_thread_enqueue, &acpi_taskq);
|
||||
taskqueue_start_threads(&acpi_taskq, acpi_max_threads, PWAIT, "acpi_task");
|
||||
if (acpi_task_count > 0) {
|
||||
if (bootverbose)
|
||||
printf("AcpiOsExecute: enqueue %d pending tasks\n",
|
||||
acpi_task_count);
|
||||
for (i = 0; i < acpi_max_tasks; i++)
|
||||
if (atomic_cmpset_acq_int(&acpi_tasks[i].at_flag, ACPI_TASK_USED,
|
||||
ACPI_TASK_USED | ACPI_TASK_ENQUEUED))
|
||||
taskqueue_enqueue(acpi_taskq, &acpi_tasks[i].at_task);
|
||||
}
|
||||
acpi_taskq_started = 1;
|
||||
}
|
||||
|
||||
SYSINIT(acpi_taskq, SI_SUB_CONFIGURE, SI_ORDER_SECOND, acpi_taskq_init, NULL);
|
||||
|
||||
/*
|
||||
* Bounce through this wrapper function since ACPI-CA doesn't understand
|
||||
|
|
@ -81,7 +131,44 @@ acpi_task_execute(void *context, int pending)
|
|||
|
||||
at = (struct acpi_task_ctx *)context;
|
||||
at->at_function(at->at_context);
|
||||
free(at, M_ACPITASK);
|
||||
atomic_clear_int(&at->at_flag, ACPI_TASK_USED | ACPI_TASK_ENQUEUED);
|
||||
acpi_task_count--;
|
||||
}
|
||||
|
||||
static ACPI_STATUS
|
||||
acpi_task_enqueue(int priority, ACPI_OSD_EXEC_CALLBACK Function, void *Context)
|
||||
{
|
||||
struct acpi_task_ctx *at;
|
||||
int i;
|
||||
|
||||
for (at = NULL, i = 0; i < acpi_max_tasks; i++)
|
||||
if (atomic_cmpset_acq_int(&acpi_tasks[i].at_flag, 0, ACPI_TASK_USED)) {
|
||||
at = &acpi_tasks[i];
|
||||
acpi_task_count++;
|
||||
break;
|
||||
}
|
||||
if (at == NULL) {
|
||||
printf("AcpiOsExecute: failed to enqueue task, consider increasing "
|
||||
"the debug.acpi.max_tasks tunable\n");
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
TASK_INIT(&at->at_task, priority, acpi_task_execute, at);
|
||||
at->at_function = Function;
|
||||
at->at_context = Context;
|
||||
|
||||
/*
|
||||
* If the task queue is ready, enqueue it now.
|
||||
*/
|
||||
if (acpi_taskq_started) {
|
||||
atomic_set_int(&at->at_flag, ACPI_TASK_ENQUEUED);
|
||||
taskqueue_enqueue(acpi_taskq, &at->at_task);
|
||||
return (AE_OK);
|
||||
}
|
||||
if (bootverbose)
|
||||
printf("AcpiOsExecute: task queue not started\n");
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -92,7 +179,6 @@ ACPI_STATUS
|
|||
AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
|
||||
void *Context)
|
||||
{
|
||||
struct acpi_task_ctx *at;
|
||||
int pri;
|
||||
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
|
||||
|
|
@ -100,12 +186,6 @@ AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
|
|||
if (Function == NULL)
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
|
||||
at = malloc(sizeof(*at), M_ACPITASK, M_NOWAIT);
|
||||
if (at == NULL)
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
|
||||
at->at_function = Function;
|
||||
at->at_context = Context;
|
||||
switch (Type) {
|
||||
case OSL_GPE_HANDLER:
|
||||
case OSL_NOTIFY_HANDLER:
|
||||
|
|
@ -126,14 +206,10 @@ AcpiOsExecute(ACPI_EXECUTE_TYPE Type, ACPI_OSD_EXEC_CALLBACK Function,
|
|||
pri = 0;
|
||||
break;
|
||||
default:
|
||||
free(at, M_ACPITASK);
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
TASK_INIT(&at->at_task, pri, acpi_task_execute, at);
|
||||
taskqueue_enqueue(taskqueue_acpi, &at->at_task);
|
||||
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
return_ACPI_STATUS (acpi_task_enqueue(pri, Function, Context));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -457,6 +457,11 @@ ACPI_HANDLE acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj);
|
|||
*/
|
||||
#define ACPI_DEV_BASE_ORDER 10
|
||||
|
||||
/* Default maximum number of tasks to enqueue. */
|
||||
#ifndef ACPI_MAX_TASKS
|
||||
#define ACPI_MAX_TASKS 32
|
||||
#endif
|
||||
|
||||
/* Default number of task queue threads to start. */
|
||||
#ifndef ACPI_MAX_THREADS
|
||||
#define ACPI_MAX_THREADS 3
|
||||
|
|
|
|||
Loading…
Reference in a new issue