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!