/*
 * Copyright (c) 2002-2004  Brian S. Dean <bsd@bdmicro.com>
 * All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY BRIAN S. DEAN ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL BRIAN S. DEAN BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 * 
 */

/*
 * $Id: threads.h,v 1.1 2010/10/19 05:18:47 bsd Exp $
 *
 * Threads package header declarations.
 *
 *
 * Author : Brian S. Dean <bsd@bsdhome.com>
 * Date   : 2002-08-29
 *
 */

#ifndef __threads_h__
#define __threads_h__

#include <inttypes.h>

/*
 * max sched timer ticks before preempting the running thread
 */
#define MAX_QUANTUM 5

typedef struct thread_t {
  struct thread_t * runq_prev;    /* previous thread in run queue */
  struct thread_t * runq_next;    /* next thread in run queue */
  struct thread_t * sleep_q_next; /* next thread in sleep queue */
  uint8_t         * sp;           /* thread stack pointer */
  uint8_t         * stack;        /* start of thread stack */
  uint8_t           priority;     /* thread priority */
  uint8_t           ticks;        /* sched timer ticks remaining */
  uint8_t           quantum;      /* sched timer ticks allowed */
  uint8_t           flags;        /* thread flags - see AVRTH_* flags below */
  uint16_t          stack_size;   /* thread stack size */
  uint16_t          sleep_timer;  /* sleep timer */
  void            * parm;         /* parameter pointer */
} THREAD;

#define AVRTH_VALID    0x01  /* thread is valid (in use) */
#define AVRTH_RUNNABLE 0x02  /* thread is runnable */


#define THREADS(n, istacksz) \
  THREAD thread[n+2]; \
  THREAD * main_thread; \
  THREAD_DEF(idle, istacksz)

#define THREAD_DEF(name, stacksz) \
  uint8_t name##_stack[stacksz]; \
  THREAD * name##_thread

#define N_THREADS  (sizeof(thread)/sizeof(THREAD))

/*
 * User code needs to declare these arrays, sized accordingly
 */
extern THREAD  thread[];             /* max # threads allowed */
extern uint8_t idle_stack[];         /* storage for idle thread stack */

/*
 * these are declared within the threads code
 */
extern THREAD * current_thread;
extern uint8_t n_threads;
extern uint8_t thread_preemption;


void thread_tick(void);

THREAD * threads_init(uint8_t max_threads, uint16_t mstacksz, uint16_t istacksz, 
                      uint8_t main_prio, uint8_t preemption);

void thread_yield(void);

THREAD * thread_create(void (*entry)(void), uint8_t * stack, 
                       uint16_t stack_size, uint8_t priority, void * parm);

void thread_sleep(uint16_t ms);

void thread_start(THREAD * t);

void thread_stop(THREAD * t);

void thread_kill(THREAD * t);

#endif

