/**
 * @file thread.h
 * @brief Heder file for implementation of threads
 * 
 * This file is based on Kalisto, Development Kernel copyrighted (c) to 
 * Distributed Systems Research Group MFF UK, Czech republic.
 */

#ifndef _THREAD_H_
#define _THREAD_H_

#include "sys.h"
#include "timers.h"


/**
 * The main CP0 status configuration for kernel threads. Switch to the kernel
 * mode, enable all interrupts and mark coprocessor 0 as usable (this is
 * not necessary because cp0 is available in the kernel mode automatically).
 */
#define KERNEL_THREAD_STATUS	\
(				\
	cp0_status_kx_mask 	\
	| cp0_status_ie_mask 	\
	| cp0_status_im_mask	\
	| cp0_status_cu0_mask	\
)

/** 
 * Size of the stack for kernel thread
 */
#define KERNEL_STACK_SIZE 4096

//used in condvars
/** how was the thread woken? thread was not waked up yet */ 
#define WOKEN_UNDEFINED 0
/** how was the thread woken? was woken by timer (moved  from sleeping to runnable threads to be scheduled) */
#define WOKEN_BY_TIMER 1
/** how was the thread woken? thread was waken by another thread */
#define WOKEN_BY_ANOTHER_THREAD 2

/*
 * Thread status definitions
 *
 * TS_DISABLED
 * 	the thread is not prepared to enter the internal structures
 * TS_READY_TO_RUN
 * 	the thread is active and is waiting for a processor
 * TS_SLEEP
 * 	the thread is disabled - waiting on a synchronization primitive
 * TS_RUN
 * 	the thread is active and running
 */
 
/** 
 * returned on thread creation if no memory is available or some other problem occur
 */ 
#define THREAD_INVALID 	-1

/**
 * Describes actual state of thread in the system
 */
enum _thread_statuses {
	/** the thread is not prepared to enter the internal structures */
	THRS_DISABLED,
	/** the thread is active and is waiting for a processor */
	THRS_READY,
	/** the thread is waiting to some time to be woken up */
	THRS_SLEEPING,
	/** the thread was suspended on some synchro primitive or by call thread_suspend() */
	THRS_SUSPENDED,
	/** thread is  waiting in the system to be removed (if detached or joined) or to be joined */
	THRS_ZOMBIE
};

// for debuging purposes only, stores names of states
extern char * thread_status [6];

/**
 * for debuging purposes only, replace name of the state (state is enum, uncomfortable for debuging)  
 */
#define ts(status) (thread_status[status])



typedef void (*thread_start_function)(void *);
struct valid_thread_item_struct;

/** 
 * Is used by thread struct, conteains pointers to previous and next thread in some queue 
 * @see thread_t
 * 
 */
struct thread_queue_struct {
	/** 
	 * @{
	 * @name Pointers to prev and next item 
	 * @}
	 */
	struct thread_struct *next, *prev;
	/** @} */	
};

/** Definition in standart .._t notation */
typedef struct thread_queue_struct thread_queue_struct_t;

void thread_queue_struct_init(thread_queue_struct_t queue);

/** 
 * Thread contains in this time pointers to two queues, one of them is for keeping
 * thread in valid thread queue (VALID) and second for, lets say, actual queue of the thread (GENERAL)
 * This can be queue on synchro primitive or runnable queue 
 */
enum queue_types {
	GENERAL, VALID	
};

typedef struct thread_struct{
		/** State of the thread, see _thread_statuses */
	int state;
	/** pointer to top of stack allocated for this thread where the context is stored */
	int *kernel_stack_context;
	/** pointer by switch context function */
	int *kernel_stack_top;
	/** pointer to stack allocated for this thread */
	int *kernel_stack;
	/** nr of interrupts for current thread. is used for disabling and enabling interrupts */
	int interrupt_counter;
	/** pointers to the ques, in which is thread actualy enqueued, valid threads and sleep/ready queue */
	thread_queue_struct_t queues[2];
	/** number increasing of the semaphore, for warnings if trying to kill thread with this > 0 */
	int num_semaphores_inc;
	/** thread, that called join() to this thread */
	struct thread_struct * joined; 
	/** id of the thread */
	int id;
	/** is this thread detached? */
	int detached;
	/** finished is set, when some thread call thread kill to this thread */
	int finished;
	/** for thread sleeping functions, time, when were thread given to sleeping thread queue */
	unsigned sleep_start_time;
	/** how long should the thread sleep */
	unsigned sleep_length; 
	/** used for disable a enable interrupts */
	int interrupt_previous_state;
	/** counting RW locks, its not good, when killing some thread owning something like this */
	int resource_couter;
	/** how was thread woke up, by timer or by another thread */ 
	int woken_up;
	/**thread  timer, used for sleeping threads */
	timer_t timer;
	/** pointer to pointer to queue in which is the thread enqueued (must be removed from it correctly) */
	struct thread_struct ** actual_queue;

} *thread_t;

/** handle to thread currently running in the system */
extern thread_t current_thread;
extern thread_t idle_thread;

/** nr of living threads in the system. Note: zombie is not living */
extern int living_threads;

//typedef thread_t thread_queue_t; 
inline unsigned thread_get_wakeup_time_in_ticks(thread_t thread);

void thread_set_state(thread_t t , int state);

void thread_remove(thread_t t);

thread_t thread_create_system (void (*start) (void), int status);

struct thread_struct * init_thread (void (*start) (), void *data, int status);

//Functions implemented
int thread_create (thread_t * thread_ptr, void (* thread_start) (void *), void * data);
thread_t thread_get_current (void);
int thread_join (thread_t thr);
int thread_join_timeout (thread_t thr, const unsigned int usec);
int thread_detach (thread_t thr);
void thread_sleep (const unsigned int sec);
void thread_usleep (const unsigned int usec);
void thread_yield (void);
void thread_suspend (void);
int thread_wakeup (thread_t thr);
void thread_wakeup_by_timer (timer_t * tmr, void* data);
int thread_kill (thread_t thr);

int thread_is_valid(thread_t thr);
void __thread_dprint(thread_t thr);

#endif /* _THREAD_H_ */
