| /* |
| * 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. |
| * |
| */ |
| |
| /** |
| * \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" |
| |
| struct net_buf; |
| |
| 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_COM 0x89 |
| #define PROCESS_EVENT_MAX 0x8a |
| |
| #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) |
| #define PROCESS_WAIT_WHILE(c) PT_WAIT_WHILE(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_PT_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_UNTIL(ev == PROCESS_EVENT_CONTINUE); \ |
| } 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 definition |
| * @{ |
| */ |
| |
| /** |
| * 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, buf, user_data) \ |
| static PT_THREAD(process_thread_##name(struct pt *process_pt, \ |
| process_event_t ev, \ |
| process_data_t data, \ |
| struct net_buf *buf, \ |
| void *user_data)) |
| |
| /** |
| * 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. |
| * |
| * 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. |
| * A configuration option allows removal of the readable name to save RAM. |
| * |
| * \param name The variable name of the process structure. |
| * \param strname The string representation of the process' name. |
| * |
| * \hideinitializer |
| */ |
| #if PROCESS_CONF_NO_PROCESS_NAMES |
| #define PROCESS(name, strname) \ |
| PROCESS_THREAD(name, ev, data); \ |
| struct process name = { NULL, \ |
| process_thread_##name } |
| #else |
| #define PROCESS(name, strname) \ |
| PROCESS_THREAD(name, ev, data, buf, user_data); \ |
| struct process name = { NULL, strname, \ |
| process_thread_##name } |
| #endif |
| |
| /** @} */ |
| |
| struct process { |
| struct process *next; |
| #if PROCESS_CONF_NO_PROCESS_NAMES |
| #define PROCESS_NAME_STRING(process) "" |
| #else |
| const char *name; |
| #define PROCESS_NAME_STRING(process) (process)->name |
| #endif |
| PT_THREAD((* thread)(struct pt *, process_event_t, process_data_t, |
| struct net_buf *, void *user_data)); |
| struct pt pt; |
| unsigned char state, needspoll; |
| void *user_data; |
| }; |
| |
| /** |
| * \name Functions called from application programs |
| * @{ |
| */ |
| |
| /** |
| * Start a process. |
| * |
| * \param p A pointer to a process structure. |
| * |
| * \param data An argument pointer that can be passed to the new |
| * process |
| * |
| */ |
| CCIF void process_start(struct process *p, process_data_t data, void *user_data); |
| |
| /** |
| * 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 auxiliary 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. |
| */ |
| CCIF 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. |
| */ |
| CCIF void process_post_synch(struct process *p, |
| process_event_t ev, process_data_t data, |
| struct net_buf *buf); |
| |
| /** |
| * \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() |
| */ |
| CCIF 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 |
| CCIF extern struct process *process_current; |
| |
| /** |
| * 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. |
| */ |
| CCIF 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. |
| */ |
| CCIF 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 actually 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(struct net_buf *buf); |
| |
| |
| /** |
| * Check if a process is running. |
| * |
| * This function checks if a specific process is running. |
| * |
| * \param p The process. |
| * \retval Non-zero if the process is running. |
| * \retval Zero if the process is not running. |
| */ |
| CCIF int process_is_running(struct process *p); |
| |
| /** |
| * Number of events waiting to be processed. |
| * |
| * \return The number of events that are currently waiting to be |
| * processed. |
| */ |
| int process_nevents(void); |
| |
| /** @} */ |
| |
| CCIF extern struct process *process_list; |
| |
| #define PROCESS_LIST() process_list |
| |
| #endif /* PROCESS_H_ */ |
| |
| /** @} */ |
| /** @} */ |