1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <kernel.h>
7 #include <ksched.h>
8 #include <spinlock.h>
9 #include <kernel/sched_priq.h>
10 #include <wait_q.h>
11 #include <kswap.h>
12 #include <kernel_arch_func.h>
13 #include <syscall_handler.h>
14 #include <drivers/timer/system_timer.h>
15 #include <stdbool.h>
16 #include <kernel_internal.h>
17 #include <logging/log.h>
18 #include <sys/atomic.h>
19 LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
20 
21 #if defined(CONFIG_SCHED_DUMB)
22 #define _priq_run_add		z_priq_dumb_add
23 #define _priq_run_remove	z_priq_dumb_remove
24 # if defined(CONFIG_SCHED_CPU_MASK)
25 #  define _priq_run_best	_priq_dumb_mask_best
26 # else
27 #  define _priq_run_best	z_priq_dumb_best
28 # endif
29 #elif defined(CONFIG_SCHED_SCALABLE)
30 #define _priq_run_add		z_priq_rb_add
31 #define _priq_run_remove	z_priq_rb_remove
32 #define _priq_run_best		z_priq_rb_best
33 #elif defined(CONFIG_SCHED_MULTIQ)
34 #define _priq_run_add		z_priq_mq_add
35 #define _priq_run_remove	z_priq_mq_remove
36 #define _priq_run_best		z_priq_mq_best
37 #endif
38 
39 #if defined(CONFIG_WAITQ_SCALABLE)
40 #define z_priq_wait_add		z_priq_rb_add
41 #define _priq_wait_remove	z_priq_rb_remove
42 #define _priq_wait_best		z_priq_rb_best
43 #elif defined(CONFIG_WAITQ_DUMB)
44 #define z_priq_wait_add		z_priq_dumb_add
45 #define _priq_wait_remove	z_priq_dumb_remove
46 #define _priq_wait_best		z_priq_dumb_best
47 #endif
48 
49 struct k_spinlock sched_spinlock;
50 
51 static void update_cache(int preempt_ok);
52 static void end_thread(struct k_thread *thread);
53 
is_preempt(struct k_thread * thread)54 static inline int is_preempt(struct k_thread *thread)
55 {
56 	/* explanation in kernel_struct.h */
57 	return thread->base.preempt <= _PREEMPT_THRESHOLD;
58 }
59 
is_metairq(struct k_thread * thread)60 static inline int is_metairq(struct k_thread *thread)
61 {
62 #if CONFIG_NUM_METAIRQ_PRIORITIES > 0
63 	return (thread->base.prio - K_HIGHEST_THREAD_PRIO)
64 		< CONFIG_NUM_METAIRQ_PRIORITIES;
65 #else
66 	return 0;
67 #endif
68 }
69 
70 #if CONFIG_ASSERT
is_thread_dummy(struct k_thread * thread)71 static inline bool is_thread_dummy(struct k_thread *thread)
72 {
73 	return (thread->base.thread_state & _THREAD_DUMMY) != 0U;
74 }
75 #endif
76 
77 /*
78  * Return value same as e.g. memcmp
79  * > 0 -> thread 1 priority  > thread 2 priority
80  * = 0 -> thread 1 priority == thread 2 priority
81  * < 0 -> thread 1 priority  < thread 2 priority
82  * Do not rely on the actual value returned aside from the above.
83  * (Again, like memcmp.)
84  */
z_sched_prio_cmp(struct k_thread * thread_1,struct k_thread * thread_2)85 int32_t z_sched_prio_cmp(struct k_thread *thread_1,
86 	struct k_thread *thread_2)
87 {
88 	/* `prio` is <32b, so the below cannot overflow. */
89 	int32_t b1 = thread_1->base.prio;
90 	int32_t b2 = thread_2->base.prio;
91 
92 	if (b1 != b2) {
93 		return b2 - b1;
94 	}
95 
96 #ifdef CONFIG_SCHED_DEADLINE
97 	/* If we assume all deadlines live within the same "half" of
98 	 * the 32 bit modulus space (this is a documented API rule),
99 	 * then the latest deadline in the queue minus the earliest is
100 	 * guaranteed to be (2's complement) non-negative.  We can
101 	 * leverage that to compare the values without having to check
102 	 * the current time.
103 	 */
104 	uint32_t d1 = thread_1->base.prio_deadline;
105 	uint32_t d2 = thread_2->base.prio_deadline;
106 
107 	if (d1 != d2) {
108 		/* Sooner deadline means higher effective priority.
109 		 * Doing the calculation with unsigned types and casting
110 		 * to signed isn't perfect, but at least reduces this
111 		 * from UB on overflow to impdef.
112 		 */
113 		return (int32_t) (d2 - d1);
114 	}
115 #endif
116 	return 0;
117 }
118 
should_preempt(struct k_thread * thread,int preempt_ok)119 static ALWAYS_INLINE bool should_preempt(struct k_thread *thread,
120 					 int preempt_ok)
121 {
122 	/* Preemption is OK if it's being explicitly allowed by
123 	 * software state (e.g. the thread called k_yield())
124 	 */
125 	if (preempt_ok != 0) {
126 		return true;
127 	}
128 
129 	__ASSERT(_current != NULL, "");
130 
131 	/* Or if we're pended/suspended/dummy (duh) */
132 	if (z_is_thread_prevented_from_running(_current)) {
133 		return true;
134 	}
135 
136 	/* Edge case on ARM where a thread can be pended out of an
137 	 * interrupt handler before the "synchronous" swap starts
138 	 * context switching.  Platforms with atomic swap can never
139 	 * hit this.
140 	 */
141 	if (IS_ENABLED(CONFIG_SWAP_NONATOMIC)
142 	    && z_is_thread_timeout_active(thread)) {
143 		return true;
144 	}
145 
146 	/* Otherwise we have to be running a preemptible thread or
147 	 * switching to a metairq
148 	 */
149 	if (is_preempt(_current) || is_metairq(thread)) {
150 		return true;
151 	}
152 
153 	return false;
154 }
155 
156 #ifdef CONFIG_SCHED_CPU_MASK
_priq_dumb_mask_best(sys_dlist_t * pq)157 static ALWAYS_INLINE struct k_thread *_priq_dumb_mask_best(sys_dlist_t *pq)
158 {
159 	/* With masks enabled we need to be prepared to walk the list
160 	 * looking for one we can run
161 	 */
162 	struct k_thread *thread;
163 
164 	SYS_DLIST_FOR_EACH_CONTAINER(pq, thread, base.qnode_dlist) {
165 		if ((thread->base.cpu_mask & BIT(_current_cpu->id)) != 0) {
166 			return thread;
167 		}
168 	}
169 	return NULL;
170 }
171 #endif
172 
z_priq_dumb_add(sys_dlist_t * pq,struct k_thread * thread)173 ALWAYS_INLINE void z_priq_dumb_add(sys_dlist_t *pq, struct k_thread *thread)
174 {
175 	struct k_thread *t;
176 
177 	__ASSERT_NO_MSG(!z_is_idle_thread_object(thread));
178 
179 	SYS_DLIST_FOR_EACH_CONTAINER(pq, t, base.qnode_dlist) {
180 		if (z_sched_prio_cmp(thread, t) > 0) {
181 			sys_dlist_insert(&t->base.qnode_dlist,
182 					 &thread->base.qnode_dlist);
183 			return;
184 		}
185 	}
186 
187 	sys_dlist_append(pq, &thread->base.qnode_dlist);
188 }
189 
190 /* _current is never in the run queue until context switch on
191  * SMP configurations, see z_requeue_current()
192  */
should_queue_thread(struct k_thread * th)193 static inline bool should_queue_thread(struct k_thread *th)
194 {
195 	return !IS_ENABLED(CONFIG_SMP) || th != _current;
196 }
197 
queue_thread(void * pq,struct k_thread * thread)198 static ALWAYS_INLINE void queue_thread(void *pq,
199 				       struct k_thread *thread)
200 {
201 	thread->base.thread_state |= _THREAD_QUEUED;
202 	if (should_queue_thread(thread)) {
203 		_priq_run_add(pq, thread);
204 	}
205 #ifdef CONFIG_SMP
206 	if (thread == _current) {
207 		/* add current to end of queue means "yield" */
208 		_current_cpu->swap_ok = true;
209 	}
210 #endif
211 }
212 
dequeue_thread(void * pq,struct k_thread * thread)213 static ALWAYS_INLINE void dequeue_thread(void *pq,
214 					 struct k_thread *thread)
215 {
216 	thread->base.thread_state &= ~_THREAD_QUEUED;
217 	if (should_queue_thread(thread)) {
218 		_priq_run_remove(pq, thread);
219 	}
220 }
221 
signal_pending_ipi(void)222 static void signal_pending_ipi(void)
223 {
224 	/* Synchronization note: you might think we need to lock these
225 	 * two steps, but an IPI is idempotent.  It's OK if we do it
226 	 * twice.  All we require is that if a CPU sees the flag true,
227 	 * it is guaranteed to send the IPI, and if a core sets
228 	 * pending_ipi, the IPI will be sent the next time through
229 	 * this code.
230 	 */
231 #if defined(CONFIG_SMP) && defined(CONFIG_SCHED_IPI_SUPPORTED)
232 	if (CONFIG_MP_NUM_CPUS > 1) {
233 		if (_kernel.pending_ipi) {
234 			_kernel.pending_ipi = false;
235 			arch_sched_ipi();
236 		}
237 	}
238 #endif
239 }
240 
241 #ifdef CONFIG_SMP
242 /* Called out of z_swap() when CONFIG_SMP.  The current thread can
243  * never live in the run queue until we are inexorably on the context
244  * switch path on SMP, otherwise there is a deadlock condition where a
245  * set of CPUs pick a cycle of threads to run and wait for them all to
246  * context switch forever.
247  */
z_requeue_current(struct k_thread * curr)248 void z_requeue_current(struct k_thread *curr)
249 {
250 	if (z_is_thread_queued(curr)) {
251 		_priq_run_add(&_kernel.ready_q.runq, curr);
252 	}
253 	signal_pending_ipi();
254 }
255 #endif
256 
is_aborting(struct k_thread * thread)257 static inline bool is_aborting(struct k_thread *thread)
258 {
259 	return (thread->base.thread_state & _THREAD_ABORTING) != 0U;
260 }
261 
next_up(void)262 static ALWAYS_INLINE struct k_thread *next_up(void)
263 {
264 	struct k_thread *thread;
265 
266 	thread = _priq_run_best(&_kernel.ready_q.runq);
267 
268 #if (CONFIG_NUM_METAIRQ_PRIORITIES > 0) && (CONFIG_NUM_COOP_PRIORITIES > 0)
269 	/* MetaIRQs must always attempt to return back to a
270 	 * cooperative thread they preempted and not whatever happens
271 	 * to be highest priority now. The cooperative thread was
272 	 * promised it wouldn't be preempted (by non-metairq threads)!
273 	 */
274 	struct k_thread *mirqp = _current_cpu->metairq_preempted;
275 
276 	if (mirqp != NULL && (thread == NULL || !is_metairq(thread))) {
277 		if (!z_is_thread_prevented_from_running(mirqp)) {
278 			thread = mirqp;
279 		} else {
280 			_current_cpu->metairq_preempted = NULL;
281 		}
282 	}
283 #endif
284 
285 #ifndef CONFIG_SMP
286 	/* In uniprocessor mode, we can leave the current thread in
287 	 * the queue (actually we have to, otherwise the assembly
288 	 * context switch code for all architectures would be
289 	 * responsible for putting it back in z_swap and ISR return!),
290 	 * which makes this choice simple.
291 	 */
292 	return (thread != NULL) ? thread : _current_cpu->idle_thread;
293 #else
294 	/* Under SMP, the "cache" mechanism for selecting the next
295 	 * thread doesn't work, so we have more work to do to test
296 	 * _current against the best choice from the queue.  Here, the
297 	 * thread selected above represents "the best thread that is
298 	 * not current".
299 	 *
300 	 * Subtle note on "queued": in SMP mode, _current does not
301 	 * live in the queue, so this isn't exactly the same thing as
302 	 * "ready", it means "is _current already added back to the
303 	 * queue such that we don't want to re-add it".
304 	 */
305 	if (is_aborting(_current)) {
306 		end_thread(_current);
307 	}
308 
309 	int queued = z_is_thread_queued(_current);
310 	int active = !z_is_thread_prevented_from_running(_current);
311 
312 	if (thread == NULL) {
313 		thread = _current_cpu->idle_thread;
314 	}
315 
316 	if (active) {
317 		int32_t cmp = z_sched_prio_cmp(_current, thread);
318 
319 		/* Ties only switch if state says we yielded */
320 		if ((cmp > 0) || ((cmp == 0) && !_current_cpu->swap_ok)) {
321 			thread = _current;
322 		}
323 
324 		if (!should_preempt(thread, _current_cpu->swap_ok)) {
325 			thread = _current;
326 		}
327 	}
328 
329 	/* Put _current back into the queue */
330 	if (thread != _current && active &&
331 		!z_is_idle_thread_object(_current) && !queued) {
332 		queue_thread(&_kernel.ready_q.runq, _current);
333 	}
334 
335 	/* Take the new _current out of the queue */
336 	if (z_is_thread_queued(thread)) {
337 		dequeue_thread(&_kernel.ready_q.runq, thread);
338 	}
339 
340 	_current_cpu->swap_ok = false;
341 	return thread;
342 #endif
343 }
344 
move_thread_to_end_of_prio_q(struct k_thread * thread)345 static void move_thread_to_end_of_prio_q(struct k_thread *thread)
346 {
347 	if (z_is_thread_queued(thread)) {
348 		dequeue_thread(&_kernel.ready_q.runq, thread);
349 	}
350 	queue_thread(&_kernel.ready_q.runq, thread);
351 	update_cache(thread == _current);
352 }
353 
354 #ifdef CONFIG_TIMESLICING
355 
356 static int slice_time;
357 static int slice_max_prio;
358 
359 #ifdef CONFIG_SWAP_NONATOMIC
360 /* If z_swap() isn't atomic, then it's possible for a timer interrupt
361  * to try to timeslice away _current after it has already pended
362  * itself but before the corresponding context switch.  Treat that as
363  * a noop condition in z_time_slice().
364  */
365 static struct k_thread *pending_current;
366 #endif
367 
z_reset_time_slice(void)368 void z_reset_time_slice(void)
369 {
370 	/* Add the elapsed time since the last announced tick to the
371 	 * slice count, as we'll see those "expired" ticks arrive in a
372 	 * FUTURE z_time_slice() call.
373 	 */
374 	if (slice_time != 0) {
375 		_current_cpu->slice_ticks = slice_time + sys_clock_elapsed();
376 		z_set_timeout_expiry(slice_time, false);
377 	}
378 }
379 
k_sched_time_slice_set(int32_t slice,int prio)380 void k_sched_time_slice_set(int32_t slice, int prio)
381 {
382 	LOCKED(&sched_spinlock) {
383 		_current_cpu->slice_ticks = 0;
384 		slice_time = k_ms_to_ticks_ceil32(slice);
385 		if (IS_ENABLED(CONFIG_TICKLESS_KERNEL) && slice > 0) {
386 			/* It's not possible to reliably set a 1-tick
387 			 * timeout if ticks aren't regular.
388 			 */
389 			slice_time = MAX(2, slice_time);
390 		}
391 		slice_max_prio = prio;
392 		z_reset_time_slice();
393 	}
394 }
395 
sliceable(struct k_thread * thread)396 static inline int sliceable(struct k_thread *thread)
397 {
398 	return is_preempt(thread)
399 		&& !z_is_thread_prevented_from_running(thread)
400 		&& !z_is_prio_higher(thread->base.prio, slice_max_prio)
401 		&& !z_is_idle_thread_object(thread);
402 }
403 
404 /* Called out of each timer interrupt */
z_time_slice(int ticks)405 void z_time_slice(int ticks)
406 {
407 	/* Hold sched_spinlock, so that activity on another CPU
408 	 * (like a call to k_thread_abort() at just the wrong time)
409 	 * won't affect the correctness of the decisions made here.
410 	 * Also prevents any nested interrupts from changing
411 	 * thread state to avoid similar issues, since this would
412 	 * normally run with IRQs enabled.
413 	 */
414 	k_spinlock_key_t key = k_spin_lock(&sched_spinlock);
415 
416 #ifdef CONFIG_SWAP_NONATOMIC
417 	if (pending_current == _current) {
418 		z_reset_time_slice();
419 		k_spin_unlock(&sched_spinlock, key);
420 		return;
421 	}
422 	pending_current = NULL;
423 #endif
424 
425 	if (slice_time && sliceable(_current)) {
426 		if (ticks >= _current_cpu->slice_ticks) {
427 			move_thread_to_end_of_prio_q(_current);
428 			z_reset_time_slice();
429 		} else {
430 			_current_cpu->slice_ticks -= ticks;
431 		}
432 	} else {
433 		_current_cpu->slice_ticks = 0;
434 	}
435 	k_spin_unlock(&sched_spinlock, key);
436 }
437 #endif
438 
439 /* Track cooperative threads preempted by metairqs so we can return to
440  * them specifically.  Called at the moment a new thread has been
441  * selected to run.
442  */
update_metairq_preempt(struct k_thread * thread)443 static void update_metairq_preempt(struct k_thread *thread)
444 {
445 #if (CONFIG_NUM_METAIRQ_PRIORITIES > 0) && (CONFIG_NUM_COOP_PRIORITIES > 0)
446 	if (is_metairq(thread) && !is_metairq(_current) &&
447 	    !is_preempt(_current)) {
448 		/* Record new preemption */
449 		_current_cpu->metairq_preempted = _current;
450 	} else if (!is_metairq(thread) && !z_is_idle_thread_object(thread)) {
451 		/* Returning from existing preemption */
452 		_current_cpu->metairq_preempted = NULL;
453 	}
454 #endif
455 }
456 
update_cache(int preempt_ok)457 static void update_cache(int preempt_ok)
458 {
459 #ifndef CONFIG_SMP
460 	struct k_thread *thread = next_up();
461 
462 	if (should_preempt(thread, preempt_ok)) {
463 #ifdef CONFIG_TIMESLICING
464 		if (thread != _current) {
465 			z_reset_time_slice();
466 		}
467 #endif
468 		update_metairq_preempt(thread);
469 		_kernel.ready_q.cache = thread;
470 	} else {
471 		_kernel.ready_q.cache = _current;
472 	}
473 
474 #else
475 	/* The way this works is that the CPU record keeps its
476 	 * "cooperative swapping is OK" flag until the next reschedule
477 	 * call or context switch.  It doesn't need to be tracked per
478 	 * thread because if the thread gets preempted for whatever
479 	 * reason the scheduler will make the same decision anyway.
480 	 */
481 	_current_cpu->swap_ok = preempt_ok;
482 #endif
483 }
484 
thread_active_elsewhere(struct k_thread * thread)485 static bool thread_active_elsewhere(struct k_thread *thread)
486 {
487 	/* True if the thread is currently running on another CPU.
488 	 * There are more scalable designs to answer this question in
489 	 * constant time, but this is fine for now.
490 	 */
491 #ifdef CONFIG_SMP
492 	int currcpu = _current_cpu->id;
493 
494 	for (int i = 0; i < CONFIG_MP_NUM_CPUS; i++) {
495 		if ((i != currcpu) &&
496 		    (_kernel.cpus[i].current == thread)) {
497 			return true;
498 		}
499 	}
500 #endif
501 	return false;
502 }
503 
flag_ipi(void)504 static void flag_ipi(void)
505 {
506 #if defined(CONFIG_SMP) && defined(CONFIG_SCHED_IPI_SUPPORTED)
507 	if (CONFIG_MP_NUM_CPUS > 1) {
508 		_kernel.pending_ipi = true;
509 	}
510 #endif
511 }
512 
ready_thread(struct k_thread * thread)513 static void ready_thread(struct k_thread *thread)
514 {
515 #ifdef CONFIG_KERNEL_COHERENCE
516 	__ASSERT_NO_MSG(arch_mem_coherent(thread));
517 #endif
518 
519 	/* If thread is queued already, do not try and added it to the
520 	 * run queue again
521 	 */
522 	if (!z_is_thread_queued(thread) && z_is_thread_ready(thread)) {
523 		SYS_PORT_TRACING_OBJ_FUNC(k_thread, sched_ready, thread);
524 
525 		queue_thread(&_kernel.ready_q.runq, thread);
526 		update_cache(0);
527 		flag_ipi();
528 	}
529 }
530 
z_ready_thread(struct k_thread * thread)531 void z_ready_thread(struct k_thread *thread)
532 {
533 	LOCKED(&sched_spinlock) {
534 		if (!thread_active_elsewhere(thread)) {
535 			ready_thread(thread);
536 		}
537 	}
538 }
539 
z_move_thread_to_end_of_prio_q(struct k_thread * thread)540 void z_move_thread_to_end_of_prio_q(struct k_thread *thread)
541 {
542 	LOCKED(&sched_spinlock) {
543 		move_thread_to_end_of_prio_q(thread);
544 	}
545 }
546 
z_sched_start(struct k_thread * thread)547 void z_sched_start(struct k_thread *thread)
548 {
549 	k_spinlock_key_t key = k_spin_lock(&sched_spinlock);
550 
551 	if (z_has_thread_started(thread)) {
552 		k_spin_unlock(&sched_spinlock, key);
553 		return;
554 	}
555 
556 	z_mark_thread_as_started(thread);
557 	ready_thread(thread);
558 	z_reschedule(&sched_spinlock, key);
559 }
560 
z_impl_k_thread_suspend(struct k_thread * thread)561 void z_impl_k_thread_suspend(struct k_thread *thread)
562 {
563 	SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_thread, suspend, thread);
564 
565 	(void)z_abort_thread_timeout(thread);
566 
567 	LOCKED(&sched_spinlock) {
568 		if (z_is_thread_queued(thread)) {
569 			dequeue_thread(&_kernel.ready_q.runq, thread);
570 		}
571 		z_mark_thread_as_suspended(thread);
572 		update_cache(thread == _current);
573 	}
574 
575 	if (thread == _current) {
576 		z_reschedule_unlocked();
577 	}
578 
579 	SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_thread, suspend, thread);
580 }
581 
582 #ifdef CONFIG_USERSPACE
z_vrfy_k_thread_suspend(struct k_thread * thread)583 static inline void z_vrfy_k_thread_suspend(struct k_thread *thread)
584 {
585 	Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD));
586 	z_impl_k_thread_suspend(thread);
587 }
588 #include <syscalls/k_thread_suspend_mrsh.c>
589 #endif
590 
z_impl_k_thread_resume(struct k_thread * thread)591 void z_impl_k_thread_resume(struct k_thread *thread)
592 {
593 	SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_thread, resume, thread);
594 
595 	k_spinlock_key_t key = k_spin_lock(&sched_spinlock);
596 
597 	/* Do not try to resume a thread that was not suspended */
598 	if (!z_is_thread_suspended(thread)) {
599 		k_spin_unlock(&sched_spinlock, key);
600 		return;
601 	}
602 
603 	z_mark_thread_as_not_suspended(thread);
604 	ready_thread(thread);
605 
606 	z_reschedule(&sched_spinlock, key);
607 
608 	SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_thread, resume, thread);
609 }
610 
611 #ifdef CONFIG_USERSPACE
z_vrfy_k_thread_resume(struct k_thread * thread)612 static inline void z_vrfy_k_thread_resume(struct k_thread *thread)
613 {
614 	Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD));
615 	z_impl_k_thread_resume(thread);
616 }
617 #include <syscalls/k_thread_resume_mrsh.c>
618 #endif
619 
pended_on_thread(struct k_thread * thread)620 static _wait_q_t *pended_on_thread(struct k_thread *thread)
621 {
622 	__ASSERT_NO_MSG(thread->base.pended_on);
623 
624 	return thread->base.pended_on;
625 }
626 
unready_thread(struct k_thread * thread)627 static void unready_thread(struct k_thread *thread)
628 {
629 	if (z_is_thread_queued(thread)) {
630 		dequeue_thread(&_kernel.ready_q.runq, thread);
631 	}
632 	update_cache(thread == _current);
633 }
634 
635 /* sched_spinlock must be held */
add_to_waitq_locked(struct k_thread * thread,_wait_q_t * wait_q)636 static void add_to_waitq_locked(struct k_thread *thread, _wait_q_t *wait_q)
637 {
638 	unready_thread(thread);
639 	z_mark_thread_as_pending(thread);
640 
641 	SYS_PORT_TRACING_FUNC(k_thread, sched_pend, thread);
642 
643 	if (wait_q != NULL) {
644 		thread->base.pended_on = wait_q;
645 		z_priq_wait_add(&wait_q->waitq, thread);
646 	}
647 }
648 
add_thread_timeout(struct k_thread * thread,k_timeout_t timeout)649 static void add_thread_timeout(struct k_thread *thread, k_timeout_t timeout)
650 {
651 	if (!K_TIMEOUT_EQ(timeout, K_FOREVER)) {
652 		z_add_thread_timeout(thread, timeout);
653 	}
654 }
655 
pend_locked(struct k_thread * thread,_wait_q_t * wait_q,k_timeout_t timeout)656 static void pend_locked(struct k_thread *thread, _wait_q_t *wait_q,
657 			k_timeout_t timeout)
658 {
659 #ifdef CONFIG_KERNEL_COHERENCE
660 	__ASSERT_NO_MSG(wait_q == NULL || arch_mem_coherent(wait_q));
661 #endif
662 	add_to_waitq_locked(thread, wait_q);
663 	add_thread_timeout(thread, timeout);
664 }
665 
z_pend_thread(struct k_thread * thread,_wait_q_t * wait_q,k_timeout_t timeout)666 void z_pend_thread(struct k_thread *thread, _wait_q_t *wait_q,
667 		   k_timeout_t timeout)
668 {
669 	__ASSERT_NO_MSG(thread == _current || is_thread_dummy(thread));
670 	LOCKED(&sched_spinlock) {
671 		pend_locked(thread, wait_q, timeout);
672 	}
673 }
674 
unpend_thread_no_timeout(struct k_thread * thread)675 static inline void unpend_thread_no_timeout(struct k_thread *thread)
676 {
677 	_priq_wait_remove(&pended_on_thread(thread)->waitq, thread);
678 	z_mark_thread_as_not_pending(thread);
679 	thread->base.pended_on = NULL;
680 }
681 
z_unpend_thread_no_timeout(struct k_thread * thread)682 ALWAYS_INLINE void z_unpend_thread_no_timeout(struct k_thread *thread)
683 {
684 	LOCKED(&sched_spinlock) {
685 		unpend_thread_no_timeout(thread);
686 	}
687 }
688 
689 #ifdef CONFIG_SYS_CLOCK_EXISTS
690 /* Timeout handler for *_thread_timeout() APIs */
z_thread_timeout(struct _timeout * timeout)691 void z_thread_timeout(struct _timeout *timeout)
692 {
693 	struct k_thread *thread = CONTAINER_OF(timeout,
694 					       struct k_thread, base.timeout);
695 
696 	LOCKED(&sched_spinlock) {
697 		bool killed = ((thread->base.thread_state & _THREAD_DEAD) ||
698 			       (thread->base.thread_state & _THREAD_ABORTING));
699 
700 		if (!killed) {
701 			if (thread->base.pended_on != NULL) {
702 				unpend_thread_no_timeout(thread);
703 			}
704 			z_mark_thread_as_started(thread);
705 			z_mark_thread_as_not_suspended(thread);
706 			ready_thread(thread);
707 		}
708 	}
709 }
710 #endif
711 
z_pend_curr_irqlock(uint32_t key,_wait_q_t * wait_q,k_timeout_t timeout)712 int z_pend_curr_irqlock(uint32_t key, _wait_q_t *wait_q, k_timeout_t timeout)
713 {
714 	/* This is a legacy API for pre-switch architectures and isn't
715 	 * correctly synchronized for multi-cpu use
716 	 */
717 	__ASSERT_NO_MSG(!IS_ENABLED(CONFIG_SMP));
718 
719 	pend_locked(_current, wait_q, timeout);
720 
721 #if defined(CONFIG_TIMESLICING) && defined(CONFIG_SWAP_NONATOMIC)
722 	pending_current = _current;
723 
724 	int ret = z_swap_irqlock(key);
725 	LOCKED(&sched_spinlock) {
726 		if (pending_current == _current) {
727 			pending_current = NULL;
728 		}
729 	}
730 	return ret;
731 #else
732 	return z_swap_irqlock(key);
733 #endif
734 }
735 
z_pend_curr(struct k_spinlock * lock,k_spinlock_key_t key,_wait_q_t * wait_q,k_timeout_t timeout)736 int z_pend_curr(struct k_spinlock *lock, k_spinlock_key_t key,
737 	       _wait_q_t *wait_q, k_timeout_t timeout)
738 {
739 #if defined(CONFIG_TIMESLICING) && defined(CONFIG_SWAP_NONATOMIC)
740 	pending_current = _current;
741 #endif
742 	__ASSERT_NO_MSG(sizeof(sched_spinlock) == 0 || lock != &sched_spinlock);
743 
744 	/* We do a "lock swap" prior to calling z_swap(), such that
745 	 * the caller's lock gets released as desired.  But we ensure
746 	 * that we hold the scheduler lock and leave local interrupts
747 	 * masked until we reach the context swich.  z_swap() itself
748 	 * has similar code; the duplication is because it's a legacy
749 	 * API that doesn't expect to be called with scheduler lock
750 	 * held.
751 	 */
752 	(void) k_spin_lock(&sched_spinlock);
753 	pend_locked(_current, wait_q, timeout);
754 	k_spin_release(lock);
755 	return z_swap(&sched_spinlock, key);
756 }
757 
z_unpend1_no_timeout(_wait_q_t * wait_q)758 struct k_thread *z_unpend1_no_timeout(_wait_q_t *wait_q)
759 {
760 	struct k_thread *thread = NULL;
761 
762 	LOCKED(&sched_spinlock) {
763 		thread = _priq_wait_best(&wait_q->waitq);
764 
765 		if (thread != NULL) {
766 			unpend_thread_no_timeout(thread);
767 		}
768 	}
769 
770 	return thread;
771 }
772 
z_unpend_first_thread(_wait_q_t * wait_q)773 struct k_thread *z_unpend_first_thread(_wait_q_t *wait_q)
774 {
775 	struct k_thread *thread = NULL;
776 
777 	LOCKED(&sched_spinlock) {
778 		thread = _priq_wait_best(&wait_q->waitq);
779 
780 		if (thread != NULL) {
781 			unpend_thread_no_timeout(thread);
782 			(void)z_abort_thread_timeout(thread);
783 		}
784 	}
785 
786 	return thread;
787 }
788 
z_unpend_thread(struct k_thread * thread)789 void z_unpend_thread(struct k_thread *thread)
790 {
791 	z_unpend_thread_no_timeout(thread);
792 	(void)z_abort_thread_timeout(thread);
793 }
794 
795 /* Priority set utility that does no rescheduling, it just changes the
796  * run queue state, returning true if a reschedule is needed later.
797  */
z_set_prio(struct k_thread * thread,int prio)798 bool z_set_prio(struct k_thread *thread, int prio)
799 {
800 	bool need_sched = 0;
801 
802 	LOCKED(&sched_spinlock) {
803 		need_sched = z_is_thread_ready(thread);
804 
805 		if (need_sched) {
806 			/* Don't requeue on SMP if it's the running thread */
807 			if (!IS_ENABLED(CONFIG_SMP) || z_is_thread_queued(thread)) {
808 				dequeue_thread(&_kernel.ready_q.runq, thread);
809 				thread->base.prio = prio;
810 				queue_thread(&_kernel.ready_q.runq, thread);
811 			} else {
812 				thread->base.prio = prio;
813 			}
814 			update_cache(1);
815 		} else {
816 			thread->base.prio = prio;
817 		}
818 	}
819 
820 	SYS_PORT_TRACING_OBJ_FUNC(k_thread, sched_priority_set, thread, prio);
821 
822 	return need_sched;
823 }
824 
z_thread_priority_set(struct k_thread * thread,int prio)825 void z_thread_priority_set(struct k_thread *thread, int prio)
826 {
827 	bool need_sched = z_set_prio(thread, prio);
828 
829 	flag_ipi();
830 
831 	if (need_sched && _current->base.sched_locked == 0U) {
832 		z_reschedule_unlocked();
833 	}
834 }
835 
resched(uint32_t key)836 static inline bool resched(uint32_t key)
837 {
838 #ifdef CONFIG_SMP
839 	_current_cpu->swap_ok = 0;
840 #endif
841 
842 	return arch_irq_unlocked(key) && !arch_is_in_isr();
843 }
844 
845 /*
846  * Check if the next ready thread is the same as the current thread
847  * and save the trip if true.
848  */
need_swap(void)849 static inline bool need_swap(void)
850 {
851 	/* the SMP case will be handled in C based z_swap() */
852 #ifdef CONFIG_SMP
853 	return true;
854 #else
855 	struct k_thread *new_thread;
856 
857 	/* Check if the next ready thread is the same as the current thread */
858 	new_thread = _kernel.ready_q.cache;
859 	return new_thread != _current;
860 #endif
861 }
862 
z_reschedule(struct k_spinlock * lock,k_spinlock_key_t key)863 void z_reschedule(struct k_spinlock *lock, k_spinlock_key_t key)
864 {
865 	if (resched(key.key) && need_swap()) {
866 		z_swap(lock, key);
867 	} else {
868 		k_spin_unlock(lock, key);
869 		signal_pending_ipi();
870 	}
871 }
872 
z_reschedule_irqlock(uint32_t key)873 void z_reschedule_irqlock(uint32_t key)
874 {
875 	if (resched(key)) {
876 		z_swap_irqlock(key);
877 	} else {
878 		irq_unlock(key);
879 		signal_pending_ipi();
880 	}
881 }
882 
k_sched_lock(void)883 void k_sched_lock(void)
884 {
885 	LOCKED(&sched_spinlock) {
886 		SYS_PORT_TRACING_FUNC(k_thread, sched_lock);
887 
888 		z_sched_lock();
889 	}
890 }
891 
k_sched_unlock(void)892 void k_sched_unlock(void)
893 {
894 	LOCKED(&sched_spinlock) {
895 		__ASSERT(_current->base.sched_locked != 0U, "");
896 		__ASSERT(!arch_is_in_isr(), "");
897 
898 		++_current->base.sched_locked;
899 		update_cache(0);
900 	}
901 
902 	LOG_DBG("scheduler unlocked (%p:%d)",
903 		_current, _current->base.sched_locked);
904 
905 	SYS_PORT_TRACING_FUNC(k_thread, sched_unlock);
906 
907 	z_reschedule_unlocked();
908 }
909 
z_swap_next_thread(void)910 struct k_thread *z_swap_next_thread(void)
911 {
912 #ifdef CONFIG_SMP
913 	struct k_thread *ret = next_up();
914 
915 	if (ret == _current) {
916 		/* When not swapping, have to signal IPIs here.  In
917 		 * the context switch case it must happen later, after
918 		 * _current gets requeued.
919 		 */
920 		signal_pending_ipi();
921 	}
922 	return ret;
923 #else
924 	return _kernel.ready_q.cache;
925 #endif
926 }
927 
928 /* Just a wrapper around _current = xxx with tracing */
set_current(struct k_thread * new_thread)929 static inline void set_current(struct k_thread *new_thread)
930 {
931 	z_thread_mark_switched_out();
932 	_current_cpu->current = new_thread;
933 }
934 
935 #ifdef CONFIG_USE_SWITCH
z_get_next_switch_handle(void * interrupted)936 void *z_get_next_switch_handle(void *interrupted)
937 {
938 	z_check_stack_sentinel();
939 
940 #ifdef CONFIG_SMP
941 	void *ret = NULL;
942 
943 	LOCKED(&sched_spinlock) {
944 		struct k_thread *old_thread = _current, *new_thread;
945 
946 		if (IS_ENABLED(CONFIG_SMP)) {
947 			old_thread->switch_handle = NULL;
948 		}
949 		new_thread = next_up();
950 
951 		if (old_thread != new_thread) {
952 			update_metairq_preempt(new_thread);
953 			wait_for_switch(new_thread);
954 			arch_cohere_stacks(old_thread, interrupted, new_thread);
955 
956 #ifdef CONFIG_TIMESLICING
957 			z_reset_time_slice();
958 #endif
959 			_current_cpu->swap_ok = 0;
960 			set_current(new_thread);
961 
962 #ifdef CONFIG_SPIN_VALIDATE
963 			/* Changed _current!  Update the spinlock
964 			 * bookkeeping so the validation doesn't get
965 			 * confused when the "wrong" thread tries to
966 			 * release the lock.
967 			 */
968 			z_spin_lock_set_owner(&sched_spinlock);
969 #endif
970 
971 			/* A queued (runnable) old/current thread
972 			 * needs to be added back to the run queue
973 			 * here, and atomically with its switch handle
974 			 * being set below.  This is safe now, as we
975 			 * will not return into it.
976 			 */
977 			if (z_is_thread_queued(old_thread)) {
978 				_priq_run_add(&_kernel.ready_q.runq,
979 					      old_thread);
980 			}
981 		}
982 		old_thread->switch_handle = interrupted;
983 		ret = new_thread->switch_handle;
984 		if (IS_ENABLED(CONFIG_SMP)) {
985 			/* Active threads MUST have a null here */
986 			new_thread->switch_handle = NULL;
987 		}
988 	}
989 	signal_pending_ipi();
990 	return ret;
991 #else
992 	_current->switch_handle = interrupted;
993 	set_current(_kernel.ready_q.cache);
994 	return _current->switch_handle;
995 #endif
996 }
997 #endif
998 
z_priq_dumb_remove(sys_dlist_t * pq,struct k_thread * thread)999 void z_priq_dumb_remove(sys_dlist_t *pq, struct k_thread *thread)
1000 {
1001 	__ASSERT_NO_MSG(!z_is_idle_thread_object(thread));
1002 
1003 	sys_dlist_remove(&thread->base.qnode_dlist);
1004 }
1005 
z_priq_dumb_best(sys_dlist_t * pq)1006 struct k_thread *z_priq_dumb_best(sys_dlist_t *pq)
1007 {
1008 	struct k_thread *thread = NULL;
1009 	sys_dnode_t *n = sys_dlist_peek_head(pq);
1010 
1011 	if (n != NULL) {
1012 		thread = CONTAINER_OF(n, struct k_thread, base.qnode_dlist);
1013 	}
1014 	return thread;
1015 }
1016 
z_priq_rb_lessthan(struct rbnode * a,struct rbnode * b)1017 bool z_priq_rb_lessthan(struct rbnode *a, struct rbnode *b)
1018 {
1019 	struct k_thread *thread_a, *thread_b;
1020 	int32_t cmp;
1021 
1022 	thread_a = CONTAINER_OF(a, struct k_thread, base.qnode_rb);
1023 	thread_b = CONTAINER_OF(b, struct k_thread, base.qnode_rb);
1024 
1025 	cmp = z_sched_prio_cmp(thread_a, thread_b);
1026 
1027 	if (cmp > 0) {
1028 		return true;
1029 	} else if (cmp < 0) {
1030 		return false;
1031 	} else {
1032 		return thread_a->base.order_key < thread_b->base.order_key
1033 			? 1 : 0;
1034 	}
1035 }
1036 
z_priq_rb_add(struct _priq_rb * pq,struct k_thread * thread)1037 void z_priq_rb_add(struct _priq_rb *pq, struct k_thread *thread)
1038 {
1039 	struct k_thread *t;
1040 
1041 	__ASSERT_NO_MSG(!z_is_idle_thread_object(thread));
1042 
1043 	thread->base.order_key = pq->next_order_key++;
1044 
1045 	/* Renumber at wraparound.  This is tiny code, and in practice
1046 	 * will almost never be hit on real systems.  BUT on very
1047 	 * long-running systems where a priq never completely empties
1048 	 * AND that contains very large numbers of threads, it can be
1049 	 * a latency glitch to loop over all the threads like this.
1050 	 */
1051 	if (!pq->next_order_key) {
1052 		RB_FOR_EACH_CONTAINER(&pq->tree, t, base.qnode_rb) {
1053 			t->base.order_key = pq->next_order_key++;
1054 		}
1055 	}
1056 
1057 	rb_insert(&pq->tree, &thread->base.qnode_rb);
1058 }
1059 
z_priq_rb_remove(struct _priq_rb * pq,struct k_thread * thread)1060 void z_priq_rb_remove(struct _priq_rb *pq, struct k_thread *thread)
1061 {
1062 	__ASSERT_NO_MSG(!z_is_idle_thread_object(thread));
1063 
1064 	rb_remove(&pq->tree, &thread->base.qnode_rb);
1065 
1066 	if (!pq->tree.root) {
1067 		pq->next_order_key = 0;
1068 	}
1069 }
1070 
z_priq_rb_best(struct _priq_rb * pq)1071 struct k_thread *z_priq_rb_best(struct _priq_rb *pq)
1072 {
1073 	struct k_thread *thread = NULL;
1074 	struct rbnode *n = rb_get_min(&pq->tree);
1075 
1076 	if (n != NULL) {
1077 		thread = CONTAINER_OF(n, struct k_thread, base.qnode_rb);
1078 	}
1079 	return thread;
1080 }
1081 
1082 #ifdef CONFIG_SCHED_MULTIQ
1083 # if (K_LOWEST_THREAD_PRIO - K_HIGHEST_THREAD_PRIO) > 31
1084 # error Too many priorities for multiqueue scheduler (max 32)
1085 # endif
1086 #endif
1087 
z_priq_mq_add(struct _priq_mq * pq,struct k_thread * thread)1088 ALWAYS_INLINE void z_priq_mq_add(struct _priq_mq *pq, struct k_thread *thread)
1089 {
1090 	int priority_bit = thread->base.prio - K_HIGHEST_THREAD_PRIO;
1091 
1092 	sys_dlist_append(&pq->queues[priority_bit], &thread->base.qnode_dlist);
1093 	pq->bitmask |= BIT(priority_bit);
1094 }
1095 
z_priq_mq_remove(struct _priq_mq * pq,struct k_thread * thread)1096 ALWAYS_INLINE void z_priq_mq_remove(struct _priq_mq *pq, struct k_thread *thread)
1097 {
1098 	int priority_bit = thread->base.prio - K_HIGHEST_THREAD_PRIO;
1099 
1100 	sys_dlist_remove(&thread->base.qnode_dlist);
1101 	if (sys_dlist_is_empty(&pq->queues[priority_bit])) {
1102 		pq->bitmask &= ~BIT(priority_bit);
1103 	}
1104 }
1105 
z_priq_mq_best(struct _priq_mq * pq)1106 struct k_thread *z_priq_mq_best(struct _priq_mq *pq)
1107 {
1108 	if (!pq->bitmask) {
1109 		return NULL;
1110 	}
1111 
1112 	struct k_thread *thread = NULL;
1113 	sys_dlist_t *l = &pq->queues[__builtin_ctz(pq->bitmask)];
1114 	sys_dnode_t *n = sys_dlist_peek_head(l);
1115 
1116 	if (n != NULL) {
1117 		thread = CONTAINER_OF(n, struct k_thread, base.qnode_dlist);
1118 	}
1119 	return thread;
1120 }
1121 
z_unpend_all(_wait_q_t * wait_q)1122 int z_unpend_all(_wait_q_t *wait_q)
1123 {
1124 	int need_sched = 0;
1125 	struct k_thread *thread;
1126 
1127 	while ((thread = z_waitq_head(wait_q)) != NULL) {
1128 		z_unpend_thread(thread);
1129 		z_ready_thread(thread);
1130 		need_sched = 1;
1131 	}
1132 
1133 	return need_sched;
1134 }
1135 
z_sched_init(void)1136 void z_sched_init(void)
1137 {
1138 #ifdef CONFIG_SCHED_DUMB
1139 	sys_dlist_init(&_kernel.ready_q.runq);
1140 #endif
1141 
1142 #ifdef CONFIG_SCHED_SCALABLE
1143 	_kernel.ready_q.runq = (struct _priq_rb) {
1144 		.tree = {
1145 			.lessthan_fn = z_priq_rb_lessthan,
1146 		}
1147 	};
1148 #endif
1149 
1150 #ifdef CONFIG_SCHED_MULTIQ
1151 	for (int i = 0; i < ARRAY_SIZE(_kernel.ready_q.runq.queues); i++) {
1152 		sys_dlist_init(&_kernel.ready_q.runq.queues[i]);
1153 	}
1154 #endif
1155 
1156 #ifdef CONFIG_TIMESLICING
1157 	k_sched_time_slice_set(CONFIG_TIMESLICE_SIZE,
1158 		CONFIG_TIMESLICE_PRIORITY);
1159 #endif
1160 }
1161 
z_impl_k_thread_priority_get(k_tid_t thread)1162 int z_impl_k_thread_priority_get(k_tid_t thread)
1163 {
1164 	return thread->base.prio;
1165 }
1166 
1167 #ifdef CONFIG_USERSPACE
z_vrfy_k_thread_priority_get(k_tid_t thread)1168 static inline int z_vrfy_k_thread_priority_get(k_tid_t thread)
1169 {
1170 	Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD));
1171 	return z_impl_k_thread_priority_get(thread);
1172 }
1173 #include <syscalls/k_thread_priority_get_mrsh.c>
1174 #endif
1175 
z_impl_k_thread_priority_set(k_tid_t thread,int prio)1176 void z_impl_k_thread_priority_set(k_tid_t thread, int prio)
1177 {
1178 	/*
1179 	 * Use NULL, since we cannot know what the entry point is (we do not
1180 	 * keep track of it) and idle cannot change its priority.
1181 	 */
1182 	Z_ASSERT_VALID_PRIO(prio, NULL);
1183 	__ASSERT(!arch_is_in_isr(), "");
1184 
1185 	struct k_thread *th = (struct k_thread *)thread;
1186 
1187 	z_thread_priority_set(th, prio);
1188 }
1189 
1190 #ifdef CONFIG_USERSPACE
z_vrfy_k_thread_priority_set(k_tid_t thread,int prio)1191 static inline void z_vrfy_k_thread_priority_set(k_tid_t thread, int prio)
1192 {
1193 	Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD));
1194 	Z_OOPS(Z_SYSCALL_VERIFY_MSG(_is_valid_prio(prio, NULL),
1195 				    "invalid thread priority %d", prio));
1196 	Z_OOPS(Z_SYSCALL_VERIFY_MSG((int8_t)prio >= thread->base.prio,
1197 				    "thread priority may only be downgraded (%d < %d)",
1198 				    prio, thread->base.prio));
1199 
1200 	z_impl_k_thread_priority_set(thread, prio);
1201 }
1202 #include <syscalls/k_thread_priority_set_mrsh.c>
1203 #endif
1204 
1205 #ifdef CONFIG_SCHED_DEADLINE
z_impl_k_thread_deadline_set(k_tid_t tid,int deadline)1206 void z_impl_k_thread_deadline_set(k_tid_t tid, int deadline)
1207 {
1208 	struct k_thread *thread = tid;
1209 
1210 	LOCKED(&sched_spinlock) {
1211 		thread->base.prio_deadline = k_cycle_get_32() + deadline;
1212 		if (z_is_thread_queued(thread)) {
1213 			dequeue_thread(&_kernel.ready_q.runq, thread);
1214 			queue_thread(&_kernel.ready_q.runq, thread);
1215 		}
1216 	}
1217 }
1218 
1219 #ifdef CONFIG_USERSPACE
z_vrfy_k_thread_deadline_set(k_tid_t tid,int deadline)1220 static inline void z_vrfy_k_thread_deadline_set(k_tid_t tid, int deadline)
1221 {
1222 	struct k_thread *thread = tid;
1223 
1224 	Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD));
1225 	Z_OOPS(Z_SYSCALL_VERIFY_MSG(deadline > 0,
1226 				    "invalid thread deadline %d",
1227 				    (int)deadline));
1228 
1229 	z_impl_k_thread_deadline_set((k_tid_t)thread, deadline);
1230 }
1231 #include <syscalls/k_thread_deadline_set_mrsh.c>
1232 #endif
1233 #endif
1234 
z_impl_k_yield(void)1235 void z_impl_k_yield(void)
1236 {
1237 	__ASSERT(!arch_is_in_isr(), "");
1238 
1239 	SYS_PORT_TRACING_FUNC(k_thread, yield);
1240 
1241 	k_spinlock_key_t key = k_spin_lock(&sched_spinlock);
1242 
1243 	if (!IS_ENABLED(CONFIG_SMP) ||
1244 	    z_is_thread_queued(_current)) {
1245 		dequeue_thread(&_kernel.ready_q.runq,
1246 			       _current);
1247 	}
1248 	queue_thread(&_kernel.ready_q.runq, _current);
1249 	update_cache(1);
1250 	z_swap(&sched_spinlock, key);
1251 }
1252 
1253 #ifdef CONFIG_USERSPACE
z_vrfy_k_yield(void)1254 static inline void z_vrfy_k_yield(void)
1255 {
1256 	z_impl_k_yield();
1257 }
1258 #include <syscalls/k_yield_mrsh.c>
1259 #endif
1260 
z_tick_sleep(k_ticks_t ticks)1261 static int32_t z_tick_sleep(k_ticks_t ticks)
1262 {
1263 #ifdef CONFIG_MULTITHREADING
1264 	uint32_t expected_wakeup_ticks;
1265 
1266 	__ASSERT(!arch_is_in_isr(), "");
1267 
1268 #ifndef CONFIG_TIMEOUT_64BIT
1269 	/* LOG subsys does not handle 64-bit values
1270 	 * https://github.com/zephyrproject-rtos/zephyr/issues/26246
1271 	 */
1272 	LOG_DBG("thread %p for %u ticks", _current, ticks);
1273 #endif
1274 
1275 	/* wait of 0 ms is treated as a 'yield' */
1276 	if (ticks == 0) {
1277 		k_yield();
1278 		return 0;
1279 	}
1280 
1281 	k_timeout_t timeout = Z_TIMEOUT_TICKS(ticks);
1282 	if (Z_TICK_ABS(ticks) <= 0) {
1283 		expected_wakeup_ticks = ticks + sys_clock_tick_get_32();
1284 	} else {
1285 		expected_wakeup_ticks = Z_TICK_ABS(ticks);
1286 	}
1287 
1288 	k_spinlock_key_t key = k_spin_lock(&sched_spinlock);
1289 
1290 #if defined(CONFIG_TIMESLICING) && defined(CONFIG_SWAP_NONATOMIC)
1291 	pending_current = _current;
1292 #endif
1293 	unready_thread(_current);
1294 	z_add_thread_timeout(_current, timeout);
1295 	z_mark_thread_as_suspended(_current);
1296 
1297 	(void)z_swap(&sched_spinlock, key);
1298 
1299 	__ASSERT(!z_is_thread_state_set(_current, _THREAD_SUSPENDED), "");
1300 
1301 	ticks = (k_ticks_t)expected_wakeup_ticks - sys_clock_tick_get_32();
1302 	if (ticks > 0) {
1303 		return ticks;
1304 	}
1305 #endif
1306 
1307 	return 0;
1308 }
1309 
z_impl_k_sleep(k_timeout_t timeout)1310 int32_t z_impl_k_sleep(k_timeout_t timeout)
1311 {
1312 	k_ticks_t ticks;
1313 
1314 	__ASSERT(!arch_is_in_isr(), "");
1315 
1316 	SYS_PORT_TRACING_FUNC_ENTER(k_thread, sleep, timeout);
1317 
1318 	/* in case of K_FOREVER, we suspend */
1319 	if (K_TIMEOUT_EQ(timeout, K_FOREVER)) {
1320 		k_thread_suspend(_current);
1321 
1322 		SYS_PORT_TRACING_FUNC_EXIT(k_thread, sleep, timeout, (int32_t) K_TICKS_FOREVER);
1323 
1324 		return (int32_t) K_TICKS_FOREVER;
1325 	}
1326 
1327 	ticks = timeout.ticks;
1328 
1329 	ticks = z_tick_sleep(ticks);
1330 
1331 	int32_t ret = k_ticks_to_ms_floor64(ticks);
1332 
1333 	SYS_PORT_TRACING_FUNC_EXIT(k_thread, sleep, timeout, ret);
1334 
1335 	return ret;
1336 }
1337 
1338 #ifdef CONFIG_USERSPACE
z_vrfy_k_sleep(k_timeout_t timeout)1339 static inline int32_t z_vrfy_k_sleep(k_timeout_t timeout)
1340 {
1341 	return z_impl_k_sleep(timeout);
1342 }
1343 #include <syscalls/k_sleep_mrsh.c>
1344 #endif
1345 
z_impl_k_usleep(int us)1346 int32_t z_impl_k_usleep(int us)
1347 {
1348 	int32_t ticks;
1349 
1350 	SYS_PORT_TRACING_FUNC_ENTER(k_thread, usleep, us);
1351 
1352 	ticks = k_us_to_ticks_ceil64(us);
1353 	ticks = z_tick_sleep(ticks);
1354 
1355 	SYS_PORT_TRACING_FUNC_EXIT(k_thread, usleep, us, k_ticks_to_us_floor64(ticks));
1356 
1357 	return k_ticks_to_us_floor64(ticks);
1358 }
1359 
1360 #ifdef CONFIG_USERSPACE
z_vrfy_k_usleep(int us)1361 static inline int32_t z_vrfy_k_usleep(int us)
1362 {
1363 	return z_impl_k_usleep(us);
1364 }
1365 #include <syscalls/k_usleep_mrsh.c>
1366 #endif
1367 
z_impl_k_wakeup(k_tid_t thread)1368 void z_impl_k_wakeup(k_tid_t thread)
1369 {
1370 	SYS_PORT_TRACING_OBJ_FUNC(k_thread, wakeup, thread);
1371 
1372 	if (z_is_thread_pending(thread)) {
1373 		return;
1374 	}
1375 
1376 	if (z_abort_thread_timeout(thread) < 0) {
1377 		/* Might have just been sleeping forever */
1378 		if (thread->base.thread_state != _THREAD_SUSPENDED) {
1379 			return;
1380 		}
1381 	}
1382 
1383 	z_mark_thread_as_not_suspended(thread);
1384 	z_ready_thread(thread);
1385 
1386 	flag_ipi();
1387 
1388 	if (!arch_is_in_isr()) {
1389 		z_reschedule_unlocked();
1390 	}
1391 }
1392 
1393 #ifdef CONFIG_TRACE_SCHED_IPI
1394 extern void z_trace_sched_ipi(void);
1395 #endif
1396 
1397 #ifdef CONFIG_SMP
z_sched_ipi(void)1398 void z_sched_ipi(void)
1399 {
1400 	/* NOTE: When adding code to this, make sure this is called
1401 	 * at appropriate location when !CONFIG_SCHED_IPI_SUPPORTED.
1402 	 */
1403 #ifdef CONFIG_TRACE_SCHED_IPI
1404 	z_trace_sched_ipi();
1405 #endif
1406 }
1407 #endif
1408 
1409 #ifdef CONFIG_USERSPACE
z_vrfy_k_wakeup(k_tid_t thread)1410 static inline void z_vrfy_k_wakeup(k_tid_t thread)
1411 {
1412 	Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD));
1413 	z_impl_k_wakeup(thread);
1414 }
1415 #include <syscalls/k_wakeup_mrsh.c>
1416 #endif
1417 
z_impl_z_current_get(void)1418 k_tid_t z_impl_z_current_get(void)
1419 {
1420 #ifdef CONFIG_SMP
1421 	/* In SMP, _current is a field read from _current_cpu, which
1422 	 * can race with preemption before it is read.  We must lock
1423 	 * local interrupts when reading it.
1424 	 */
1425 	unsigned int k = arch_irq_lock();
1426 #endif
1427 
1428 	k_tid_t ret = _current_cpu->current;
1429 
1430 #ifdef CONFIG_SMP
1431 	arch_irq_unlock(k);
1432 #endif
1433 	return ret;
1434 }
1435 
1436 #ifdef CONFIG_USERSPACE
z_vrfy_z_current_get(void)1437 static inline k_tid_t z_vrfy_z_current_get(void)
1438 {
1439 	return z_impl_z_current_get();
1440 }
1441 #include <syscalls/z_current_get_mrsh.c>
1442 #endif
1443 
z_impl_k_is_preempt_thread(void)1444 int z_impl_k_is_preempt_thread(void)
1445 {
1446 	return !arch_is_in_isr() && is_preempt(_current);
1447 }
1448 
1449 #ifdef CONFIG_USERSPACE
z_vrfy_k_is_preempt_thread(void)1450 static inline int z_vrfy_k_is_preempt_thread(void)
1451 {
1452 	return z_impl_k_is_preempt_thread();
1453 }
1454 #include <syscalls/k_is_preempt_thread_mrsh.c>
1455 #endif
1456 
1457 #ifdef CONFIG_SCHED_CPU_MASK
1458 # ifdef CONFIG_SMP
1459 /* Right now we use a single byte for this mask */
1460 BUILD_ASSERT(CONFIG_MP_NUM_CPUS <= 8, "Too many CPUs for mask word");
1461 # endif
1462 
1463 
cpu_mask_mod(k_tid_t thread,uint32_t enable_mask,uint32_t disable_mask)1464 static int cpu_mask_mod(k_tid_t thread, uint32_t enable_mask, uint32_t disable_mask)
1465 {
1466 	int ret = 0;
1467 
1468 	LOCKED(&sched_spinlock) {
1469 		if (z_is_thread_prevented_from_running(thread)) {
1470 			thread->base.cpu_mask |= enable_mask;
1471 			thread->base.cpu_mask  &= ~disable_mask;
1472 		} else {
1473 			ret = -EINVAL;
1474 		}
1475 	}
1476 	return ret;
1477 }
1478 
k_thread_cpu_mask_clear(k_tid_t thread)1479 int k_thread_cpu_mask_clear(k_tid_t thread)
1480 {
1481 	return cpu_mask_mod(thread, 0, 0xffffffff);
1482 }
1483 
k_thread_cpu_mask_enable_all(k_tid_t thread)1484 int k_thread_cpu_mask_enable_all(k_tid_t thread)
1485 {
1486 	return cpu_mask_mod(thread, 0xffffffff, 0);
1487 }
1488 
k_thread_cpu_mask_enable(k_tid_t thread,int cpu)1489 int k_thread_cpu_mask_enable(k_tid_t thread, int cpu)
1490 {
1491 	return cpu_mask_mod(thread, BIT(cpu), 0);
1492 }
1493 
k_thread_cpu_mask_disable(k_tid_t thread,int cpu)1494 int k_thread_cpu_mask_disable(k_tid_t thread, int cpu)
1495 {
1496 	return cpu_mask_mod(thread, 0, BIT(cpu));
1497 }
1498 
1499 #endif /* CONFIG_SCHED_CPU_MASK */
1500 
unpend_all(_wait_q_t * wait_q)1501 static inline void unpend_all(_wait_q_t *wait_q)
1502 {
1503 	struct k_thread *thread;
1504 
1505 	while ((thread = z_waitq_head(wait_q)) != NULL) {
1506 		unpend_thread_no_timeout(thread);
1507 		(void)z_abort_thread_timeout(thread);
1508 		arch_thread_return_value_set(thread, 0);
1509 		ready_thread(thread);
1510 	}
1511 }
1512 
1513 #ifdef CONFIG_CMSIS_RTOS_V1
1514 extern void z_thread_cmsis_status_mask_clear(struct k_thread *thread);
1515 #endif
1516 
end_thread(struct k_thread * thread)1517 static void end_thread(struct k_thread *thread)
1518 {
1519 	/* We hold the lock, and the thread is known not to be running
1520 	 * anywhere.
1521 	 */
1522 	if ((thread->base.thread_state & _THREAD_DEAD) == 0U) {
1523 		thread->base.thread_state |= _THREAD_DEAD;
1524 		thread->base.thread_state &= ~_THREAD_ABORTING;
1525 		if (z_is_thread_queued(thread)) {
1526 			dequeue_thread(&_kernel.ready_q.runq, thread);
1527 		}
1528 		if (thread->base.pended_on != NULL) {
1529 			unpend_thread_no_timeout(thread);
1530 		}
1531 		(void)z_abort_thread_timeout(thread);
1532 		unpend_all(&thread->join_queue);
1533 		update_cache(1);
1534 
1535 		SYS_PORT_TRACING_FUNC(k_thread, sched_abort, thread);
1536 
1537 		z_thread_monitor_exit(thread);
1538 
1539 #ifdef CONFIG_CMSIS_RTOS_V1
1540 		z_thread_cmsis_status_mask_clear(thread);
1541 #endif
1542 
1543 #ifdef CONFIG_USERSPACE
1544 		z_mem_domain_exit_thread(thread);
1545 		z_thread_perms_all_clear(thread);
1546 		z_object_uninit(thread->stack_obj);
1547 		z_object_uninit(thread);
1548 #endif
1549 	}
1550 }
1551 
z_thread_abort(struct k_thread * thread)1552 void z_thread_abort(struct k_thread *thread)
1553 {
1554 	k_spinlock_key_t key = k_spin_lock(&sched_spinlock);
1555 
1556 	if ((thread->base.thread_state & _THREAD_DEAD) != 0U) {
1557 		k_spin_unlock(&sched_spinlock, key);
1558 		return;
1559 	}
1560 
1561 #ifdef CONFIG_SMP
1562 	if (is_aborting(thread) && thread == _current && arch_is_in_isr()) {
1563 		/* Another CPU is spinning for us, don't deadlock */
1564 		end_thread(thread);
1565 	}
1566 
1567 	bool active = thread_active_elsewhere(thread);
1568 
1569 	if (active) {
1570 		/* It's running somewhere else, flag and poke */
1571 		thread->base.thread_state |= _THREAD_ABORTING;
1572 
1573 		/* We're going to spin, so need a true synchronous IPI
1574 		 * here, not deferred!
1575 		 */
1576 #ifdef CONFIG_SCHED_IPI_SUPPORTED
1577 		arch_sched_ipi();
1578 #endif
1579 	}
1580 
1581 	if (is_aborting(thread) && thread != _current) {
1582 		if (arch_is_in_isr()) {
1583 			/* ISRs can only spin waiting another CPU */
1584 			k_spin_unlock(&sched_spinlock, key);
1585 			while (is_aborting(thread)) {
1586 			}
1587 		} else if (active) {
1588 			/* Threads can join */
1589 			add_to_waitq_locked(_current, &thread->join_queue);
1590 			z_swap(&sched_spinlock, key);
1591 		}
1592 		return; /* lock has been released */
1593 	}
1594 #endif
1595 	end_thread(thread);
1596 	if (thread == _current && !arch_is_in_isr()) {
1597 		z_swap(&sched_spinlock, key);
1598 		__ASSERT(false, "aborted _current back from dead");
1599 	}
1600 	k_spin_unlock(&sched_spinlock, key);
1601 }
1602 
1603 #if !defined(CONFIG_ARCH_HAS_THREAD_ABORT)
z_impl_k_thread_abort(struct k_thread * thread)1604 void z_impl_k_thread_abort(struct k_thread *thread)
1605 {
1606 	SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_thread, abort, thread);
1607 
1608 	z_thread_abort(thread);
1609 
1610 	SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_thread, abort, thread);
1611 }
1612 #endif
1613 
z_impl_k_thread_join(struct k_thread * thread,k_timeout_t timeout)1614 int z_impl_k_thread_join(struct k_thread *thread, k_timeout_t timeout)
1615 {
1616 	k_spinlock_key_t key = k_spin_lock(&sched_spinlock);
1617 	int ret = 0;
1618 
1619 	SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_thread, join, thread, timeout);
1620 
1621 	if ((thread->base.thread_state & _THREAD_DEAD) != 0U) {
1622 		ret = 0;
1623 	} else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) {
1624 		ret = -EBUSY;
1625 	} else if ((thread == _current) ||
1626 		   (thread->base.pended_on == &_current->join_queue)) {
1627 		ret = -EDEADLK;
1628 	} else {
1629 		__ASSERT(!arch_is_in_isr(), "cannot join in ISR");
1630 		add_to_waitq_locked(_current, &thread->join_queue);
1631 		add_thread_timeout(_current, timeout);
1632 
1633 		SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_thread, join, thread, timeout);
1634 		ret = z_swap(&sched_spinlock, key);
1635 		SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_thread, join, thread, timeout, ret);
1636 
1637 		return ret;
1638 	}
1639 
1640 	SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_thread, join, thread, timeout, ret);
1641 
1642 	k_spin_unlock(&sched_spinlock, key);
1643 	return ret;
1644 }
1645 
1646 #ifdef CONFIG_USERSPACE
1647 /* Special case: don't oops if the thread is uninitialized.  This is because
1648  * the initialization bit does double-duty for thread objects; if false, means
1649  * the thread object is truly uninitialized, or the thread ran and exited for
1650  * some reason.
1651  *
1652  * Return true in this case indicating we should just do nothing and return
1653  * success to the caller.
1654  */
thread_obj_validate(struct k_thread * thread)1655 static bool thread_obj_validate(struct k_thread *thread)
1656 {
1657 	struct z_object *ko = z_object_find(thread);
1658 	int ret = z_object_validate(ko, K_OBJ_THREAD, _OBJ_INIT_TRUE);
1659 
1660 	switch (ret) {
1661 	case 0:
1662 		return false;
1663 	case -EINVAL:
1664 		return true;
1665 	default:
1666 #ifdef CONFIG_LOG
1667 		z_dump_object_error(ret, thread, ko, K_OBJ_THREAD);
1668 #endif
1669 		Z_OOPS(Z_SYSCALL_VERIFY_MSG(ret, "access denied"));
1670 	}
1671 	CODE_UNREACHABLE; /* LCOV_EXCL_LINE */
1672 }
1673 
z_vrfy_k_thread_join(struct k_thread * thread,k_timeout_t timeout)1674 static inline int z_vrfy_k_thread_join(struct k_thread *thread,
1675 				       k_timeout_t timeout)
1676 {
1677 	if (thread_obj_validate(thread)) {
1678 		return 0;
1679 	}
1680 
1681 	return z_impl_k_thread_join(thread, timeout);
1682 }
1683 #include <syscalls/k_thread_join_mrsh.c>
1684 
z_vrfy_k_thread_abort(k_tid_t thread)1685 static inline void z_vrfy_k_thread_abort(k_tid_t thread)
1686 {
1687 	if (thread_obj_validate(thread)) {
1688 		return;
1689 	}
1690 
1691 	Z_OOPS(Z_SYSCALL_VERIFY_MSG(!(thread->base.user_options & K_ESSENTIAL),
1692 				    "aborting essential thread %p", thread));
1693 
1694 	z_impl_k_thread_abort((struct k_thread *)thread);
1695 }
1696 #include <syscalls/k_thread_abort_mrsh.c>
1697 #endif /* CONFIG_USERSPACE */
1698 
1699 /*
1700  * future scheduler.h API implementations
1701  */
z_sched_wake(_wait_q_t * wait_q,int swap_retval,void * swap_data)1702 bool z_sched_wake(_wait_q_t *wait_q, int swap_retval, void *swap_data)
1703 {
1704 	struct k_thread *thread;
1705 	bool ret = false;
1706 
1707 	LOCKED(&sched_spinlock) {
1708 		thread = _priq_wait_best(&wait_q->waitq);
1709 
1710 		if (thread != NULL) {
1711 			z_thread_return_value_set_with_data(thread,
1712 							    swap_retval,
1713 							    swap_data);
1714 			unpend_thread_no_timeout(thread);
1715 			(void)z_abort_thread_timeout(thread);
1716 			ready_thread(thread);
1717 			ret = true;
1718 		}
1719 	}
1720 
1721 	return ret;
1722 }
1723 
z_sched_wait(struct k_spinlock * lock,k_spinlock_key_t key,_wait_q_t * wait_q,k_timeout_t timeout,void ** data)1724 int z_sched_wait(struct k_spinlock *lock, k_spinlock_key_t key,
1725 		 _wait_q_t *wait_q, k_timeout_t timeout, void **data)
1726 {
1727 	int ret = z_pend_curr(lock, key, wait_q, timeout);
1728 
1729 	if (data != NULL) {
1730 		*data = _current->base.swap_data;
1731 	}
1732 	return ret;
1733 }
1734