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