//
// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
//
// The contents of this file are covered under the licence agreement in the
// file "LICENCE" distributed with Cforall.
//
// kernel_private.h --
//
// Author           : Thierry Delisle
// Created On       : Mon Feb 13 12:27:26 2017
// Last Modified By : Peter A. Buhr
// Last Modified On : Thu Mar 29 14:06:40 2018
// Update Count     : 3
//

#pragma once

#include "kernel"
#include "thread"

#include "alarm.h"


//-----------------------------------------------------------------------------
// Scheduler

extern "C" {
	void disable_interrupts();
	void enable_interrupts_noPoll();
	void enable_interrupts( __cfaabi_dbg_ctx_param );
}

void ScheduleThread( thread_desc * );
static inline void WakeThread( thread_desc * thrd ) {
	if( !thrd ) return;

	disable_interrupts();
	ScheduleThread( thrd );
	enable_interrupts( __cfaabi_dbg_ctx );
}
thread_desc * nextThread(cluster * this);

//Block current thread and release/wake-up the following resources
void BlockInternal(void);
void BlockInternal(__spinlock_t * lock);
void BlockInternal(thread_desc * thrd);
void BlockInternal(__spinlock_t * lock, thread_desc * thrd);
void BlockInternal(__spinlock_t * locks [], unsigned short count);
void BlockInternal(__spinlock_t * locks [], unsigned short count, thread_desc * thrds [], unsigned short thrd_count);
void LeaveThread(__spinlock_t * lock, thread_desc * thrd);

//-----------------------------------------------------------------------------
// Processor
void main(processorCtx_t *);
void start(processor * this);
void runThread(processor * this, thread_desc * dst);
void finishRunning(processor * this);
void terminate(processor * this);
void spin(processor * this, unsigned int * spin_count);

struct event_kernel_t {
	alarm_list_t alarms;
	__spinlock_t lock;
};

extern event_kernel_t * event_kernel;

//extern thread_local coroutine_desc * volatile this_coroutine;
//extern thread_local thread_desc *    volatile this_thread;
//extern thread_local processor *      volatile this_processor;

// extern volatile thread_local bool preemption_in_progress;
// extern volatile thread_local bool preemption_enabled;
// extern volatile thread_local unsigned short disable_preempt_count;

struct __cfa_kernel_preemption_state_t {
	bool enabled;
	bool in_progress;
	unsigned short disable_count;
};

extern volatile thread_local __cfa_kernel_preemption_state_t preemption_state;

//-----------------------------------------------------------------------------
// Threads
extern "C" {
      forall(dtype T | is_thread(T))
      void CtxInvokeThread(T * this);
}

extern void ThreadCtxSwitch(coroutine_desc * src, coroutine_desc * dst);

__cfaabi_dbg_debug_do(
	extern void __cfaabi_dbg_thread_register  ( thread_desc * thrd );
	extern void __cfaabi_dbg_thread_unregister( thread_desc * thrd );
)

//-----------------------------------------------------------------------------
// Utils
#define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)]


void doregister( struct thread_desc & thrd );
void unregister( struct thread_desc & thrd );

void doregister( struct cluster     & cltr );
void unregister( struct cluster     & cltr );

void doregister( struct cluster * cltr, struct processor * proc );
void unregister( struct cluster * cltr, struct processor * proc );

// Local Variables: //
// mode: c //
// tab-width: 4 //
// End: //
