xref: /dflybsd-src/sys/dev/drm/include/linux/sched.h (revision 789731325bde747251c28a37e0a00ed4efb88c46)
139cfddd2SFrançois Tigeot /*
296e4903bSFrançois Tigeot  * Copyright (c) 2015-2020 François Tigeot <ftigeot@wolfpond.org>
33f2dd94aSFrançois Tigeot  * Copyright (c) 2019-2020 Matthew Dillon <dillon@backplane.com>
48c49d0deSFrançois Tigeot  * All rights reserved.
58c49d0deSFrançois Tigeot  *
68c49d0deSFrançois Tigeot  * Redistribution and use in source and binary forms, with or without
78c49d0deSFrançois Tigeot  * modification, are permitted provided that the following conditions
88c49d0deSFrançois Tigeot  * are met:
98c49d0deSFrançois Tigeot  * 1. Redistributions of source code must retain the above copyright
108c49d0deSFrançois Tigeot  *    notice unmodified, this list of conditions, and the following
118c49d0deSFrançois Tigeot  *    disclaimer.
128c49d0deSFrançois Tigeot  * 2. Redistributions in binary form must reproduce the above copyright
138c49d0deSFrançois Tigeot  *    notice, this list of conditions and the following disclaimer in the
148c49d0deSFrançois Tigeot  *    documentation and/or other materials provided with the distribution.
158c49d0deSFrançois Tigeot  *
168c49d0deSFrançois Tigeot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
178c49d0deSFrançois Tigeot  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
188c49d0deSFrançois Tigeot  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
198c49d0deSFrançois Tigeot  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
208c49d0deSFrançois Tigeot  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
218c49d0deSFrançois Tigeot  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
228c49d0deSFrançois Tigeot  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
238c49d0deSFrançois Tigeot  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
248c49d0deSFrançois Tigeot  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
258c49d0deSFrançois Tigeot  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
268c49d0deSFrançois Tigeot  */
278c49d0deSFrançois Tigeot 
288c49d0deSFrançois Tigeot #ifndef	_LINUX_SCHED_H_
298c49d0deSFrançois Tigeot #define	_LINUX_SCHED_H_
308c49d0deSFrançois Tigeot 
315915b712SFrançois Tigeot #include <linux/capability.h>
32d6aa1cc5SFrançois Tigeot #include <linux/threads.h>
335915b712SFrançois Tigeot #include <linux/kernel.h>
345915b712SFrançois Tigeot #include <linux/types.h>
355915b712SFrançois Tigeot #include <linux/jiffies.h>
36eaf74c33SFrançois Tigeot #include <linux/rbtree.h>
374757df22SFrançois Tigeot #include <linux/thread_info.h>
38d6aa1cc5SFrançois Tigeot #include <linux/cpumask.h>
395915b712SFrançois Tigeot #include <linux/errno.h>
40d6aa1cc5SFrançois Tigeot #include <linux/mm_types.h>
41237ffc69SFrançois Tigeot #include <linux/preempt.h>
425915b712SFrançois Tigeot 
435915b712SFrançois Tigeot #include <asm/page.h>
445915b712SFrançois Tigeot 
45111dab5bSFrançois Tigeot #include <linux/smp.h>
465915b712SFrançois Tigeot #include <linux/compiler.h>
475915b712SFrançois Tigeot #include <linux/completion.h>
48d6aa1cc5SFrançois Tigeot #include <linux/pid.h>
49d6aa1cc5SFrançois Tigeot #include <linux/rcupdate.h>
505915b712SFrançois Tigeot #include <linux/rculist.h>
515915b712SFrançois Tigeot 
525915b712SFrançois Tigeot #include <linux/time.h>
535915b712SFrançois Tigeot #include <linux/timer.h>
545915b712SFrançois Tigeot #include <linux/hrtimer.h>
551382b9d0SFrançois Tigeot #include <linux/llist.h>
565915b712SFrançois Tigeot #include <linux/gfp.h>
575915b712SFrançois Tigeot 
58c6002f72SFrançois Tigeot #include <asm/processor.h>
59c6002f72SFrançois Tigeot 
6043cc53d1SFrançois Tigeot #include <linux/spinlock.h>
6143cc53d1SFrançois Tigeot 
628c49d0deSFrançois Tigeot #include <sys/param.h>
638c49d0deSFrançois Tigeot #include <sys/systm.h>
648c49d0deSFrançois Tigeot #include <sys/proc.h>
658c49d0deSFrançois Tigeot #include <sys/sched.h>
66861f7f60SFrançois Tigeot #include <sys/signal2.h>
678c49d0deSFrançois Tigeot 
68d4d2d20bSFrançois Tigeot #include <machine/cpu.h>
69d4d2d20bSFrançois Tigeot 
701dedbd3bSFrançois Tigeot struct seq_file;
711dedbd3bSFrançois Tigeot 
728c49d0deSFrançois Tigeot #define	TASK_RUNNING		0
738c49d0deSFrançois Tigeot #define	TASK_INTERRUPTIBLE	1
748c49d0deSFrançois Tigeot #define	TASK_UNINTERRUPTIBLE	2
758c49d0deSFrançois Tigeot 
76d658c120SFrançois Tigeot #define TASK_NORMAL		(TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)
77d658c120SFrançois Tigeot 
781e8d33eeSFrançois Tigeot #define MAX_SCHEDULE_TIMEOUT    LONG_MAX
791e8d33eeSFrançois Tigeot 
80a85cb24fSFrançois Tigeot #define TASK_COMM_LEN	MAXCOMLEN
81a85cb24fSFrançois Tigeot 
821487f786SFrançois Tigeot struct task_struct {
831487f786SFrançois Tigeot 	struct thread *dfly_td;
841487f786SFrançois Tigeot 	volatile long state;
851487f786SFrançois Tigeot 	struct mm_struct *mm;	/* mirror copy in p->p_linux_mm */
861487f786SFrançois Tigeot 	int prio;
87aa2693a5SFrançois Tigeot 
88aa2693a5SFrançois Tigeot 	/* kthread-specific data */
89aa2693a5SFrançois Tigeot 	unsigned long		kt_flags;
90aa2693a5SFrançois Tigeot 	int			(*kt_fn)(void *data);
91aa2693a5SFrançois Tigeot 	void			*kt_fndata;
92aa2693a5SFrançois Tigeot 	int			kt_exitvalue;
93a85cb24fSFrançois Tigeot 
94a85cb24fSFrançois Tigeot 	/* executable name without path */
95a85cb24fSFrançois Tigeot 	char			comm[TASK_COMM_LEN];
963f2dd94aSFrançois Tigeot 
973f2dd94aSFrançois Tigeot 	atomic_t usage_counter;
983f2dd94aSFrançois Tigeot 	pid_t pid;
993f2dd94aSFrançois Tigeot 	struct spinlock		kt_spin;
1001487f786SFrançois Tigeot };
1011487f786SFrançois Tigeot 
1023b66ff82SFrançois Tigeot #define __set_current_state(state_value)	current->state = (state_value);
1033b66ff82SFrançois Tigeot 
1043b66ff82SFrançois Tigeot #define set_current_state(state_value)		\
1053b66ff82SFrançois Tigeot do {						\
1063b66ff82SFrançois Tigeot 	__set_current_state(state_value);	\
1073b66ff82SFrançois Tigeot 	mb();					\
1083b66ff82SFrançois Tigeot } while (0)
1093b66ff82SFrançois Tigeot 
1108c49d0deSFrançois Tigeot /*
1111e8d33eeSFrançois Tigeot  * schedule_timeout: puts the current thread to sleep until timeout
1121e8d33eeSFrançois Tigeot  * if its state allows it to.
1138c49d0deSFrançois Tigeot  */
1148c49d0deSFrançois Tigeot static inline long
schedule_timeout(signed long timeout)1158c49d0deSFrançois Tigeot schedule_timeout(signed long timeout)
1168c49d0deSFrançois Tigeot {
1171e8d33eeSFrançois Tigeot 	unsigned long time_before, time_after;
1181e8d33eeSFrançois Tigeot 	long slept, ret = 0;
1191e8d33eeSFrançois Tigeot 	int timo;
1208c49d0deSFrançois Tigeot 
1218c49d0deSFrançois Tigeot 	if (timeout < 0) {
1228c49d0deSFrançois Tigeot 		kprintf("schedule_timeout(): timeout cannot be negative\n");
1231e8d33eeSFrançois Tigeot 		goto done;
1248c49d0deSFrançois Tigeot 	}
1258c49d0deSFrançois Tigeot 
1261e8d33eeSFrançois Tigeot 	/*
1271e8d33eeSFrançois Tigeot 	 * Indefinite wait if timeout is MAX_SCHEDULE_TIMEOUT, but we are
1281e8d33eeSFrançois Tigeot 	 * also translating to an integer.  The first conditional will
1291e8d33eeSFrançois Tigeot 	 * cover both but to code defensively test both.
1301e8d33eeSFrançois Tigeot 	 */
1311e8d33eeSFrançois Tigeot 	if (timeout >= INT_MAX || timeout == MAX_SCHEDULE_TIMEOUT)
1321e8d33eeSFrançois Tigeot 		timo = 0;
1331e8d33eeSFrançois Tigeot 	else
1341e8d33eeSFrançois Tigeot 		timo = timeout;
1358c49d0deSFrançois Tigeot 
1363f2dd94aSFrançois Tigeot 	spin_lock(&current->kt_spin);
1373f2dd94aSFrançois Tigeot 
1381e8d33eeSFrançois Tigeot 	switch (current->state) {
1391e8d33eeSFrançois Tigeot 	case TASK_INTERRUPTIBLE:
1400657583bSFrançois Tigeot 		time_before = ticks;
1413f2dd94aSFrançois Tigeot 		ssleep(current, &current->kt_spin, PCATCH, "lstim", timo);
1420657583bSFrançois Tigeot 		time_after = ticks;
1431e8d33eeSFrançois Tigeot 		slept = time_after - time_before;
1441e8d33eeSFrançois Tigeot 		ret = timeout - slept;
1451e8d33eeSFrançois Tigeot 		if (ret < 0)
1461e8d33eeSFrançois Tigeot 			ret = 0;
1471e8d33eeSFrançois Tigeot 		break;
1481e8d33eeSFrançois Tigeot 	case TASK_UNINTERRUPTIBLE:
1493f2dd94aSFrançois Tigeot 		ssleep(current, &current->kt_spin, 0, "lstim", timo);
1501e8d33eeSFrançois Tigeot 		break;
1511e8d33eeSFrançois Tigeot 	default:
1523f2dd94aSFrançois Tigeot 		/*
1533f2dd94aSFrançois Tigeot 		 * Task has been flagged running before we could
1543f2dd94aSFrançois Tigeot 		 * enter the sleep.
1553f2dd94aSFrançois Tigeot 		 *
1563f2dd94aSFrançois Tigeot 		 * XXX should be able to remove this ssleep(), have it
1573f2dd94aSFrançois Tigeot 		 * here to protect against live-locks in case we mess
1583f2dd94aSFrançois Tigeot 		 * up the task->state.
1593f2dd94aSFrançois Tigeot 		 */
1603f2dd94aSFrançois Tigeot 		ssleep(current, &current->kt_spin, 0, "lst1", 1);
1611e8d33eeSFrançois Tigeot 		break;
1621e8d33eeSFrançois Tigeot 	}
1631e8d33eeSFrançois Tigeot 
1643f2dd94aSFrançois Tigeot 	spin_unlock(&current->kt_spin);
1653f2dd94aSFrançois Tigeot 
1661e8d33eeSFrançois Tigeot done:
1671e8d33eeSFrançois Tigeot 	if (timeout == MAX_SCHEDULE_TIMEOUT)
1681e8d33eeSFrançois Tigeot 		ret = MAX_SCHEDULE_TIMEOUT;
1691e8d33eeSFrançois Tigeot 
1701e8d33eeSFrançois Tigeot 	current->state = TASK_RUNNING;
1711e8d33eeSFrançois Tigeot 	return ret;
1728c49d0deSFrançois Tigeot }
1738c49d0deSFrançois Tigeot 
174d4d2d20bSFrançois Tigeot static inline void
schedule(void)175d4d2d20bSFrançois Tigeot schedule(void)
176d4d2d20bSFrançois Tigeot {
177d4d2d20bSFrançois Tigeot 	(void)schedule_timeout(MAX_SCHEDULE_TIMEOUT);
178d4d2d20bSFrançois Tigeot }
179d4d2d20bSFrançois Tigeot 
1803b66ff82SFrançois Tigeot static inline signed long
schedule_timeout_uninterruptible(signed long timeout)1813b66ff82SFrançois Tigeot schedule_timeout_uninterruptible(signed long timeout)
1823b66ff82SFrançois Tigeot {
1833b66ff82SFrançois Tigeot 	__set_current_state(TASK_UNINTERRUPTIBLE);
1843b66ff82SFrançois Tigeot 	return schedule_timeout(timeout);
1853b66ff82SFrançois Tigeot }
1863b66ff82SFrançois Tigeot 
1870713b2cdSFrançois Tigeot static inline long
io_schedule_timeout(signed long timeout)1880713b2cdSFrançois Tigeot io_schedule_timeout(signed long timeout)
1890713b2cdSFrançois Tigeot {
1900713b2cdSFrançois Tigeot 	return schedule_timeout(timeout);
1910713b2cdSFrançois Tigeot }
1920713b2cdSFrançois Tigeot 
193282d6506SFrançois Tigeot /*
194282d6506SFrançois Tigeot  * local_clock: fast time source, monotonic on the same cpu
195282d6506SFrançois Tigeot  */
196282d6506SFrançois Tigeot static inline uint64_t
local_clock(void)197282d6506SFrançois Tigeot local_clock(void)
198282d6506SFrançois Tigeot {
199282d6506SFrançois Tigeot 	struct timespec ts;
200282d6506SFrançois Tigeot 
201282d6506SFrançois Tigeot 	getnanouptime(&ts);
202282d6506SFrançois Tigeot 	return (ts.tv_sec * NSEC_PER_SEC) + ts.tv_nsec;
203282d6506SFrançois Tigeot }
204282d6506SFrançois Tigeot 
20539cfddd2SFrançois Tigeot static inline void
yield(void)20639cfddd2SFrançois Tigeot yield(void)
20739cfddd2SFrançois Tigeot {
20839cfddd2SFrançois Tigeot 	lwkt_yield();
20939cfddd2SFrançois Tigeot }
21039cfddd2SFrançois Tigeot 
211be7d0317SFrançois Tigeot static inline int
wake_up_process(struct task_struct * tsk)2121e8d33eeSFrançois Tigeot wake_up_process(struct task_struct *tsk)
2131e8d33eeSFrançois Tigeot {
2143f2dd94aSFrançois Tigeot 	long ostate;
2153f2dd94aSFrançois Tigeot 
2163f2dd94aSFrançois Tigeot 	/*
2173f2dd94aSFrançois Tigeot 	 * Among other things, this function is supposed to act as
2183f2dd94aSFrançois Tigeot 	 * a barrier
2193f2dd94aSFrançois Tigeot 	 */
220be7d0317SFrançois Tigeot 	smp_wmb();
2213f2dd94aSFrançois Tigeot 	spin_lock(&tsk->kt_spin);
2223f2dd94aSFrançois Tigeot 	ostate = tsk->state;
2233f2dd94aSFrançois Tigeot 	tsk->state = TASK_RUNNING;
2243f2dd94aSFrançois Tigeot 	spin_unlock(&tsk->kt_spin);
225*78973132SSergey Zigachev 	/* if (ostate != TASK_RUNNING) */
2261e8d33eeSFrançois Tigeot 	wakeup(tsk);
227be7d0317SFrançois Tigeot 
228d658c120SFrançois Tigeot 	return 1;	/* Always indicate the process was woken up */
229be7d0317SFrançois Tigeot }
230be7d0317SFrançois Tigeot 
231ce723fceSFrançois Tigeot static inline int
signal_pending(struct task_struct * p)2321e8d33eeSFrançois Tigeot signal_pending(struct task_struct *p)
233ce723fceSFrançois Tigeot {
2340e32b8c5SMatthew Dillon 	struct thread *t = p->dfly_td;
2351e8d33eeSFrançois Tigeot 
23678b84d65SFrançois Tigeot 	/* Some kernel threads do not have lwp, t->td_lwp can be NULL */
23778b84d65SFrançois Tigeot 	if (t->td_lwp == NULL)
23878b84d65SFrançois Tigeot 		return 0;
23978b84d65SFrançois Tigeot 
2401e8d33eeSFrançois Tigeot 	return CURSIG(t->td_lwp);
2411e8d33eeSFrançois Tigeot }
2421e8d33eeSFrançois Tigeot 
2431e8d33eeSFrançois Tigeot static inline int
fatal_signal_pending(struct task_struct * p)24478b84d65SFrançois Tigeot fatal_signal_pending(struct task_struct *p)
24578b84d65SFrançois Tigeot {
2460e32b8c5SMatthew Dillon 	struct thread *t = p->dfly_td;
24778b84d65SFrançois Tigeot 	sigset_t pending_set;
24878b84d65SFrançois Tigeot 
24978b84d65SFrançois Tigeot 	/* Some kernel threads do not have lwp, t->td_lwp can be NULL */
25078b84d65SFrançois Tigeot 	if (t->td_lwp == NULL)
25178b84d65SFrançois Tigeot 		return 0;
25278b84d65SFrançois Tigeot 
25378b84d65SFrançois Tigeot 	pending_set = lwp_sigpend(t->td_lwp);
25478b84d65SFrançois Tigeot 	return SIGISMEMBER(pending_set, SIGKILL);
25578b84d65SFrançois Tigeot }
25678b84d65SFrançois Tigeot 
25778b84d65SFrançois Tigeot static inline int
signal_pending_state(long state,struct task_struct * p)2581e8d33eeSFrançois Tigeot signal_pending_state(long state, struct task_struct *p)
2591e8d33eeSFrançois Tigeot {
26078b84d65SFrançois Tigeot 	if (state & TASK_INTERRUPTIBLE)
26178b84d65SFrançois Tigeot 		return (signal_pending(p));
26278b84d65SFrançois Tigeot 	else
26378b84d65SFrançois Tigeot 		return (fatal_signal_pending(p));
264536555abSMatthew Dillon }
265ce723fceSFrançois Tigeot 
266ff14819bSFrançois Tigeot /* Explicit rescheduling in order to reduce latency */
267ff14819bSFrançois Tigeot static inline int
cond_resched(void)268ff14819bSFrançois Tigeot cond_resched(void)
269ff14819bSFrançois Tigeot {
270ff14819bSFrançois Tigeot 	lwkt_yield();
271ff14819bSFrançois Tigeot 	return 0;
272ff14819bSFrançois Tigeot }
273ff14819bSFrançois Tigeot 
274c58e4e0aSFrançois Tigeot static inline int
send_sig(int sig,struct proc * p,int priv)275c58e4e0aSFrançois Tigeot send_sig(int sig, struct proc *p, int priv)
276c58e4e0aSFrançois Tigeot {
277c58e4e0aSFrançois Tigeot 	ksignal(p, sig);
278c58e4e0aSFrançois Tigeot 	return 0;
279c58e4e0aSFrançois Tigeot }
280c58e4e0aSFrançois Tigeot 
281a34b4168SMatthew Dillon static inline void
set_need_resched(void)282a34b4168SMatthew Dillon set_need_resched(void)
283a34b4168SMatthew Dillon {
284a34b4168SMatthew Dillon 	/* do nothing for now */
285a34b4168SMatthew Dillon 	/* used on ttm_bo_reserve failures */
286a34b4168SMatthew Dillon }
287a34b4168SMatthew Dillon 
288d4d2d20bSFrançois Tigeot static inline bool
need_resched(void)289d4d2d20bSFrançois Tigeot need_resched(void)
290d4d2d20bSFrançois Tigeot {
291d4d2d20bSFrançois Tigeot 	return any_resched_wanted();
292d4d2d20bSFrançois Tigeot }
293d4d2d20bSFrançois Tigeot 
294d4d2d20bSFrançois Tigeot static inline int
sched_setscheduler_nocheck(struct task_struct * ts,int policy,const struct sched_param * param)295d4d2d20bSFrançois Tigeot sched_setscheduler_nocheck(struct task_struct *ts,
296d4d2d20bSFrançois Tigeot 			   int policy, const struct sched_param *param)
297d4d2d20bSFrançois Tigeot {
298d4d2d20bSFrançois Tigeot 	/* We do not allow different thread scheduling policies */
299d4d2d20bSFrançois Tigeot 	return 0;
300d4d2d20bSFrançois Tigeot }
301d4d2d20bSFrançois Tigeot 
30296e4903bSFrançois Tigeot static inline int
pagefault_disabled(void)30396e4903bSFrançois Tigeot pagefault_disabled(void)
30496e4903bSFrançois Tigeot {
30596e4903bSFrançois Tigeot 	return (curthread->td_flags & TDF_NOFAULT);
30696e4903bSFrançois Tigeot }
30796e4903bSFrançois Tigeot 
308a85cb24fSFrançois Tigeot static inline void
mmgrab(struct mm_struct * mm)309a85cb24fSFrançois Tigeot mmgrab(struct mm_struct *mm)
310a85cb24fSFrançois Tigeot {
311a85cb24fSFrançois Tigeot 	atomic_inc(&mm->mm_count);
312a85cb24fSFrançois Tigeot }
313a85cb24fSFrançois Tigeot 
3148c49d0deSFrançois Tigeot #endif	/* _LINUX_SCHED_H_ */
315