<commit_before>/*
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <timeout_q.h>
#include <drivers/system_timer.h>
#include <sys_clock.h>
#include <spinlock.h>
#include <ksched.h>
#include <syscall_handler.h>

#define LOCKED(lck) for (k_spinlock_key_t __i = {},			\
					  __key = k_spin_lock(lck);	\
			!__i.key;					\
			k_spin_unlock(lck, __key), __i.key = 1)

static u64_t curr_tick;

static sys_dlist_t timeout_list = SYS_DLIST_STATIC_INIT(&timeout_list);

static struct k_spinlock timeout_lock;

static bool can_wait_forever;

/* During a call to z_clock_announce(), the "current" time is "ahead"
 * of the reference used by timeout_list by this amount.
 */
static int announce_advance;

#if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)
int z_clock_hw_cycles_per_sec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
#endif

static struct _timeout *first(void)
{
	sys_dnode_t *t = sys_dlist_peek_head(&timeout_list);

	return t == NULL ? NULL : CONTAINER_OF(t, struct _timeout, node);
}

static struct _timeout *next(struct _timeout *t)
{
	sys_dnode_t *n = sys_dlist_peek_next(&timeout_list, &t->node);

	return n == NULL ? NULL : CONTAINER_OF(n, struct _timeout, node);
}

static void remove(struct _timeout *t)
{
	if (next(t) != NULL) {
		next(t)->dticks += t->dticks;
	}

	sys_dlist_remove(&t->node);
	t->dticks = _INACTIVE;
}

static s32_t adjust_elapsed(s32_t ticks)
{
	ticks -= z_clock_elapsed();
	return ticks < 0 ? 0 : ticks;
}

void _add_timeout(struct _timeout *to, _timeout_func_t fn, s32_t ticks)
{
	__ASSERT(to->dticks < 0, "");
	to->fn = fn;

	LOCKED(&timeout_lock) {
		struct _timeout *t;

		to->dticks = adjust_elapsed(ticks) + announce_advance;
		for (t = first(); t != NULL; t = next(t)) {
			__ASSERT(t->dticks >= 0, "");

			if (t->dticks > to->dticks) {
				t->dticks -= to->dticks;
				sys_dlist_insert_before(&timeout_list,
							&t->node, &to->node);
				break;
			}
			to->dticks -= t->dticks;
		}

		if (t == NULL) {
			sys_dlist_append(&timeout_list, &to->node);
		}
	}

	z_clock_set_timeout(_get_next_timeout_expiry(), false);
}

int _abort_timeout(struct _timeout *to)
{
	int ret = _INACTIVE;

	LOCKED(&timeout_lock) {
		if (to->dticks != _INACTIVE) {
			remove(to);
			ret = 0;
		}
	}

	return ret;
}

s32_t z_timeout_remaining(struct _timeout *to)
{
	s32_t ticks = 0;

	if (to->dticks == _INACTIVE) {
		return 0;
	}

	LOCKED(&timeout_lock) {
		for (struct _timeout *t = first(); t != NULL; t = next(t)) {
			ticks += t->dticks;
			if (to == t) {
				break;
			}
		}
	}

	return ticks;
}

void z_clock_announce(s32_t ticks)
{
	struct _timeout *t = NULL;

#ifdef CONFIG_TIMESLICING
	z_time_slice(ticks);
#endif

	LOCKED(&timeout_lock) {
		curr_tick += ticks;
		announce_advance = ticks;
	}

	while (true) {
		LOCKED(&timeout_lock) {
			t = first();
			if (t != NULL) {
				if (t->dticks <= announce_advance) {
					announce_advance -= t->dticks;
					t->dticks = 0;
					remove(t);
				} else {
					t->dticks -= announce_advance;
					t = NULL;
				}
			}
		}

		if (t == NULL) {
			break;
		}

		t->fn(t);
	}

	announce_advance = 0;
	z_clock_set_timeout(_get_next_timeout_expiry(), false);
}

s32_t _get_next_timeout_expiry(void)
{
	s32_t ret = 0;
	int max = can_wait_forever ? K_FOREVER : INT_MAX;

	LOCKED(&timeout_lock) {
		struct _timeout *to = first();

		ret = to == NULL ? max : adjust_elapsed(to->dticks);
	}

#ifdef CONFIG_TIMESLICING
	if (_current_cpu->slice_ticks && _current_cpu->slice_ticks < ret) {
		ret = _current_cpu->slice_ticks;
	}
#endif
	return ret;<commit_msg>kernel/timeout: Fix announcement tick logic<commit_after>/*
 * Copyright (c) 2018 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include <timeout_q.h>
#include <drivers/system_timer.h>
#include <sys_clock.h>
#include <spinlock.h>
#include <ksched.h>
#include <syscall_handler.h>

#define LOCKED(lck) for (k_spinlock_key_t __i = {},			\
					  __key = k_spin_lock(lck);	\
			!__i.key;					\
			k_spin_unlock(lck, __key), __i.key = 1)

static u64_t curr_tick;

static sys_dlist_t timeout_list = SYS_DLIST_STATIC_INIT(&timeout_list);

static struct k_spinlock timeout_lock;

static bool can_wait_forever;

/* Cycles left to process in the currently-executing z_clock_announce() */
static int announce_remaining;

#if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)
int z_clock_hw_cycles_per_sec = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
#endif

static struct _timeout *first(void)
{
	sys_dnode_t *t = sys_dlist_peek_head(&timeout_list);

	return t == NULL ? NULL : CONTAINER_OF(t, struct _timeout, node);
}

static struct _timeout *next(struct _timeout *t)
{
	sys_dnode_t *n = sys_dlist_peek_next(&timeout_list, &t->node);

	return n == NULL ? NULL : CONTAINER_OF(n, struct _timeout, node);
}

static void remove(struct _timeout *t)
{
	if (next(t) != NULL) {
		next(t)->dticks += t->dticks;
	}

	sys_dlist_remove(&t->node);
	t->dticks = _INACTIVE;
}

static s32_t adjust_elapsed(s32_t ticks)
{
	ticks -= announce_remaining == 0 ? z_clock_elapsed() : 0;
	return max(0, ticks);
}

void _add_timeout(struct _timeout *to, _timeout_func_t fn, s32_t ticks)
{
	__ASSERT(to->dticks < 0, "");
	to->fn = fn;

	LOCKED(&timeout_lock) {
		struct _timeout *t;

		to->dticks = adjust_elapsed(ticks) + announce_remaining;
		for (t = first(); t != NULL; t = next(t)) {
			__ASSERT(t->dticks >= 0, "");

			if (t->dticks > to->dticks) {
				t->dticks -= to->dticks;
				sys_dlist_insert_before(&timeout_list,
							&t->node, &to->node);
				break;
			}
			to->dticks -= t->dticks;
		}

		if (t == NULL) {
			sys_dlist_append(&timeout_list, &to->node);
		}
	}

	z_clock_set_timeout(_get_next_timeout_expiry(), false);
}

int _abort_timeout(struct _timeout *to)
{
	int ret = _INACTIVE;

	LOCKED(&timeout_lock) {
		if (to->dticks != _INACTIVE) {
			remove(to);
			ret = 0;
		}
	}

	return ret;
}

s32_t z_timeout_remaining(struct _timeout *to)
{
	s32_t ticks = 0;

	if (to->dticks == _INACTIVE) {
		return 0;
	}

	LOCKED(&timeout_lock) {
		for (struct _timeout *t = first(); t != NULL; t = next(t)) {
			ticks += t->dticks;
			if (to == t) {
				break;
			}
		}
	}

	return ticks;
}

void z_clock_announce(s32_t ticks)
{
	struct _timeout *t = NULL;

#ifdef CONFIG_TIMESLICING
	z_time_slice(ticks);
#endif

	announce_remaining = ticks;
	while (true) {
		LOCKED(&timeout_lock) {
			t = first();
			if (t != NULL) {
				if (t->dticks <= announce_remaining) {
					announce_remaining -= t->dticks;
					curr_tick += t->dticks;
					t->dticks = 0;
					remove(t);
				} else {
					t->dticks -= announce_remaining;
					t = NULL;
				}
			}
		}

		if (t == NULL) {
			break;
		}

		t->fn(t);
	}

	LOCKED(&timeout_lock) {
		curr_tick += announce_remaining;
		announce_remaining = 0;
	}

	z_clock_set_timeout(_get_next_timeout_expiry(), false);
}

s32_t _get_next_timeout_expiry(void)
{
	s32_t ret = 0;
	int max = can_wait_forever ? K_FOREVER : INT_MAX;

	LOCKED(&timeout_lock) {
		struct _timeout *to = first();

		ret = to == NULL ? max : adjust_elapsed(to->dticks);
	}

#ifdef CONFIG_TIMESLICING
	if (_current_cpu->slice_ticks && _current_cpu->slice_ticks < ret) {
		ret = _current_cpu->slice_ticks;
	}
#endif
	return ret;
{'fraction_non_alphanumeric': 0.1431159420289855, 'fraction_numerical': 0.009894091415830546, 'mean_word_length': 3.842780026990553, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 80, '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': '4178515', 'n_tokens_mistral': 3260, 'n_tokens_neox': 2968, 'n_words': 595}