//                              -*- Mode: CFA -*-
//
// 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 --
//
// Author           : Thierry Delisle
// Created On       : Tue Jan 17 12:27:26 2017
// Last Modified By : Thierry Delisle
// Last Modified On : --
// Update Count     : 0
//

#ifndef KERNEL_H
#define KERNEL_H

#include <stdbool.h>

#include "invoke.h"

extern "C" {
#include <pthread.h>
}

//-----------------------------------------------------------------------------
// Locks
bool try_lock( spinlock * );
void lock( spinlock * );
void unlock( spinlock * );

struct signal_once {
	volatile bool cond;
	struct spinlock lock;
	struct __thread_queue_t blocked;
};

void ?{}(signal_once * this);
void ^?{}(signal_once * this);

void wait( signal_once * );
void signal( signal_once * );

//-----------------------------------------------------------------------------
// Cluster
struct cluster {
	__thread_queue_t ready_queue;
	spinlock lock;
};

void ?{}(cluster * this);
void ^?{}(cluster * this);

//-----------------------------------------------------------------------------
// Processor
enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule };

//TODO use union, many of these fields are mutually exclusive (i.e. MULTI vs NOMULTI)
struct FinishAction {
	FinishOpCode action_code;
	thread_desc * thrd;
	spinlock * lock;
	spinlock ** locks;
	unsigned short lock_count;
	thread_desc ** thrds;
	unsigned short thrd_count;
};
static inline void ?{}(FinishAction * this) { 
	this->action_code = No_Action;
	this->thrd = NULL;
	this->lock = NULL;
}
static inline void ^?{}(FinishAction * this) {}

struct processor {
	struct processorCtx_t * runner;
	cluster * cltr;
	coroutine_desc * current_coroutine;
	thread_desc * current_thread;
	pthread_t kernel_thread;
	
	signal_once terminated;
	volatile bool is_terminated;

	struct FinishAction finish;

	struct alarm_node_t * preemption_alarm;
	unsigned int preemption;

	bool pending_preemption;

	char * last_enable;
};

void ?{}(processor * this);
void ?{}(processor * this, cluster * cltr);
void ^?{}(processor * this);

#endif //KERNEL_H

// Local Variables: //
// mode: CFA //
// tab-width: 6 //
// End: //
