//                              -*- 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.
//
// threads --
//
// Author           : Thierry Delisle
// Created On       : Tue Jan 17 12:27:26 2016
// 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>
}

//-----------------------------------------------------------------------------
// Cluster
struct cluster {
	simple_thread_list ready_queue;
	pthread_spinlock_t lock;
};

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

//-----------------------------------------------------------------------------
// Processor
struct processor {
	struct processorCtx_t * ctx;
	cluster * cltr;
	coroutine * current_coroutine;
	thread * current_thread;
	pthread_t kernel_thread;
	simple_lock lock;
	volatile bool terminated;
};

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


//-----------------------------------------------------------------------------
// Locks

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

void lock( simple_lock * );
void unlock( simple_lock * );

struct pthread_spinlock_guard {
	pthread_spinlock_t * lock;
};

static inline void ?{}( pthread_spinlock_guard * this, pthread_spinlock_t * lock ) {
	this->lock = lock;
	pthread_spin_lock( this->lock );
}

static inline void ^?{}( pthread_spinlock_guard * this ) {
	pthread_spin_unlock( this->lock );
}

// //Simple spinlock implementation from 
// //http://stackoverflow.com/questions/1383363/is-my-spin-lock-implementation-correct-and-optimal
// //Not optimal but correct
// #define VOL 

// struct simple_spinlock {
// 	VOL int lock;
// };

// extern VOL int __sync_lock_test_and_set( VOL int *, VOL int);
// extern void __sync_synchronize();

// static inline void lock( simple_spinlock * this ) {
//     while (__sync_lock_test_and_set(&this->lock, 1)) {
//         // Do nothing. This GCC builtin instruction
//         // ensures memory barrier.
//     }
// }

// static inline void unlock( simple_spinlock * this ) {
//     __sync_synchronize(); // Memory barrier.
//     this->lock = 0;
// }

#endif //KERNEL_H

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