Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102742013
D19565.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D19565.diff
View Options
Index: sys/compat/linuxkpi/common/include/linux/fs.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/fs.h
+++ sys/compat/linuxkpi/common/include/linux/fs.h
@@ -323,4 +323,13 @@
#define shmem_truncate_range(...) \
linux_shmem_truncate_range(__VA_ARGS__)
+static inline int
+simple_open(struct inode *inode, struct file *file)
+{
+
+ if (inode->i_private)
+ file->private_data = inode->i_private;
+ return (0);
+}
+
#endif /* _LINUX_FS_H_ */
Index: sys/compat/linuxkpi/common/include/linux/interrupt.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/interrupt.h
+++ sys/compat/linuxkpi/common/include/linux/interrupt.h
@@ -189,11 +189,14 @@
struct tasklet_struct {
TAILQ_ENTRY(tasklet_struct) entry;
tasklet_func_t *func;
+ /* Our state implementation is different. Avoid same name as Linux. */
+ volatile u_int _state;
+ atomic_t count;
unsigned long data;
};
#define DECLARE_TASKLET(name, func, data) \
-struct tasklet_struct name = { { NULL, NULL }, func, data }
+struct tasklet_struct name = { { NULL, NULL }, func, ATOMIC_INIT(0), data }
#define tasklet_hi_schedule(t) tasklet_schedule(t)
@@ -202,6 +205,10 @@
extern void tasklet_init(struct tasklet_struct *, tasklet_func_t *,
unsigned long data);
extern void tasklet_enable(struct tasklet_struct *);
+extern bool tasklet_is_enabled(struct tasklet_struct *);
extern void tasklet_disable(struct tasklet_struct *);
+extern int tasklet_trylock(struct tasklet_struct *);
+extern void tasklet_unlock(struct tasklet_struct *);
+extern void tasklet_unlock_wait(struct tasklet_struct *ts);
#endif /* _LINUX_INTERRUPT_H_ */
Index: sys/compat/linuxkpi/common/include/linux/preempt.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/preempt.h
+++ sys/compat/linuxkpi/common/include/linux/preempt.h
@@ -34,6 +34,9 @@
#define in_interrupt() \
(curthread->td_intr_nesting_level || curthread->td_critnest)
+#define in_task() \
+ (curthread->td_intr_nesting_level == 0 && curthread->td_critnest == 0)
+
#define preempt_disable() critical_enter()
#define preempt_enable() critical_exit()
Index: sys/compat/linuxkpi/common/include/linux/sched.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/sched.h
+++ sys/compat/linuxkpi/common/include/linux/sched.h
@@ -80,6 +80,7 @@
int rcu_recurse;
int bsd_interrupt_value;
struct work_struct *work; /* current work struct, if set */
+ struct task_struct *group_leader;
};
#define current ({ \
Index: sys/compat/linuxkpi/common/include/linux/uaccess.h
===================================================================
--- sys/compat/linuxkpi/common/include/linux/uaccess.h
+++ sys/compat/linuxkpi/common/include/linux/uaccess.h
@@ -60,12 +60,17 @@
#define get_user(_x, _p) linux_copyin((_p), &(_x), sizeof(*(_p)))
#define put_user(_x, _p) __put_user(_x, _p)
#define clear_user(...) linux_clear_user(__VA_ARGS__)
-#define access_ok(...) linux_access_ok(__VA_ARGS__)
+
+#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 50000
+#define access_ok(a,b) linux_access_ok(a,b)
+#else
+#define access_ok(a,b,c) linux_access_ok(b,c)
+#endif
extern int linux_copyin(const void *uaddr, void *kaddr, size_t len);
extern int linux_copyout(const void *kaddr, void *uaddr, size_t len);
extern size_t linux_clear_user(void *uaddr, size_t len);
-extern int linux_access_ok(int rw, const void *uaddr, size_t len);
+extern int linux_access_ok(const void *uaddr, size_t len);
/*
* NOTE: Each pagefault_disable() call must have a corresponding
Index: sys/compat/linuxkpi/common/src/linux_compat.c
===================================================================
--- sys/compat/linuxkpi/common/src/linux_compat.c
+++ sys/compat/linuxkpi/common/src/linux_compat.c
@@ -897,7 +897,7 @@
}
int
-linux_access_ok(int rw, const void *uaddr, size_t len)
+linux_access_ok(const void *uaddr, size_t len)
{
uintptr_t saddr;
uintptr_t eaddr;
Index: sys/compat/linuxkpi/common/src/linux_current.c
===================================================================
--- sys/compat/linuxkpi/common/src/linux_current.c
+++ sys/compat/linuxkpi/common/src/linux_current.c
@@ -67,6 +67,7 @@
ts->task_thread = td;
ts->comm = td->td_name;
ts->pid = td->td_tid;
+ ts->group_leader = ts;
atomic_set(&ts->usage, 1);
atomic_set(&ts->state, TASK_RUNNING);
init_completion(&ts->parked);
Index: sys/compat/linuxkpi/common/src/linux_tasklet.c
===================================================================
--- sys/compat/linuxkpi/common/src/linux_tasklet.c
+++ sys/compat/linuxkpi/common/src/linux_tasklet.c
@@ -41,20 +41,22 @@
#define TASKLET_ST_BUSY 1
#define TASKLET_ST_EXEC 2
#define TASKLET_ST_LOOP 3
-#define TASKLET_ST_PAUSED 4
#define TASKLET_ST_CMPSET(ts, old, new) \
- atomic_cmpset_ptr((volatile uintptr_t *)&(ts)->entry.tqe_prev, old, new)
+ atomic_cmpset_int((volatile u_int *)&(ts)->_state, old, new)
#define TASKLET_ST_SET(ts, new) \
- WRITE_ONCE(*(volatile uintptr_t *)&(ts)->entry.tqe_prev, new)
+ WRITE_ONCE(*(volatile u_int *)&(ts)->_state, new)
#define TASKLET_ST_GET(ts) \
- READ_ONCE(*(volatile uintptr_t *)&(ts)->entry.tqe_prev)
+ READ_ONCE(*(volatile u_int *)&(ts)->_state)
+
+#define TASKLET_ST_TESTANDSET(ts, new) \
+ atomic_testandset_int((volatile u_int *)&(ts)->_state, new)
struct tasklet_worker {
struct mtx mtx;
- TAILQ_HEAD(, tasklet_struct) head;
+ TAILQ_HEAD(tasklet_list, tasklet_struct) head;
struct grouptask gtask;
} __aligned(CACHE_LINE_SIZE);
@@ -68,25 +70,34 @@
{
struct tasklet_worker *tw = (struct tasklet_worker *)arg;
struct tasklet_struct *ts;
+ struct tasklet_struct *last;
linux_set_current(curthread);
TASKLET_WORKER_LOCK(tw);
+ last = TAILQ_LAST(&tw->head, tasklet_list);
while (1) {
ts = TAILQ_FIRST(&tw->head);
if (ts == NULL)
break;
TAILQ_REMOVE(&tw->head, ts, entry);
- TASKLET_WORKER_UNLOCK(tw);
- do {
- /* reset executing state */
- TASKLET_ST_SET(ts, TASKLET_ST_EXEC);
-
- ts->func(ts->data);
-
- } while (TASKLET_ST_CMPSET(ts, TASKLET_ST_EXEC, TASKLET_ST_IDLE) == 0);
- TASKLET_WORKER_LOCK(tw);
+ if (!atomic_read(&ts->count)) {
+ TASKLET_WORKER_UNLOCK(tw);
+ do {
+ /* reset executing state */
+ TASKLET_ST_SET(ts, TASKLET_ST_EXEC);
+
+ ts->func(ts->data);
+
+ } while (TASKLET_ST_CMPSET(ts, TASKLET_ST_EXEC,
+ TASKLET_ST_IDLE) == 0);
+ TASKLET_WORKER_LOCK(tw);
+ } else {
+ TAILQ_INSERT_TAIL(&tw->head, ts, entry);
+ }
+ if (ts == last)
+ break;
}
TASKLET_WORKER_UNLOCK(tw);
}
@@ -140,6 +151,8 @@
ts->entry.tqe_next = NULL;
ts->func = func;
ts->data = data;
+ atomic_set_int(&(ts)->_state, TASKLET_ST_IDLE);
+ atomic_set(&ts->count, 0);
}
void
@@ -158,6 +171,10 @@
tasklet_schedule(struct tasklet_struct *ts)
{
+ /* tasklet is paused */
+ if (atomic_read(&ts->count))
+ return;
+
if (TASKLET_ST_CMPSET(ts, TASKLET_ST_EXEC, TASKLET_ST_LOOP)) {
/* tasklet_handler() will loop */
} else if (TASKLET_ST_CMPSET(ts, TASKLET_ST_IDLE, TASKLET_ST_BUSY)) {
@@ -201,17 +218,47 @@
void
tasklet_enable(struct tasklet_struct *ts)
{
- (void) TASKLET_ST_CMPSET(ts, TASKLET_ST_PAUSED, TASKLET_ST_IDLE);
+
+ atomic_dec(&ts->count);
+}
+
+bool
+tasklet_is_enabled(struct tasklet_struct *ts)
+{
+
+ return !atomic_read(&ts->count);
}
void
tasklet_disable(struct tasklet_struct *ts)
{
- while (1) {
- if (TASKLET_ST_GET(ts) == TASKLET_ST_PAUSED)
- break;
- if (TASKLET_ST_CMPSET(ts, TASKLET_ST_IDLE, TASKLET_ST_PAUSED))
- break;
+
+ atomic_inc(&ts->count);
+ tasklet_unlock_wait(ts);
+ mb();
+}
+
+int
+tasklet_trylock(struct tasklet_struct *ts)
+{
+
+ return (!TASKLET_ST_TESTANDSET(ts, TASKLET_ST_BUSY));
+}
+
+void
+tasklet_unlock(struct tasklet_struct *ts)
+{
+
+ TASKLET_ST_SET(ts, TASKLET_ST_IDLE);
+}
+
+void
+tasklet_unlock_wait(struct tasklet_struct *ts)
+{
+
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "tasklet_kill() can sleep");
+
+ /* wait until tasklet is no longer busy */
+ while (TASKLET_ST_GET(ts) != TASKLET_ST_IDLE)
pause("W", 1);
- }
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Nov 17, 2:29 PM (22 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14680109
Default Alt Text
D19565.diff (8 KB)
Attached To
Mode
D19565: linuxkpi v5.0 updates
Attached
Detach File
Event Timeline
Log In to Comment