Import of the contiki-2.x development code from the SICS internal CVS server
This commit is contained in:
commit
c9e808d638
671 changed files with 95332 additions and 0 deletions
526
core/sys/process.h
Normal file
526
core/sys/process.h
Normal file
|
@ -0,0 +1,526 @@
|
|||
/*
|
||||
* Copyright (c) 2005, Swedish Institute of Computer Science
|
||||
* 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.
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 THE INSTITUTE OR CONTRIBUTORS 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.
|
||||
*
|
||||
* This file is part of the Contiki operating system.
|
||||
*
|
||||
* @(#)$Id: process.h,v 1.1 2006/06/17 22:41:20 adamdunkels Exp $
|
||||
*/
|
||||
|
||||
/**
|
||||
* \addtogroup sys
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup process Contiki processes
|
||||
*
|
||||
* A process in Contiki consists of a single \ref pt protothread.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Header file for the Contiki process interface.
|
||||
* \author
|
||||
* Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
#ifndef __PROCESS_H__
|
||||
#define __PROCESS_H__
|
||||
|
||||
#include "sys/pt.h"
|
||||
#include "sys/cc.h"
|
||||
|
||||
typedef unsigned char process_event_t;
|
||||
typedef void * process_data_t;
|
||||
typedef unsigned char process_num_events_t;
|
||||
|
||||
/**
|
||||
* \name Return values
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Return value indicating that an operation was successful.
|
||||
*
|
||||
* This value is returned to indicate that an operation
|
||||
* was successful.
|
||||
*/
|
||||
#define PROCESS_ERR_OK 0
|
||||
/**
|
||||
* \brief Return value indicating that the event queue was full.
|
||||
*
|
||||
* This value is returned from process_post() to indicate
|
||||
* that the event queue was full and that an event could
|
||||
* not be posted.
|
||||
*/
|
||||
#define PROCESS_ERR_FULL 1
|
||||
/* @} */
|
||||
|
||||
#define PROCESS_NONE NULL
|
||||
|
||||
#ifndef PROCESS_CONF_NUMEVENTS
|
||||
#define PROCESS_CONF_NUMEVENTS 32
|
||||
#endif /* PROCESS_CONF_NUMEVENTS */
|
||||
|
||||
#define PROCESS_EVENT_NONE 0x80
|
||||
#define PROCESS_EVENT_INIT 0x81
|
||||
#define PROCESS_EVENT_POLL 0x82
|
||||
#define PROCESS_EVENT_EXIT 0x83
|
||||
#define PROCESS_EVENT_SERVICE_REMOVED 0x84
|
||||
#define PROCESS_EVENT_CONTINUE 0x85
|
||||
#define PROCESS_EVENT_MSG 0x86
|
||||
#define PROCESS_EVENT_EXITED 0x87
|
||||
#define PROCESS_EVENT_TIMER 0x88
|
||||
#define PROCESS_EVENT_MAX 0x89
|
||||
|
||||
#define PROCESS_BROADCAST NULL
|
||||
#define PROCESS_ZOMBIE ((struct process *)0x1)
|
||||
|
||||
/**
|
||||
* \name Process protothread functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Define the beginning of a process.
|
||||
*
|
||||
* This macro defines the beginning of a process, and must always
|
||||
* appear in a PROCESS_THREAD() definition. The PROCESS_END() macro
|
||||
* must come at the end of the process.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_BEGIN() PT_BEGIN(process_pt)
|
||||
|
||||
/**
|
||||
* Define the end of a process.
|
||||
*
|
||||
* This macro defines the end of a process. It must appear in a
|
||||
* PROCESS_THREAD() definition and must always be included. The
|
||||
* process exits when the PROCESS_END() macro is reached.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_END() PT_END(process_pt)
|
||||
|
||||
/**
|
||||
* Wait for an event to be posted to the process.
|
||||
*
|
||||
* This macro blocks the currently running process until the process
|
||||
* receives an event.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_WAIT_EVENT() PROCESS_YIELD()
|
||||
|
||||
/**
|
||||
* Wait for an event to be posted to the process, with an extra
|
||||
* condition.
|
||||
*
|
||||
* This macro is similar to PROCESS_WAIT_EVENT() in that it blocks the
|
||||
* currently running process until the process receives an event. But
|
||||
* PROCESS_WAIT_EVENT_UNTIL() takes an extra condition which must be
|
||||
* true for the process to continue.
|
||||
*
|
||||
* \param c The condition that must be true for the process to continue.
|
||||
* \sa PT_WAIT_UNTIL()
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_WAIT_EVENT_UNTIL(c) PROCESS_YIELD_UNTIL(c)
|
||||
|
||||
/**
|
||||
* Yield the currently running process.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_YIELD() PT_YIELD(process_pt)
|
||||
|
||||
/**
|
||||
* Yield the currently running process until a condition occurs.
|
||||
*
|
||||
* This macro is different from PROCESS_WAIT_UNTIL() in that
|
||||
* PROCESS_YIELD_UNTIL() is guaranteed to always yield at least
|
||||
* once. This ensures that the process does not end up in an infinite
|
||||
* loop and monopolizing the CPU.
|
||||
*
|
||||
* \param c The condition to wait for.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_YIELD_UNTIL(c) PT_YIELD_UNTIL(process_pt, c)
|
||||
|
||||
/**
|
||||
* Wait for a condition to occur.
|
||||
*
|
||||
* This macro does not guarantee that the process yields, and should
|
||||
* therefore be used with care. In most cases, PROCESS_WAIT_EVENT(),
|
||||
* PROCESS_WAIT_EVENT_UNTIL(), PROCESS_YIELD() or
|
||||
* PROCESS_YIELD_UNTIL() should be used instead.
|
||||
*
|
||||
* \param c The condition to wait for.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_WAIT_UNTIL(c) PT_WAIT_UNTIL(process_pt, c)
|
||||
|
||||
/**
|
||||
* Exit the currently running process.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_EXIT() PT_EXIT(process_pt)
|
||||
|
||||
/**
|
||||
* Spawn a protothread from the process.
|
||||
*
|
||||
* \param pt The protothread state (struct pt) for the new protothread
|
||||
* \param thread The call to the protothread function.
|
||||
* \sa PT_SPAWN()
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_SPAWN(pt, thread) PT_SPAWN(process_pt, pt, thread)
|
||||
|
||||
/**
|
||||
* Yield the process for a short while.
|
||||
*
|
||||
* This macro yields the currently running process for a short while,
|
||||
* thus letting other processes run before the process continues.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_PAUSE() do { \
|
||||
process_post(PROCESS_CURRENT(), PROCESS_EVENT_CONTINUE, NULL); \
|
||||
PROCESS_WAIT_EVENT(); \
|
||||
} while(0)
|
||||
|
||||
/** @} end of protothread functions */
|
||||
|
||||
/**
|
||||
* \name Poll and exit handlers
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* Specify an action when a process is polled.
|
||||
*
|
||||
* \note This declaration must come immediately before the
|
||||
* PROCESS_BEGIN() macro.
|
||||
*
|
||||
* \param handler The action to be performed.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_POLLHANDLER(handler) if(ev == PROCESS_EVENT_POLL) { handler; }
|
||||
|
||||
/**
|
||||
* Specify an action when a process exits.
|
||||
*
|
||||
* \note This declaration must come immediately before the
|
||||
* PROCESS_BEGIN() macro.
|
||||
*
|
||||
* \param handler The action to be performed.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_EXITHANDLER(handler) if(ev == PROCESS_EVENT_EXIT) { handler; }
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \name Process declaration and definion
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Define the body of a process.
|
||||
*
|
||||
* This macro is used to define the body (protothread) of a
|
||||
* process. The process is called whenever an event occurs in the
|
||||
* system, A process always start with the PROCESS_BEGIN() macro and
|
||||
* end with the PROCESS_END() macro.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_THREAD(name, ev, data) \
|
||||
static PT_THREAD(process_thread_##name(struct pt *process_pt, \
|
||||
process_event_t ev, \
|
||||
process_data_t data))
|
||||
|
||||
#if PROCESS_LOADABLE
|
||||
#define PROCESS_LOAD(name) const struct process *process_load = &name;
|
||||
#else /* PROCESS_LOADABLE */
|
||||
#define PROCESS_LOAD(name)
|
||||
#endif /* PROCESS_LOADABLE */
|
||||
extern const struct process *process_load;
|
||||
|
||||
/**
|
||||
* Declare the name of a process.
|
||||
*
|
||||
* This macro is typically used in header files to declare the name of
|
||||
* a process that is implemented in the C file.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_NAME(name) extern struct process name
|
||||
|
||||
/**
|
||||
* Declare a process that should not be automatically loaded.
|
||||
*
|
||||
* This macro is similar to the PROCESS() declaration, with the
|
||||
* difference that for programs that are compiled as loadable
|
||||
* programs, processes declared with the PROCESS_NOLOAD() declaration
|
||||
* will not be automatically started when the program is loaded.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_NOLOAD(name, strname) \
|
||||
PROCESS_THREAD(name, ev, data); \
|
||||
struct process name = { NULL, strname, \
|
||||
process_thread_##name };
|
||||
/**
|
||||
* Declare a process.
|
||||
*
|
||||
* This macro declares a process. The process has two names: the
|
||||
* variable of the process structure, which is used by the C program,
|
||||
* and a human readable string name, which is used when debugging.
|
||||
*
|
||||
* \note For programs that are compiled as loadable programs: the
|
||||
* process declared with the PROCESS() declaration will be
|
||||
* automatically started when the program is loaded. The
|
||||
* PROCESS_NOLOAD() declaration can be used to declare a process that
|
||||
* shouldn't be automatically loaded.
|
||||
*
|
||||
* \param name The variable name of the process structure.
|
||||
* \param strname The string repressentation of the process' name.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS(name, strname) \
|
||||
PROCESS_NOLOAD(name, strname); \
|
||||
PROCESS_LOAD(name)
|
||||
|
||||
/** @} */
|
||||
|
||||
struct process {
|
||||
struct process *next;
|
||||
const char *name;
|
||||
PT_THREAD((* thread)(struct pt *, process_event_t, process_data_t));
|
||||
struct pt pt;
|
||||
unsigned char state;
|
||||
};
|
||||
|
||||
/**
|
||||
* \name Functions called from application programs
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Start a process.
|
||||
*
|
||||
* \param p A pointer to a process structure.
|
||||
*
|
||||
* \param arg An argument pointer that can be passed to the new
|
||||
* process
|
||||
*
|
||||
*/
|
||||
void process_start(struct process *p, char *arg);
|
||||
|
||||
/**
|
||||
* Post an asynchronous event.
|
||||
*
|
||||
* This function posts an asynchronous event to one or more
|
||||
* processes. The handing of the event is deferred until the target
|
||||
* process is scheduled by the kernel. An event can be broadcast to
|
||||
* all processes, in which case all processes in the system will be
|
||||
* scheduled to handle the event.
|
||||
*
|
||||
* \param ev The event to be posted.
|
||||
*
|
||||
* \param data The auxillary data to be sent with the event
|
||||
*
|
||||
* \param p The process to which the event should be posted, or
|
||||
* PROCESS_BROADCAST if the event should be posted to all processes.
|
||||
*
|
||||
* \retval PROCESS_ERR_OK The event could be posted.
|
||||
*
|
||||
* \retval PROCESS_ERR_FULL The event queue was full and the event could
|
||||
* not be posted.
|
||||
*/
|
||||
int process_post(struct process *p, process_event_t ev, process_data_t data);
|
||||
|
||||
/**
|
||||
* Post a synchronous event to a process.
|
||||
*
|
||||
* \param p A pointer to the process' process structure.
|
||||
*
|
||||
* \param ev The event to be posted.
|
||||
*
|
||||
* \param data A pointer to additional data that is posted together
|
||||
* with the event.
|
||||
*/
|
||||
void process_post_synch(struct process *p,
|
||||
process_event_t ev, process_data_t data);
|
||||
|
||||
/**
|
||||
* \brief Cause a process to exit
|
||||
* \param p The process that is to be exited
|
||||
*
|
||||
* This function causes a process to exit. The process can
|
||||
* either be the currently executing process, or another
|
||||
* process that is currently running.
|
||||
*
|
||||
* \sa PROCESS_CURRENT()
|
||||
*/
|
||||
void process_exit(struct process *p);
|
||||
|
||||
|
||||
/**
|
||||
* Get a pointer to the currently running process.
|
||||
*
|
||||
* This macro get a pointer to the currently running
|
||||
* process. Typically, this macro is used to post an event to the
|
||||
* current process with process_post().
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define PROCESS_CURRENT() process_current
|
||||
extern struct process *process_current;
|
||||
|
||||
#define PROCESS_SET_FLAGS(flags)
|
||||
#define PROCESS_NO_BROADCAST
|
||||
|
||||
/**
|
||||
* Switch context to another process
|
||||
*
|
||||
* This function switch context to the specified process and executes
|
||||
* the code as if run by that process. Typical use of this function is
|
||||
* to switch context in services, called by other processes. Each
|
||||
* PROCESS_CONTEXT_BEGIN() must be followed by the
|
||||
* PROCESS_CONTEXT_END() macro to end the context switch.
|
||||
*
|
||||
* Example:
|
||||
\code
|
||||
PROCESS_CONTEXT_BEGIN(&test_process);
|
||||
etimer_set(&timer, CLOCK_SECOND);
|
||||
PROCESS_CONTEXT_END(&test_process);
|
||||
\endcode
|
||||
*
|
||||
* \param p The process to use as context
|
||||
*
|
||||
* \sa PROCESS_CONTEXT_END()
|
||||
* \sa PROCESS_CURRENT()
|
||||
*/
|
||||
#define PROCESS_CONTEXT_BEGIN(p) {\
|
||||
struct process *tmp_current = PROCESS_CURRENT();\
|
||||
process_current = p
|
||||
|
||||
/**
|
||||
* End a context switch
|
||||
*
|
||||
* This function ends a context switch and changes back to the
|
||||
* previous process.
|
||||
*
|
||||
* \param p The process used in the context switch
|
||||
*
|
||||
* \sa PROCESS_CONTEXT_START()
|
||||
*/
|
||||
#define PROCESS_CONTEXT_END(p) process_current = tmp_current; }
|
||||
|
||||
/**
|
||||
* \brief Allocate a global event number.
|
||||
* \return The allocated event number
|
||||
*
|
||||
* In Contiki, event numbers above 128 are global and may
|
||||
* be posted from one process to another. This function
|
||||
* allocates one such event number.
|
||||
*
|
||||
* \note There currently is no way to deallocate an allocated event
|
||||
* number.
|
||||
*/
|
||||
process_event_t process_alloc_event(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \name Functions called from device drivers
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Request a process to be polled.
|
||||
*
|
||||
* This function typically is called from an interrupt handler to
|
||||
* cause a process to be polled.
|
||||
*
|
||||
* \param p A pointer to the process' process structure.
|
||||
*/
|
||||
void process_poll(struct process *p);
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \name Functions called by the system and boot-up code
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Initialize the process module.
|
||||
*
|
||||
* This function initializes the process module and should
|
||||
* be called by the system boot-up code.
|
||||
*/
|
||||
void process_init(void);
|
||||
|
||||
/**
|
||||
* Run the system once - call poll handlers and process one event.
|
||||
*
|
||||
* This function should be called repeatedly from the main() program
|
||||
* to actuall run the Contiki system. It calls the necessary poll
|
||||
* handlers, and processes one event. The function returns the number
|
||||
* of events that are waiting in the event queue so that the caller
|
||||
* may choose to put the CPU to sleep when there are no pending
|
||||
* events.
|
||||
*
|
||||
* \return The number of events that are currently waiting in the
|
||||
* event queue.
|
||||
*/
|
||||
int process_run(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
extern struct process *process_list;
|
||||
|
||||
#define PROCESS_LIST() process_list
|
||||
|
||||
#endif /* __PROCESS_H__ */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
Loading…
Add table
Add a link
Reference in a new issue