<commit_before>/*
 * Copyright (c) 2018 Intel corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <kernel.h>
#include <kernel_structs.h>
#include <spinlock.h>
#include <kswap.h>
#include <kernel_internal.h>

#ifdef CONFIG_SMP
static atomic_t global_lock;

unsigned int z_smp_global_lock(void)
{
	unsigned int key = z_arch_irq_lock();

	if (!_current->base.global_lock_count) {
		while (!atomic_cas(&global_lock, 0, 1)) {
		}
	}

	_current->base.global_lock_count++;

	return key;
}

void z_smp_global_unlock(unsigned int key)
{
	if (_current->base.global_lock_count) {
		_current->base.global_lock_count--;

		if (!_current->base.global_lock_count) {
			atomic_clear(&global_lock);
		}
	}

	z_arch_irq_unlock(key);
}

void z_smp_reacquire_global_lock(struct k_thread *thread)
{
	if (thread->base.global_lock_count) {
		z_arch_irq_lock();

		while (!atomic_cas(&global_lock, 0, 1)) {
		}
	}
}


/* Called from within z_swap(), so assumes lock already held */
void z_smp_release_global_lock(struct k_thread *thread)
{
	if (!thread->base.global_lock_count) {
		atomic_clear(&global_lock);
	}
}

#endif

extern k_thread_stack_t _interrupt_stack1[];
extern k_thread_stack_t _interrupt_stack2[];
extern k_thread_stack_t _interrupt_stack3[];

#if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 1
static void smp_init_top(int key, void *arg)
{
	atomic_t *start_flag = arg;

	/* Wait for the signal to begin scheduling */
	do {
		k_busy_wait(100);
	} while (!atomic_get(start_flag));

	/* Switch out of a dummy thread.  Trick cribbed from the main
	 * thread init.  Should probably unify implementations.
	 */
	struct k_thread dummy_thread = {
		.base.user_options = K_ESSENTIAL,
		.base.thread_state = _THREAD_DUMMY,
	};

	z_arch_curr_cpu()->current = &dummy_thread;
	smp_timer_init();
	z_swap_unlocked();

	CODE_UNREACHABLE;
}
#endif

void smp_init(void)
{
	atomic_t start_flag;

	(void)atomic_clear(&start_flag);

#if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 1
	z_arch_start_cpu(1, _interrupt_stack1, CONFIG_ISR_STACK_SIZE,
			smp_init_top, &start_flag);
#endif

#if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 2
	z_arch_start_cpu(2, _interrupt_stack2, CONFIG_ISR_STACK_SIZE,
			smp_init_top, &start_flag);
#endif

#if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 3
	z_arch_start_cpu(3, _interrupt_stack3, CONFIG_ISR_STACK_SIZE,
			smp_init_top, &start_flag);
#endif

	(void)atomic_set(&start_flag, 1);
}
<commit_msg>kernel/smp: Fix bitrot with the way the SMP "start flag" works<commit_after>/*
 * Copyright (c) 2018 Intel corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <kernel.h>
#include <kernel_structs.h>
#include <spinlock.h>
#include <kswap.h>
#include <kernel_internal.h>

#ifdef CONFIG_SMP
static atomic_t global_lock;
static atomic_t start_flag;

unsigned int z_smp_global_lock(void)
{
	unsigned int key = z_arch_irq_lock();

	if (!_current->base.global_lock_count) {
		while (!atomic_cas(&global_lock, 0, 1)) {
		}
	}

	_current->base.global_lock_count++;

	return key;
}

void z_smp_global_unlock(unsigned int key)
{
	if (_current->base.global_lock_count) {
		_current->base.global_lock_count--;

		if (!_current->base.global_lock_count) {
			atomic_clear(&global_lock);
		}
	}

	z_arch_irq_unlock(key);
}

void z_smp_reacquire_global_lock(struct k_thread *thread)
{
	if (thread->base.global_lock_count) {
		z_arch_irq_lock();

		while (!atomic_cas(&global_lock, 0, 1)) {
		}
	}
}


/* Called from within z_swap(), so assumes lock already held */
void z_smp_release_global_lock(struct k_thread *thread)
{
	if (!thread->base.global_lock_count) {
		atomic_clear(&global_lock);
	}
}

#endif

extern k_thread_stack_t _interrupt_stack1[];
extern k_thread_stack_t _interrupt_stack2[];
extern k_thread_stack_t _interrupt_stack3[];

#if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 1
static void smp_init_top(int key, void *arg)
{
	atomic_t *start_flag = arg;

	/* Wait for the signal to begin scheduling */
	while (!atomic_get(start_flag)) {
	}

	/* Switch out of a dummy thread.  Trick cribbed from the main
	 * thread init.  Should probably unify implementations.
	 */
	struct k_thread dummy_thread = {
		.base.user_options = K_ESSENTIAL,
		.base.thread_state = _THREAD_DUMMY,
	};

	z_arch_curr_cpu()->current = &dummy_thread;
	smp_timer_init();
	z_swap_unlocked();

	CODE_UNREACHABLE;
}

void smp_init(void)
{
	(void)atomic_clear(&start_flag);

#if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 1
	z_arch_start_cpu(1, _interrupt_stack1, CONFIG_ISR_STACK_SIZE,
			smp_init_top, &start_flag);
#endif

#if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 2
	z_arch_start_cpu(2, _interrupt_stack2, CONFIG_ISR_STACK_SIZE,
			smp_init_top, &start_flag);
#endif

#if defined(CONFIG_SMP) && CONFIG_MP_NUM_CPUS > 3
	z_arch_start_cpu(3, _interrupt_stack3, CONFIG_ISR_STACK_SIZE,
			smp_init_top, &start_flag);
#endif

	(void)atomic_set(&start_flag, 1);
}
#endif

{'fraction_non_alphanumeric': 0.11921343711593609, 'fraction_numerical': 0.010446538303973782, 'mean_word_length': 5.4504623513870545, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4348519', 'n_tokens_mistral': 2011, 'n_tokens_neox': 1908, 'n_words': 365}