OpenModem/bertos/kern/proc_p.h
2014-04-03 22:21:37 +02:00

230 lines
6.3 KiB
C

/**
* \file
* <!--
* This file is part of BeRTOS.
*
* Bertos is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*
* Copyright 2001, 2004 Develer S.r.l. (http://www.develer.com/)
* Copyright 1999, 2000, 2001 Bernie Innocenti <bernie@codewiz.org>
*
* -->
*
* \brief Internal scheduler structures and definitions for processes.
*
* \author Bernie Innocenti <bernie@codewiz.org>
*/
#ifndef KERN_PROC_P_H
#define KERN_PROC_P_H
#include "cfg/cfg_proc.h"
#include "cfg/cfg_monitor.h"
#include <cfg/compiler.h>
#include <cpu/types.h> /* for cpu_stack_t */
#include <cpu/irq.h> // IRQ_ASSERT_DISABLED()
#include <kern/proc.h> // struct Process
#ifndef asm_switch_context
/**
* CPU dependent context switching routines.
*
* Saving and restoring the context on the stack is done by a CPU-dependent
* support routine which usually needs to be written in assembly.
*/
EXTERN_C void asm_switch_context(cpu_stack_t **new_sp, cpu_stack_t **save_sp);
#endif
/**
* \name Flags for Process.flags.
* \{
*/
#define PF_FREESTACK BV(0) /**< Free the stack when process dies */
/*\}*/
/** Track running processes. */
extern REGISTER Process *current_process;
/**
* Track ready processes.
*
* Access to this list must be performed with interrupts disabled
*/
extern REGISTER List proc_ready_list;
#if CONFIG_KERN_PRI
# if CONFIG_KERN_PRI_INHERIT
#define __prio_orig(proc) (proc->orig_pri)
#define __prio_inh(proc) (LIST_EMPTY(&(proc)->inh_list) ? INT_MIN : \
((PriNode *)LIST_HEAD(&proc->inh_list))->pri)
#define __prio_proc(proc) (__prio_inh(proc) > __prio_orig(proc) ? \
__prio_inh(proc) : __prio_orig(proc))
# endif
#define prio_next() (LIST_EMPTY(&proc_ready_list) ? INT_MIN : \
((PriNode *)LIST_HEAD(&proc_ready_list))->pri)
#define prio_proc(proc) (proc->link.pri)
#define prio_curr() prio_proc(current_process)
#define SCHED_ENQUEUE_INTERNAL(proc) \
LIST_ENQUEUE(&proc_ready_list, &(proc)->link)
#define SCHED_ENQUEUE_HEAD_INTERNAL(proc) \
LIST_ENQUEUE_HEAD(&proc_ready_list, &(proc)->link)
#else
#define prio_next() 0
#define prio_proc(proc) 0
#define prio_curr() 0
#define SCHED_ENQUEUE_INTERNAL(proc) ADDTAIL(&proc_ready_list, &(proc)->link)
#define SCHED_ENQUEUE_HEAD_INTERNAL(proc) ADDHEAD(&proc_ready_list, &(proc)->link)
#endif
/**
* Enqueue a process in the ready list.
*
* Always use this macro to instert a process in the ready list, as its
* might vary to implement a different scheduling algorithms.
*
* \note Access to the scheduler ready list must be performed with
* interrupts disabled.
*/
#define SCHED_ENQUEUE(proc) do { \
IRQ_ASSERT_DISABLED(); \
LIST_ASSERT_VALID(&proc_ready_list); \
SCHED_ENQUEUE_INTERNAL(proc); \
} while (0)
#define SCHED_ENQUEUE_HEAD(proc) do { \
IRQ_ASSERT_DISABLED(); \
LIST_ASSERT_VALID(&proc_ready_list); \
SCHED_ENQUEUE_HEAD_INTERNAL(proc); \
} while (0)
#if CONFIG_KERN_PRI
/**
* Changes the priority of an already enqueued process.
*
* Searches and removes the process from the ready list, then uses LIST_ENQUEUE(()
* to insert again to fix priority.
*
* No action is performed for processes that aren't in the ready list, eg. in semaphore queues.
*
* \note Performance could be improved with a different implementation of priority list.
*/
INLINE void sched_reenqueue(struct Process *proc)
{
IRQ_ASSERT_DISABLED();
LIST_ASSERT_VALID(&proc_ready_list);
Node *n;
PriNode *pos = NULL;
FOREACH_NODE(n, &proc_ready_list)
{
if (n == &proc->link.link)
{
pos = (PriNode *)n;
break;
}
}
// only remove and enqueue again if process is already in the ready list
// otherwise leave it alone
if (pos)
{
REMOVE(&proc->link.link);
LIST_ENQUEUE(&proc_ready_list, &proc->link);
}
}
#endif //CONFIG_KERN_PRI
/* Process trampoline */
void proc_entry(void);
/* Schedule another process *without* adding the current one to the ready list. */
void proc_switch(void);
/* Immediately schedule a particular process bypassing the scheduler. */
void proc_wakeup(Process *proc);
/* Initialize a scheduler class. */
void proc_schedInit(void);
#if CONFIG_KERN_MONITOR
/** Initialize the monitor */
void monitor_init(void);
/** Register a process into the monitor */
void monitor_add(Process *proc, const char *name);
/** Unregister a process from the monitor */
void monitor_remove(Process *proc);
/** Rename a process */
void monitor_rename(Process *proc, const char *name);
#endif /* CONFIG_KERN_MONITOR */
/*
* Quantum related macros are used in the
* timer module and must be empty when
* kernel is disabled.
*/
#if (CONFIG_KERN && CONFIG_KERN_PREEMPT)
INLINE int preempt_quantum(void)
{
extern int _proc_quantum;
return _proc_quantum;
}
INLINE void proc_decQuantum(void)
{
extern int _proc_quantum;
if (_proc_quantum > 0)
_proc_quantum--;
}
INLINE void preempt_reset_quantum(void)
{
extern int _proc_quantum;
_proc_quantum = CONFIG_KERN_QUANTUM;
}
#else /* !(CONFIG_KERN && CONFIG_KERN_PREEMPT) */
INLINE int preempt_quantum(void)
{
return 0;
}
INLINE void proc_decQuantum(void)
{
}
INLINE void preempt_reset_quantum(void)
{
}
#endif /* (CONFIG_KERN && CONFIG_KERN_PREEMPT) */
#endif /* KERN_PROC_P_H */