2024-01-08 00:39:27 +00:00
|
|
|
/* $OpenBSD: workqueue.h,v 1.11 2024/01/06 09:33:08 kettenis Exp $ */
|
2023-04-30 01:15:27 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2015 Mark Kettenis
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _LINUX_WORKQUEUE_H
|
|
|
|
#define _LINUX_WORKQUEUE_H
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/task.h>
|
|
|
|
#include <sys/timeout.h>
|
|
|
|
#include <linux/bitops.h>
|
|
|
|
#include <linux/atomic.h>
|
|
|
|
#include <linux/rcupdate.h>
|
|
|
|
#include <linux/lockdep.h>
|
|
|
|
#include <linux/timer.h>
|
|
|
|
|
|
|
|
struct workqueue_struct;
|
|
|
|
|
|
|
|
extern struct workqueue_struct *system_wq;
|
|
|
|
extern struct workqueue_struct *system_highpri_wq;
|
|
|
|
extern struct workqueue_struct *system_unbound_wq;
|
|
|
|
extern struct workqueue_struct *system_long_wq;
|
|
|
|
|
2024-01-08 00:39:27 +00:00
|
|
|
#define WQ_HIGHPRI (1 << 1)
|
|
|
|
#define WQ_FREEZABLE (1 << 2)
|
|
|
|
#define WQ_UNBOUND (1 << 3)
|
|
|
|
#define WQ_MEM_RECLAIM (1 << 4)
|
2023-04-30 01:15:27 +00:00
|
|
|
|
|
|
|
#define WQ_UNBOUND_MAX_ACTIVE 4 /* matches nthreads in drm_linux.c */
|
|
|
|
|
|
|
|
static inline struct workqueue_struct *
|
|
|
|
alloc_workqueue(const char *name, int flags, int max_active)
|
|
|
|
{
|
|
|
|
struct taskq *tq = taskq_create(name, 1, IPL_TTY, 0);
|
|
|
|
return (struct workqueue_struct *)tq;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct workqueue_struct *
|
2024-01-08 00:39:27 +00:00
|
|
|
alloc_ordered_workqueue(const char *name, int flags, ...)
|
2023-04-30 01:15:27 +00:00
|
|
|
{
|
|
|
|
struct taskq *tq = taskq_create(name, 1, IPL_TTY, 0);
|
|
|
|
return (struct workqueue_struct *)tq;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline struct workqueue_struct *
|
|
|
|
create_singlethread_workqueue(const char *name)
|
|
|
|
{
|
|
|
|
struct taskq *tq = taskq_create(name, 1, IPL_TTY, 0);
|
|
|
|
return (struct workqueue_struct *)tq;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
destroy_workqueue(struct workqueue_struct *wq)
|
|
|
|
{
|
|
|
|
taskq_destroy((struct taskq *)wq);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct work_struct {
|
|
|
|
struct task task;
|
|
|
|
struct taskq *tq;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef void (*work_func_t)(struct work_struct *);
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
INIT_WORK(struct work_struct *work, work_func_t func)
|
|
|
|
{
|
|
|
|
work->tq = NULL;
|
|
|
|
task_set(&work->task, (void (*)(void *))func, work);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define INIT_WORK_ONSTACK(x, y) INIT_WORK((x), (y))
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
queue_work(struct workqueue_struct *wq, struct work_struct *work)
|
|
|
|
{
|
|
|
|
work->tq = (struct taskq *)wq;
|
|
|
|
return task_add(work->tq, &work->task);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
cancel_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
if (work->tq != NULL)
|
|
|
|
task_del(work->tq, &work->task);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
cancel_work_sync(struct work_struct *work)
|
|
|
|
{
|
|
|
|
if (work->tq != NULL)
|
|
|
|
task_del(work->tq, &work->task);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define work_pending(work) task_pending(&(work)->task)
|
|
|
|
|
|
|
|
struct delayed_work {
|
|
|
|
struct work_struct work;
|
|
|
|
struct timeout to;
|
|
|
|
struct taskq *tq;
|
|
|
|
};
|
|
|
|
|
|
|
|
#define system_power_efficient_wq ((struct workqueue_struct *)systq)
|
|
|
|
|
|
|
|
static inline struct delayed_work *
|
|
|
|
to_delayed_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
return container_of(work, struct delayed_work, work);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
__delayed_work_tick(void *arg)
|
|
|
|
{
|
|
|
|
struct delayed_work *dwork = arg;
|
|
|
|
|
|
|
|
task_add(dwork->tq, &dwork->work.task);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
INIT_DELAYED_WORK(struct delayed_work *dwork, work_func_t func)
|
|
|
|
{
|
|
|
|
INIT_WORK(&dwork->work, func);
|
|
|
|
timeout_set(&dwork->to, __delayed_work_tick, &dwork->work);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
INIT_DELAYED_WORK_ONSTACK(struct delayed_work *dwork, work_func_t func)
|
|
|
|
{
|
|
|
|
INIT_WORK(&dwork->work, func);
|
|
|
|
timeout_set(&dwork->to, __delayed_work_tick, &dwork->work);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define __DELAYED_WORK_INITIALIZER(dw, fn, flags) { \
|
|
|
|
.to = TIMEOUT_INITIALIZER(__delayed_work_tick, &(dw)), \
|
|
|
|
.tq = NULL, \
|
|
|
|
.work.tq = NULL, \
|
|
|
|
.work.task = TASK_INITIALIZER((void (*)(void *))(fn), &(dw).work) \
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
schedule_work(struct work_struct *work)
|
|
|
|
{
|
|
|
|
work->tq = (struct taskq *)system_wq;
|
|
|
|
return task_add(work->tq, &work->task);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
schedule_delayed_work(struct delayed_work *dwork, int jiffies)
|
|
|
|
{
|
|
|
|
dwork->tq = (struct taskq *)system_wq;
|
|
|
|
return timeout_add(&dwork->to, jiffies);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
queue_delayed_work(struct workqueue_struct *wq,
|
|
|
|
struct delayed_work *dwork, int jiffies)
|
|
|
|
{
|
|
|
|
dwork->tq = (struct taskq *)wq;
|
|
|
|
return timeout_add(&dwork->to, jiffies);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
mod_delayed_work(struct workqueue_struct *wq,
|
|
|
|
struct delayed_work *dwork, int jiffies)
|
|
|
|
{
|
|
|
|
dwork->tq = (struct taskq *)wq;
|
|
|
|
return (timeout_add(&dwork->to, jiffies) == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
cancel_delayed_work(struct delayed_work *dwork)
|
|
|
|
{
|
|
|
|
if (dwork->tq == NULL)
|
|
|
|
return false;
|
|
|
|
if (timeout_del(&dwork->to))
|
|
|
|
return true;
|
|
|
|
return task_del(dwork->tq, &dwork->work.task);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
cancel_delayed_work_sync(struct delayed_work *dwork)
|
|
|
|
{
|
|
|
|
if (dwork->tq == NULL)
|
|
|
|
return false;
|
|
|
|
if (timeout_del(&dwork->to))
|
|
|
|
return true;
|
|
|
|
return task_del(dwork->tq, &dwork->work.task);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
delayed_work_pending(struct delayed_work *dwork)
|
|
|
|
{
|
|
|
|
if (timeout_pending(&dwork->to))
|
|
|
|
return true;
|
|
|
|
return task_pending(&dwork->work.task);
|
|
|
|
}
|
|
|
|
|
|
|
|
void flush_workqueue(struct workqueue_struct *);
|
|
|
|
bool flush_work(struct work_struct *);
|
|
|
|
bool flush_delayed_work(struct delayed_work *);
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
flush_scheduled_work(void)
|
|
|
|
{
|
|
|
|
flush_workqueue(system_wq);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
drain_workqueue(struct workqueue_struct *wq)
|
|
|
|
{
|
|
|
|
flush_workqueue(wq);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
destroy_work_on_stack(struct work_struct *work)
|
|
|
|
{
|
|
|
|
if (work->tq)
|
|
|
|
task_del(work->tq, &work->task);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
destroy_delayed_work_on_stack(struct delayed_work *dwork)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
struct rcu_work {
|
|
|
|
struct work_struct work;
|
|
|
|
struct rcu_head rcu;
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
INIT_RCU_WORK(struct rcu_work *work, work_func_t func)
|
|
|
|
{
|
|
|
|
INIT_WORK(&work->work, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool
|
|
|
|
queue_rcu_work(struct workqueue_struct *wq, struct rcu_work *work)
|
|
|
|
{
|
|
|
|
return queue_work(wq, &work->work);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|