00. 目录
文章目录
- 00. 目录
- 01. 进程类型
- 02. 进程结构
- 03. 事件
- 04. 进程调度函数
- 05. 程序实例
- 06. process实现
- 07. 附录
01. 进程类型
进程类型主要有**协同式(cooperative)和抢占式(preemptive)**两种。
协同式进程,要等其他进程运行完进程实体函数(进程不一定运行完,这个时候有可能是阻塞,总之只要执行到return语句,具体看),然后才能开始运行。
抢占式进程,会优先运行,当有抢占式进程需要执行时,协同式进程将会被挂起,直到抢占式进程实体函数执行完毕。中断和实时任务就需要用抢占式进程实现。
02. 进程结构
2.1 进程结构体
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//取名字
#endifPT_THREAD((* thread)(struct pt *, process_event_t, process_data_t));//进程执行实体函数struct pt pt;//pt结构体,存储实体函数阻塞时的位置unsigned char state, needspoll;//state是进程状态,needspoll标志进程是否需要优先执行
};
2.2 进程链表
process_list ----->
只要抓住了进程链表头process_list,那么进程的各种操作都做得到了。
2.3 进程执行实体函数
PROCESS_THREAD(hello_world_process, ev, data)
{PROCESS_BEGIN();printf("Hello, world\n");PROCESS_END();
}#define PROCESS_THREAD(name, ev, data) \
static PT_THREAD(process_thread_##name(struct pt *process_pt, \process_event_t ev, \process_data_t data))#define PT_THREAD(name_args) char name_args
最后展开为
static char process_thread_hello_world_process(struct pt *process_pt, process_event_t ev, process_data_t data)
{//略
}
03. 事件
非同步事件
非同步事件处理中,先将事件放到事件队列中,然后事件处理程序再把事件传递给接收这个事件的进程。
同步事件
同步事件处理中,事件立马就传递给了特定的进程,表现为立马执行ProcessB的执行实体函数。
Polling(推举)
推举某个进程,让这个进程尽可能快的执行。抢占式进程的唯一调用方式。
04. 进程调度函数
先处理所有poll的进程,再处理一个事件,最后返回剩余的事件数。
int
process_run(void)
{/* Process poll events. */if(poll_requested) {do_poll();}/* Process one event from the queue */do_event();return nevents + poll_requested;
}
源码文件
源码: c o n t i k i contiki contiki\core\sys\process.c
源码: c o n t i k i contiki contiki\core\sys\process.h
05. 程序实例
test.c
#include "contiki.h"PROCESS(example_process, "Example process");AUTOSTART_PROCESSES(&example_process);PROCESS_THREAD(example_process, ev, data){PROCESS_BEGIN();while(1) {PROCESS_WAIT_EVENT();printf("Got event number %d\n", ev);}PROCESS_END();}
06. process实现
process.h
/** 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"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) \
static PT_THREAD(process_thread_##name(struct pt *process_pt, \process_event_t ev, \process_data_t 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); \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) ""
#elseconst char *name;
#define PROCESS_NAME_STRING(process) (process)->name
#endifPT_THREAD((* thread)(struct pt *, process_event_t, process_data_t));struct pt pt;unsigned char state, needspoll;
};/*** \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);/*** 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);/*** \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:\codePROCESS_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(void);/*** 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_ *//** @} */
/** @} */
process.c
/** 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 process* @{*//*** \file* Implementation of the Contiki process kernel.* \author* Adam Dunkels <adam@sics.se>**/#include <stdio.h>#include "sys/process.h"
#include "sys/arg.h"/** Pointer to the currently running process structure.*/
struct process *process_list = NULL;
struct process *process_current = NULL;static process_event_t lastevent;/** Structure used for keeping the queue of active events.*/
struct event_data {process_event_t ev;process_data_t data;struct process *p;
};static process_num_events_t nevents, fevent;
static struct event_data events[PROCESS_CONF_NUMEVENTS];#if PROCESS_CONF_STATS
process_num_events_t process_maxevents;
#endifstatic volatile unsigned char poll_requested;#define PROCESS_STATE_NONE 0
#define PROCESS_STATE_RUNNING 1
#define PROCESS_STATE_CALLED 2static void call_process(struct process *p, process_event_t ev, process_data_t data);#define DEBUG 0
#if DEBUG
#include <stdio.h>
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PRINTF(...)
#endif/*---------------------------------------------------------------------------*/
process_event_t
process_alloc_event(void)
{return lastevent++;
}
/*---------------------------------------------------------------------------*/
void
process_start(struct process *p, process_data_t data)
{struct process *q;/* First make sure that we don't try to start a process that isalready running. */for(q = process_list; q != p && q != NULL; q = q->next);/* If we found the process on the process list, we bail out. */if(q == p) {return;}/* Put on the procs list.*/p->next = process_list;process_list = p;p->state = PROCESS_STATE_RUNNING;PT_INIT(&p->pt);PRINTF("process: starting '%s'\n", PROCESS_NAME_STRING(p));/* Post a synchronous initialization event to the process. */process_post_synch(p, PROCESS_EVENT_INIT, data);
}
/*---------------------------------------------------------------------------*/
static void
exit_process(struct process *p, struct process *fromprocess)
{register struct process *q;struct process *old_current = process_current;PRINTF("process: exit_process '%s'\n", PROCESS_NAME_STRING(p));/* Make sure the process is in the process list before we try toexit it. */for(q = process_list; q != p && q != NULL; q = q->next);if(q == NULL) {return;}if(process_is_running(p)) {/* Process was running */p->state = PROCESS_STATE_NONE;/** Post a synchronous event to all processes to inform them that* this process is about to exit. This will allow services to* deallocate state associated with this process.*/for(q = process_list; q != NULL; q = q->next) {if(p != q) {call_process(q, PROCESS_EVENT_EXITED, (process_data_t)p);}}if(p->thread != NULL && p != fromprocess) {/* Post the exit event to the process that is about to exit. */process_current = p;p->thread(&p->pt, PROCESS_EVENT_EXIT, NULL);}}if(p == process_list) {process_list = process_list->next;} else {for(q = process_list; q != NULL; q = q->next) {if(q->next == p) {q->next = p->next;break;}}}process_current = old_current;
}
/*---------------------------------------------------------------------------*/
static void
call_process(struct process *p, process_event_t ev, process_data_t data)
{int ret;#if DEBUGif(p->state == PROCESS_STATE_CALLED) {printf("process: process '%s' called again with event %d\n", PROCESS_NAME_STRING(p), ev);}
#endif /* DEBUG */if((p->state & PROCESS_STATE_RUNNING) &&p->thread != NULL) {PRINTF("process: calling process '%s' with event %d\n", PROCESS_NAME_STRING(p), ev);process_current = p;p->state = PROCESS_STATE_CALLED;ret = p->thread(&p->pt, ev, data);if(ret == PT_EXITED ||ret == PT_ENDED ||ev == PROCESS_EVENT_EXIT) {exit_process(p, p);} else {p->state = PROCESS_STATE_RUNNING;}}
}
/*---------------------------------------------------------------------------*/
void
process_exit(struct process *p)
{exit_process(p, PROCESS_CURRENT());
}
/*---------------------------------------------------------------------------*/
void
process_init(void)
{lastevent = PROCESS_EVENT_MAX;nevents = fevent = 0;
#if PROCESS_CONF_STATSprocess_maxevents = 0;
#endif /* PROCESS_CONF_STATS */process_current = process_list = NULL;
}
/*---------------------------------------------------------------------------*/
/** Call each process' poll handler.*/
/*---------------------------------------------------------------------------*/
static void
do_poll(void)
{struct process *p;poll_requested = 0;/* Call the processes that needs to be polled. */for(p = process_list; p != NULL; p = p->next) {if(p->needspoll) {p->state = PROCESS_STATE_RUNNING;p->needspoll = 0;call_process(p, PROCESS_EVENT_POLL, NULL);}}
}
/*---------------------------------------------------------------------------*/
/** Process the next event in the event queue and deliver it to* listening processes.*/
/*---------------------------------------------------------------------------*/
static void
do_event(void)
{process_event_t ev;process_data_t data;struct process *receiver;struct process *p;/** If there are any events in the queue, take the first one and walk* through the list of processes to see if the event should be* delivered to any of them. If so, we call the event handler* function for the process. We only process one event at a time and* call the poll handlers inbetween.*/if(nevents > 0) {/* There are events that we should deliver. */ev = events[fevent].ev;data = events[fevent].data;receiver = events[fevent].p;/* Since we have seen the new event, we move pointer upwardsand decrease the number of events. */fevent = (fevent + 1) % PROCESS_CONF_NUMEVENTS;--nevents;/* If this is a broadcast event, we deliver it to all events, inorder of their priority. */if(receiver == PROCESS_BROADCAST) {for(p = process_list; p != NULL; p = p->next) {/* If we have been requested to poll a process, we do this inbetween processing the broadcast event. */if(poll_requested) {do_poll();}call_process(p, ev, data);}} else {/* This is not a broadcast event, so we deliver it to thespecified process. *//* If the event was an INIT event, we should also update thestate of the process. */if(ev == PROCESS_EVENT_INIT) {receiver->state = PROCESS_STATE_RUNNING;}/* Make sure that the process actually is running. */call_process(receiver, ev, data);}}
}
/*---------------------------------------------------------------------------*/
int
process_run(void)
{/* Process poll events. */if(poll_requested) {do_poll();}/* Process one event from the queue */do_event();return nevents + poll_requested;
}
/*---------------------------------------------------------------------------*/
int
process_nevents(void)
{return nevents + poll_requested;
}
/*---------------------------------------------------------------------------*/
int
process_post(struct process *p, process_event_t ev, process_data_t data)
{process_num_events_t snum;if(PROCESS_CURRENT() == NULL) {PRINTF("process_post: NULL process posts event %d to process '%s', nevents %d\n",ev,PROCESS_NAME_STRING(p), nevents);} else {PRINTF("process_post: Process '%s' posts event %d to process '%s', nevents %d\n",PROCESS_NAME_STRING(PROCESS_CURRENT()), ev,p == PROCESS_BROADCAST? "<broadcast>": PROCESS_NAME_STRING(p), nevents);}if(nevents == PROCESS_CONF_NUMEVENTS) {
#if DEBUGif(p == PROCESS_BROADCAST) {printf("soft panic: event queue is full when broadcast event %d was posted from %s\n", ev, PROCESS_NAME_STRING(process_current));} else {printf("soft panic: event queue is full when event %d was posted to %s from %s\n", ev, PROCESS_NAME_STRING(p), PROCESS_NAME_STRING(process_current));}
#endif /* DEBUG */return PROCESS_ERR_FULL;}snum = (process_num_events_t)(fevent + nevents) % PROCESS_CONF_NUMEVENTS;events[snum].ev = ev;events[snum].data = data;events[snum].p = p;++nevents;#if PROCESS_CONF_STATSif(nevents > process_maxevents) {process_maxevents = nevents;}
#endif /* PROCESS_CONF_STATS */return PROCESS_ERR_OK;
}
/*---------------------------------------------------------------------------*/
void
process_post_synch(struct process *p, process_event_t ev, process_data_t data)
{struct process *caller = process_current;call_process(p, ev, data);process_current = caller;
}
/*---------------------------------------------------------------------------*/
void
process_poll(struct process *p)
{if(p != NULL) {if(p->state == PROCESS_STATE_RUNNING ||p->state == PROCESS_STATE_CALLED) {p->needspoll = 1;poll_requested = 1;}}
}
/*---------------------------------------------------------------------------*/
int
process_is_running(struct process *p)
{return p->state != PROCESS_STATE_NONE;
}
/*---------------------------------------------------------------------------*/
/** @} */
07. 附录
参考:Contiki 2.6: Contiki processes
参考:Processes · contiki-os/contiki Wiki · GitHub