Changeset View
Changeset View
Standalone View
Standalone View
sys/compat/linuxkpi/common/src/linux_work.c
/*- | /*- | ||||
* Copyright (c) 2017-2019 Hans Petter Selasky | * Copyright (c) 2017-2021 Hans Petter Selasky | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice unmodified, this list of conditions, and the following | * notice unmodified, this list of conditions, and the following | ||||
* disclaimer. | * disclaimer. | ||||
▲ Show 20 Lines • Show All 417 Lines • ▼ Show 20 Lines | static const uint8_t states[WORK_ST_MAX] __aligned(8) = { | ||||
[WORK_ST_IDLE] = WORK_ST_IDLE, /* NOP */ | [WORK_ST_IDLE] = WORK_ST_IDLE, /* NOP */ | ||||
[WORK_ST_TIMER] = WORK_ST_CANCEL, /* try to cancel */ | [WORK_ST_TIMER] = WORK_ST_CANCEL, /* try to cancel */ | ||||
[WORK_ST_TASK] = WORK_ST_CANCEL, /* try to cancel */ | [WORK_ST_TASK] = WORK_ST_CANCEL, /* try to cancel */ | ||||
[WORK_ST_EXEC] = WORK_ST_EXEC, /* NOP */ | [WORK_ST_EXEC] = WORK_ST_EXEC, /* NOP */ | ||||
[WORK_ST_CANCEL] = WORK_ST_CANCEL, /* NOP */ | [WORK_ST_CANCEL] = WORK_ST_CANCEL, /* NOP */ | ||||
}; | }; | ||||
struct taskqueue *tq; | struct taskqueue *tq; | ||||
retry: | |||||
switch (linux_update_state(&dwork->work.state, states)) { | switch (linux_update_state(&dwork->work.state, states)) { | ||||
case WORK_ST_TIMER: | case WORK_ST_TIMER: | ||||
hselasky: @rstone: I only see that the callout function callback can sneak in right here, but not later… | |||||
rstoneUnsubmitted Not Done Inline ActionsThe callout could have started but be preempted for whatever reason. callout_stop() cannot stop a callout that has started to run. rstone: The callout could have started but be preempted for whatever reason. callout_stop() cannot… | |||||
case WORK_ST_CANCEL: | |||||
if (linux_cancel_timer(dwork, 0)) { | if (linux_cancel_timer(dwork, 0)) { | ||||
atomic_cmpxchg(&dwork->work.state, | atomic_cmpxchg(&dwork->work.state, | ||||
WORK_ST_CANCEL, WORK_ST_IDLE); | WORK_ST_CANCEL, WORK_ST_IDLE); | ||||
return (true); | return (true); | ||||
} | } | ||||
/* FALLTHROUGH */ | /* | ||||
* If the timer was not stopped, it means it has just | |||||
* elapsed and the state needs to be checked again: | |||||
*/ | |||||
goto retry; | |||||
case WORK_ST_CANCEL: | |||||
case WORK_ST_TASK: | case WORK_ST_TASK: | ||||
tq = dwork->work.work_queue->taskqueue; | tq = dwork->work.work_queue->taskqueue; | ||||
if (taskqueue_cancel(tq, &dwork->work.work_task, NULL) == 0) { | if (taskqueue_cancel(tq, &dwork->work.work_task, NULL) == 0) { | ||||
atomic_cmpxchg(&dwork->work.state, | atomic_cmpxchg(&dwork->work.state, | ||||
WORK_ST_CANCEL, WORK_ST_IDLE); | WORK_ST_CANCEL, WORK_ST_IDLE); | ||||
return (true); | return (true); | ||||
} | } | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
▲ Show 20 Lines • Show All 233 Lines • Show Last 20 Lines |
@rstone: I only see that the callout function callback can sneak in right here, but not later on!