<commit_before>/**
 * @file
 * @brief TODO --Alina
 *
 * @date 22.04.10
 * @author <NAME>
 *          - Initial implementation
 * @author <NAME>
 *          - Some insignificant contribution
 * @author <NAME>
 *          - Initial work on priority inheritance support
 * @author <NAME>
 *          - Rewriting from scratch:
 *              - Interrupts safety, adaptation to Critical API
 *              - @c startq for deferred wake/resume processing
 */

#include <assert.h>
#include <errno.h>
#include <lib/list.h>

#include <kernel/critical.h>
#include <kernel/irq_lock.h>
#include <kernel/thread/sched.h>
#include <kernel/thread/sched_strategy.h>
#include <kernel/thread/state.h>
#include <kernel/time/timer.h>
#include <kernel/task.h>
#include <hal/context.h>
#include <hal/ipl.h>

#include <profiler/tracing/trace.h>

#include <time.h>

#include "types.h"

#include <embox/unit.h>

/** Interval, what scheduler_tick is called in. */
#define SCHED_TICK_INTERVAL 100

EMBOX_UNIT(unit_init, unit_fini);

extern void startq_flush(void);
extern void startq_enqueue_wake(struct sleepq *sq, int wake_all);
extern void startq_enqueue_wake_force(struct thread *t);

int do_thread_wake_force(struct thread *thread);
void do_sleepq_wake(struct sleepq *sq, int wake_all);

static void do_sleep_locked(struct sleepq *sq);

static void __sched_wake(struct sleepq *sq, int wake_all);

static void post_switch_if(int condition);

static void sched_switch(void);

CRITICAL_DISPATCHER_DEF(sched_critical, sched_switch, CRITICAL_SCHED_LOCK);

static struct runq rq;

static sys_timer_t *tick_timer;

static clock_t prev_clock;

static inline int in_harder_critical(void) {
	return critical_inside(__CRITICAL_HARDER(CRITICAL_SCHED_LOCK));
}

static inline int in_sched_locked(void) {
	return !critical_allows(CRITICAL_SCHED_LOCK);
}

int sched_init(struct thread* current, struct thread *idle) {
	prev_clock = clock();

	runq_init(&rq, current, idle);

	assert(thread_state_started(current->state));
	assert(thread_state_started(idle->state));

	return 0;
}

struct thread *sched_current(void) {
	return runq_current(&rq);
}

void sched_start(struct thread *t) {
	assert(!in_harder_critical());

	sched_lock();
	{
		assert(!thread_state_started(t->state));
		post_switch_if(runq_start(&rq, t));
		assert(thread_state_started(t->state));
	}
	sched_unlock();
}

void sched_finish(struct thread *t) {
	assert(!in_harder_critical());

	sched_lock();
	{
		assert(!thread_state_exited(t->state));

		if (thread_state_running(t->state)) {
			post_switch_if(runq_finish(&rq, t));
		} else {
			if (thread_state_sleeping(t->state)) {
				sleepq_finish(t->sleepq, t);
			} else {
				t->state = thread_state_do_exit(t->state);
			}
		}

		assert(thread_state_exited(t->state));
	}
	sched_unlock();
}

void sched_wake_all(struct sleepq *sq) {
	__sched_wake(sq, 1);
}

void sched_wake_one(struct sleepq *sq) {
	__sched_wake(sq, 0);
}

void __sched_wake(struct sleepq *sq, int wake_all) {
	if (in_harder_critical()) {
		startq_enqueue_wake(sq, wake_all);
		critical_request_dispatch(&sched_critical);
	} else {
		do_sleepq_wake(sq, wake_all);
	}
}

void do_sleepq_wake(struct sleepq *sq, int wake_all) {
	assert(!in_harder_critical());

	sched_lock();
	{
		post_switch_if(sleepq_wake(&rq, sq, wake_all));
	}
	sched_unlock();
}

static int thread_wake_force(struct thread *thread, int sleep_result) {
	thread->sleep_res = sleep_result;

	if (in_harder_critical()) {
		startq_enqueue_wake_force(thread);
		critical_request_dispatch(&sched_critical);
	} else {
		return do_thread_wake_force(thread);
	}

	return 0;
}

int do_thread_wake_force(struct thread *thread) {
	assert(!in_harder_critical());
	assert(thread_state_sleeping(thread->state));

	return sleepq_wake_thread(&rq, thread->sleepq, thread);
}

static void do_sleep_locked(struct sleepq *sq) {
	struct thread *current = runq_current(&rq);
	assert(in_sched_locked() && !in_harder_critical());
	assert(thread_state_running(current->state));

	runq_sleep(&rq, sq);

	assert(current->sleepq == sq);
	assert(thread_state_sleeping(current->state));

	post_switch_if(1);
}

struct sched_sleep_data {
	struct event *timeout_event;
	struct thread *thread;
};

static void timeout_handler(struct sys_timer *timer, void *sleep_data) {
	struct thread *thread = (struct thread *) sleep_data;
	post_switch_if(thread_wake_force(thread, SCHED_SLEEP_TIMEOUT));
}

int sched_sleep_locked(struct sleepq *sq, unsigned long timeout) {
	int ret;
	struct sys_timer tmr;
	struct thread *current = sched_current();

	assert(in_sched_locked() && !in_harder_critical());
	assert(thread_state_running(current->state));

	current->sleep_res = 0; /* clean out sleep_res */

	if (timeout != SCHED_TIMEOUT_INFINITE) {
		ret = timer_init(&tmr, TIMER_ONESHOT, (uint32_t)timeout, timeout_handler, current);
		if (ret != ENOERR) {
			return ret;
		}
	}<commit_msg>Throw out a weird struct from sched.c<commit_after>/**
 * @file
 * @brief TODO --Alina
 *
 * @date 22.04.10
 * @author <NAME>
 *          - Initial implementation
 * @author <NAME>
 *          - Some insignificant contribution
 * @author <NAME>
 *          - Initial work on priority inheritance support
 * @author <NAME>
 *          - Rewriting from scratch:
 *              - Interrupts safety, adaptation to Critical API
 *              - @c startq for deferred wake/resume processing
 */

#include <assert.h>
#include <errno.h>
#include <lib/list.h>

#include <kernel/critical.h>
#include <kernel/irq_lock.h>
#include <kernel/thread/sched.h>
#include <kernel/thread/sched_strategy.h>
#include <kernel/thread/state.h>
#include <kernel/time/timer.h>
#include <kernel/task.h>
#include <hal/context.h>
#include <hal/ipl.h>

#include <profiler/tracing/trace.h>

#include <time.h>

#include "types.h"

#include <embox/unit.h>

/** Interval, what scheduler_tick is called in. */
#define SCHED_TICK_INTERVAL 100

EMBOX_UNIT(unit_init, unit_fini);

extern void startq_flush(void);
extern void startq_enqueue_wake(struct sleepq *sq, int wake_all);
extern void startq_enqueue_wake_force(struct thread *t);

int do_thread_wake_force(struct thread *thread);
void do_sleepq_wake(struct sleepq *sq, int wake_all);

static void do_sleep_locked(struct sleepq *sq);

static void __sched_wake(struct sleepq *sq, int wake_all);

static void post_switch_if(int condition);

static void sched_switch(void);

CRITICAL_DISPATCHER_DEF(sched_critical, sched_switch, CRITICAL_SCHED_LOCK);

static struct runq rq;

static sys_timer_t *tick_timer;

static clock_t prev_clock;

static inline int in_harder_critical(void) {
	return critical_inside(__CRITICAL_HARDER(CRITICAL_SCHED_LOCK));
}

static inline int in_sched_locked(void) {
	return !critical_allows(CRITICAL_SCHED_LOCK);
}

int sched_init(struct thread* current, struct thread *idle) {
	prev_clock = clock();

	runq_init(&rq, current, idle);

	assert(thread_state_started(current->state));
	assert(thread_state_started(idle->state));

	return 0;
}

struct thread *sched_current(void) {
	return runq_current(&rq);
}

void sched_start(struct thread *t) {
	assert(!in_harder_critical());

	sched_lock();
	{
		assert(!thread_state_started(t->state));
		post_switch_if(runq_start(&rq, t));
		assert(thread_state_started(t->state));
	}
	sched_unlock();
}

void sched_finish(struct thread *t) {
	assert(!in_harder_critical());

	sched_lock();
	{
		assert(!thread_state_exited(t->state));

		if (thread_state_running(t->state)) {
			post_switch_if(runq_finish(&rq, t));
		} else {
			if (thread_state_sleeping(t->state)) {
				sleepq_finish(t->sleepq, t);
			} else {
				t->state = thread_state_do_exit(t->state);
			}
		}

		assert(thread_state_exited(t->state));
	}
	sched_unlock();
}

void sched_wake_all(struct sleepq *sq) {
	__sched_wake(sq, 1);
}

void sched_wake_one(struct sleepq *sq) {
	__sched_wake(sq, 0);
}

void __sched_wake(struct sleepq *sq, int wake_all) {
	if (in_harder_critical()) {
		startq_enqueue_wake(sq, wake_all);
		critical_request_dispatch(&sched_critical);
	} else {
		do_sleepq_wake(sq, wake_all);
	}
}

void do_sleepq_wake(struct sleepq *sq, int wake_all) {
	assert(!in_harder_critical());

	sched_lock();
	{
		post_switch_if(sleepq_wake(&rq, sq, wake_all));
	}
	sched_unlock();
}

static int thread_wake_force(struct thread *thread, int sleep_result) {
	thread->sleep_res = sleep_result;

	if (in_harder_critical()) {
		startq_enqueue_wake_force(thread);
		critical_request_dispatch(&sched_critical);
	} else {
		return do_thread_wake_force(thread);
	}

	return 0;
}

int do_thread_wake_force(struct thread *thread) {
	assert(!in_harder_critical());
	assert(thread_state_sleeping(thread->state));

	return sleepq_wake_thread(&rq, thread->sleepq, thread);
}

static void do_sleep_locked(struct sleepq *sq) {
	struct thread *current = runq_current(&rq);
	assert(in_sched_locked() && !in_harder_critical());
	assert(thread_state_running(current->state));

	runq_sleep(&rq, sq);

	assert(current->sleepq == sq);
	assert(thread_state_sleeping(current->state));

	post_switch_if(1);
}

static void timeout_handler(struct sys_timer *timer, void *sleep_data) {
	struct thread *thread = (struct thread *) sleep_data;
	post_switch_if(thread_wake_force(thread, SCHED_SLEEP_TIMEOUT));
}

int sched_sleep_locked(struct sleepq *sq, unsigned long timeout) {
	int ret;
	struct sys_timer tmr;
	struct thread *current = sched_current();

	assert(in_sched_locked() && !in_harder_critical());
	assert(thread_state_running(current->state));

	current->sleep_res = 0; /* clean out sleep_res */

	if (timeout != SCHED_TIMEOUT_INFINITE) {
		ret = timer_init(&tmr, TIMER_ONESHOT, (uint32_t)timeout, timeout_handler, current);
		if (ret != ENOERR) {
			return ret;
		}
	}
{'fraction_non_alphanumeric': 0.1291390728476821, 'fraction_numerical': 0.0035182119205298015, 'mean_word_length': 5.396426207809398, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 79, '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': '3188440', 'n_tokens_mistral': 3640, 'n_tokens_neox': 3490, 'n_words': 700}