diff --git a/lib/pbio/sys/arg.c b/lib/pbio/sys/arg.c new file mode 100644 index 000000000..090034380 --- /dev/null +++ b/lib/pbio/sys/arg.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2003, Adam Dunkels. + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 desktop OS + * + * + */ + +/** + * \file + * Argument buffer for passing arguments when starting processes + * \author Adam Dunkels + */ + +/** + * \addtogroup sys + * @{ + */ + +/** + * \defgroup arg Argument buffer + * @{ + * + * The argument buffer can be used when passing an argument from an + * exiting process to a process that has not been created yet. Since + * the exiting process will have exited when the new process is + * started, the argument cannot be passed in any of the processes' + * addres spaces. In such situations, the argument buffer can be used. + * + * The argument buffer is statically allocated in memory and is + * globally accessible to all processes. + * + * An argument buffer is allocated with the arg_alloc() function and + * deallocated with the arg_free() function. The arg_free() function + * is designed so that it can take any pointer, not just an argument + * buffer pointer. If the pointer to arg_free() is not an argument + * buffer, the function does nothing. + */ + +#include "contiki.h" +#include "sys/arg.h" + +/** + * \internal Structure used for holding an argument buffer. + */ +struct argbuf { + char buf[128]; + char used; +}; + +static struct argbuf bufs[1]; + +/*-----------------------------------------------------------------------------------*/ +/** + * \internal Initalizer, called by the dispatcher module. + */ +/*-----------------------------------------------------------------------------------*/ +void +arg_init(void) +{ + bufs[0].used = 0; +} +/*-----------------------------------------------------------------------------------*/ +/** + * Allocates an argument buffer. + * + * \param size The requested size of the buffer, in bytes. + * + * \return Pointer to allocated buffer, or NULL if no buffer could be + * allocated. + * + * \note It currently is not possible to allocate argument buffers of + * any other size than 128 bytes. + * + */ +/*-----------------------------------------------------------------------------------*/ +char * +arg_alloc(char size) +{ + if(bufs[0].used == 0) { + bufs[0].used = 1; + return bufs[0].buf; + } + return 0; +} +/*-----------------------------------------------------------------------------------*/ +/** + * Deallocates an argument buffer. + * + * This function deallocates the argument buffer pointed to by the + * parameter, but only if the buffer actually is an argument buffer + * and is allocated. It is perfectly safe to call this function with + * any pointer. + * + * \param arg A pointer. + */ +/*-----------------------------------------------------------------------------------*/ +void +arg_free(char *arg) +{ + if(arg == bufs[0].buf) { + bufs[0].used = 0; + } +} +/*-----------------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/lib/pbio/sys/arg.h b/lib/pbio/sys/arg.h new file mode 100644 index 000000000..6c2d0eb19 --- /dev/null +++ b/lib/pbio/sys/arg.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2003, Adam Dunkels. + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 desktop OS + * + * + */ +#ifndef ARG_H_ +#define ARG_H_ + +void arg_init(void); + +char *arg_alloc(char size); +void arg_free(char *arg); + +#endif /* ARG_H_ */ diff --git a/lib/pbio/sys/autostart.c b/lib/pbio/sys/autostart.c new file mode 100644 index 000000000..a0d8a77b4 --- /dev/null +++ b/lib/pbio/sys/autostart.c @@ -0,0 +1,72 @@ +/* + * 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. + * + */ + +/** + * \file + * Implementation of module for automatically starting and exiting a list of processes. + * \author + * Adam Dunkels + */ + +#include "sys/autostart.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*---------------------------------------------------------------------------*/ +void +autostart_start(struct process * const processes[]) +{ + int i; + + for(i = 0; processes[i] != NULL; ++i) { + process_start(processes[i], NULL); + PRINTF("autostart_start: starting process '%s'\n", processes[i]->name); + } +} +/*---------------------------------------------------------------------------*/ +void +autostart_exit(struct process * const processes[]) +{ + int i; + + for(i = 0; processes[i] != NULL; ++i) { + process_exit(processes[i]); + PRINTF("autostart_exit: stopping process '%s'\n", processes[i]->name); + } +} +/*---------------------------------------------------------------------------*/ diff --git a/lib/pbio/sys/autostart.h b/lib/pbio/sys/autostart.h new file mode 100644 index 000000000..a88dbd6b6 --- /dev/null +++ b/lib/pbio/sys/autostart.h @@ -0,0 +1,62 @@ +/* + * 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. + * + */ + +/** + * \file + * Header file for module for automatically starting and exiting a list of processes. + * \author + * Adam Dunkels + */ + +#ifndef AUTOSTART_H_ +#define AUTOSTART_H_ + +#include "sys/process.h" + +#if ! CC_NO_VA_ARGS +#if AUTOSTART_ENABLE +#define AUTOSTART_PROCESSES(...) \ +struct process * const autostart_processes[] = {__VA_ARGS__, NULL} +#else /* AUTOSTART_ENABLE */ +#define AUTOSTART_PROCESSES(...) \ +extern int _dummy +#endif /* AUTOSTART_ENABLE */ +#else +#error "C compiler must support __VA_ARGS__ macro" +#endif + +CLIF extern struct process * const autostart_processes[]; + +void autostart_start(struct process * const processes[]); +void autostart_exit(struct process * const processes[]); + +#endif /* AUTOSTART_H_ */ diff --git a/lib/pbio/sys/cc-gcc.h b/lib/pbio/sys/cc-gcc.h new file mode 100644 index 000000000..e96716327 --- /dev/null +++ b/lib/pbio/sys/cc-gcc.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, Scanimetrics - http://www.scanimetrics.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. + * 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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 + * COPYRIGHT HOLDER 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. + */ +/*---------------------------------------------------------------------------*/ +#ifndef _CC_GCC_H_ +#define _CC_GCC_H_ +#ifdef __GNUC__ + +#ifndef CC_CONF_INLINE +/* use __inline__ in case "inline" is not available for any reason */ +#define CC_CONF_INLINE __inline__ +#endif + +#define CC_CONF_ALIGN(n) __attribute__((__aligned__(n))) + +#endif /* __GNUC__ */ +#endif /* _CC_GCC_H_ */ diff --git a/lib/pbio/sys/cc.h b/lib/pbio/sys/cc.h new file mode 100644 index 000000000..55567a954 --- /dev/null +++ b/lib/pbio/sys/cc.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2003, Adam Dunkels. + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 desktop OS + * + * + */ + +/** + * \file + * Default definitions of C compiler quirk work-arounds. + * \author Adam Dunkels + * + * This file is used for making use of extra functionality of some C + * compilers used for Contiki, and defining work-arounds for various + * quirks and problems with some other C compilers. + */ + +#ifndef CC_H_ +#define CC_H_ + +#include "contiki-conf.h" +#include "sys/cc-gcc.h" + +/** + * Configure if the C compiler supports the "register" keyword for + * function arguments. + */ +#if CC_CONF_REGISTER_ARGS +#define CC_REGISTER_ARG register +#else /* CC_CONF_REGISTER_ARGS */ +#define CC_REGISTER_ARG +#endif /* CC_CONF_REGISTER_ARGS */ + +/** + * Configure if the C compiler supports the arguments for function + * pointers. + */ +#if CC_CONF_FUNCTION_POINTER_ARGS +#define CC_FUNCTION_POINTER_ARGS 1 +#else /* CC_CONF_FUNCTION_POINTER_ARGS */ +#define CC_FUNCTION_POINTER_ARGS 0 +#endif /* CC_CONF_FUNCTION_POINTER_ARGS */ + +/** + * Configure if the C compiler have problems with const function pointers + */ +#ifdef CC_CONF_CONST_FUNCTION_BUG +#define CC_CONST_FUNCTION +#else /* CC_CONF_CONST_FUNCTION_BUG */ +#define CC_CONST_FUNCTION const +#endif /* CC_CONF_CONST_FUNCTION_BUG */ + +/** + * Configure work-around for unsigned char bugs with sdcc. + */ +#if CC_CONF_UNSIGNED_CHAR_BUGS +#define CC_UNSIGNED_CHAR_BUGS 1 +#else /* CC_CONF_UNSIGNED_CHAR_BUGS */ +#define CC_UNSIGNED_CHAR_BUGS 0 +#endif /* CC_CONF_UNSIGNED_CHAR_BUGS */ + +/** + * Configure if C compiler supports double hash marks in C macros. + */ +#if CC_CONF_DOUBLE_HASH +#define CC_DOUBLE_HASH 1 +#else /* CC_CONF_DOUBLE_HASH */ +#define CC_DOUBLE_HASH 0 +#endif /* CC_CONF_DOUBLE_HASH */ + +#ifdef CC_CONF_INLINE +#define CC_INLINE CC_CONF_INLINE +#else /* CC_CONF_INLINE */ +#define CC_INLINE +#endif /* CC_CONF_INLINE */ + +#ifdef CC_CONF_ALIGN +#define CC_ALIGN(n) CC_CONF_ALIGN(n) +#endif /* CC_CONF_INLINE */ + +/** + * Configure if the C compiler supports the assignment of struct value. + */ +#ifdef CC_CONF_ASSIGN_AGGREGATE +#define CC_ASSIGN_AGGREGATE(dest, src) CC_CONF_ASSIGN_AGGREGATE(dest, src) +#else /* CC_CONF_ASSIGN_AGGREGATE */ +#define CC_ASSIGN_AGGREGATE(dest, src) *dest = *src +#endif /* CC_CONF_ASSIGN_AGGREGATE */ + +#if CC_CONF_NO_VA_ARGS +#define CC_NO_VA_ARGS CC_CONF_VA_ARGS +#endif + +/** \def CC_ACCESS_NOW(x) + * This macro ensures that the access to a non-volatile variable can + * not be reordered or optimized by the compiler. + * See also https://lwn.net/Articles/508991/ - In Linux the macro is + * called ACCESS_ONCE + * The type must be passed, because the typeof-operator is a gcc + * extension + */ + +#define CC_ACCESS_NOW(type, variable) (*(volatile type *)&(variable)) + +#ifndef NULL +#define NULL 0 +#endif /* NULL */ + +#ifndef MAX +#define MAX(n, m) (((n) < (m)) ? (m) : (n)) +#endif + +#ifndef MIN +#define MIN(n, m) (((n) < (m)) ? (n) : (m)) +#endif + +#ifndef ABS +#define ABS(n) (((n) < 0) ? -(n) : (n)) +#endif + + +#define CC_CONCAT2(s1, s2) s1##s2 +/** + * A C preprocessing macro for concatenating two preprocessor tokens. + * + * We need use two macros (CC_CONCAT and CC_CONCAT2) in order to allow + * concatenation of two \#defined macros. + */ +#define CC_CONCAT(s1, s2) CC_CONCAT2(s1, s2) +#define CC_CONCAT_EXT_2(s1, s2) CC_CONCAT2(s1, s2) + +/** + * A C preprocessing macro for concatenating three preprocessor tokens. + */ +#define CC_CONCAT3(s1, s2, s3) s1##s2##s3 +#define CC_CONCAT_EXT_3(s1, s2, s3) CC_CONCAT3(s1, s2, s3) + +#endif /* CC_H_ */ diff --git a/lib/pbio/sys/clock.h b/lib/pbio/sys/clock.h new file mode 100644 index 000000000..4cbfdb223 --- /dev/null +++ b/lib/pbio/sys/clock.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2004, 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. + * + * Author: Adam Dunkels + * + */ + +/** \addtogroup sys + * @{ + */ + +/** + * \defgroup clock Clock library + * + * The clock library is the interface between Contiki and the platform + * specific clock functionality. The clock library defines a macro, + * CLOCK_SECOND, to convert seconds into the tick resolution of the platform. + * Typically this is 1-10 milliseconds, e.g. 4*CLOCK_SECOND could be 512. + * A 16 bit counter would thus overflow every 1-10 minutes. + * Platforms use the tick interrupt to maintain a long term count + * of seconds since startup. + * + * Platforms may also implement rtimers for greater time resolution + * and for real-time interrupts, These use a corresponding RTIMER_SECOND. + * + * \note These timers do not necessarily have a common divisor or are phase locked. + * One may be crystal controlled and the other may not. Low power operation + * or sleep will often use one for wake and disable the other, then give + * it a tick correction after wakeup. + * + * \note The clock library need in many cases not be used + * directly. Rather, the \ref timer "timer library", \ref etimer + * "event timers", or \ref rtimer "rtimer library" should be used. + * + * \sa \ref timer "Timer library" + * \sa \ref etimer "Event timers" + * \sa \ref rtimer "Realtime library" + * + * @{ + */ + +#ifndef CLOCK_H_ +#define CLOCK_H_ + +#include "contiki-conf.h" + +/** + * A second, measured in system clock time. + * + * \hideinitializer + */ +#ifdef CLOCK_CONF_SECOND +#define CLOCK_SECOND CLOCK_CONF_SECOND +#else +#define CLOCK_SECOND (clock_time_t)32 +#endif + +/** + * Initialize the clock library. + * + * This function initializes the clock library and should be called + * from the main() function of the system. + * + */ +void clock_init(void); + +/** + * Get the current clock time. + * + * This function returns the current system clock time. + * + * \return The current clock time, measured in system ticks. + */ +CCIF clock_time_t clock_time(void); + +/** + * Get the current value of the platform seconds. + * + * This could be the number of seconds since startup, or + * since a standard epoch. + * + * \return The value. + */ +CCIF unsigned long clock_seconds(void); + +/** + * Set the value of the platform seconds. + * \param sec The value to set. + * + */ +void clock_set_seconds(unsigned long sec); + +/** + * Wait for a given number of ticks. + * \param t How many ticks. + * + */ +void clock_wait(clock_time_t t); + +/** + * Delay a given number of microseconds. + * \param dt How many microseconds to delay. + * + * \note Interrupts could increase the delay by a variable amount. + */ +void clock_delay_usec(uint16_t dt); + +/** + * Deprecated platform-specific routines. + * + */ +int clock_fine_max(void); +unsigned short clock_fine(void); +void clock_delay(unsigned int delay); + +#endif /* CLOCK_H_ */ + +/** @} */ +/** @} */ diff --git a/lib/pbio/sys/compower.c b/lib/pbio/sys/compower.c new file mode 100644 index 000000000..02a0f3c4c --- /dev/null +++ b/lib/pbio/sys/compower.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2009, 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. + * + */ + +/** + * \file + * Communication power accounting module + * \author + * Adam Dunkels + */ + +/** + * \addtogroup compower + * @{ + */ + +#include "contiki-conf.h" +#include "sys/energest.h" +#include "sys/compower.h" +#include "net/packetbuf.h" + +struct compower_activity compower_idle_activity; + +/*---------------------------------------------------------------------------*/ +void +compower_init(void) +{ + compower_clear(&compower_idle_activity); +} +/*---------------------------------------------------------------------------*/ +void +compower_accumulate(struct compower_activity *e) +{ + static uint32_t last_listen, last_transmit; + uint32_t listen, transmit; + + energest_flush(); + + listen = energest_type_time(ENERGEST_TYPE_LISTEN); + e->listen += listen - last_listen; + last_listen = listen; + + transmit = energest_type_time(ENERGEST_TYPE_TRANSMIT); + e->transmit += transmit - last_transmit; + last_transmit = transmit; +} +/*---------------------------------------------------------------------------*/ +void +compower_clear(struct compower_activity *e) +{ + e->listen = e->transmit = 0; +} +/*---------------------------------------------------------------------------*/ +void +compower_attrconv(struct compower_activity *e) +{ + packetbuf_set_attr(PACKETBUF_ATTR_LISTEN_TIME, + packetbuf_attr(PACKETBUF_ATTR_LISTEN_TIME) + e->listen); + packetbuf_set_attr(PACKETBUF_ATTR_TRANSMIT_TIME, + packetbuf_attr(PACKETBUF_ATTR_TRANSMIT_TIME) + e->transmit); +} +/*---------------------------------------------------------------------------*/ +void +compower_accumulate_attrs(struct compower_activity *e) +{ + e->listen += packetbuf_attr(PACKETBUF_ATTR_LISTEN_TIME); + e->transmit += packetbuf_attr(PACKETBUF_ATTR_TRANSMIT_TIME); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/lib/pbio/sys/compower.h b/lib/pbio/sys/compower.h new file mode 100644 index 000000000..03d984193 --- /dev/null +++ b/lib/pbio/sys/compower.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2009, 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. + * + */ + +/** + * \file + * Header file for the communication power accounting module + * \author + * Adam Dunkels + */ + +/** \addtogroup sys + * @{ */ + +/** + * \defgroup compower Communication power accounting + * @{ + * + * The compower module accumulates power consumption information and + * attributes it to communication activities. Examples of + * communication activities are packet transmission, packet reception, + * and idle listening. + * + */ + +#ifndef COMPOWER_H_ +#define COMPOWER_H_ + +/** + * \brief An activity record that contains power consumption information for a specific communication activity. + * + * This is a structure that holds power information about + * a communication activity. It is an opaque structure + * with no user-visible elements. + */ +struct compower_activity { + uint32_t listen, transmit; +}; + +/** + * \brief The default idle communication activity. + * + * This is the idle communication activity, to which all + * energy that is not possible to attribute to individual + * packets, is attributed. Examples include idle listening + * for incoming packets and MAC-level beacon + * transmissions. + */ +extern struct compower_activity compower_idle_activity; + +/** + * \brief Initialize the communication power accounting module. + * + * This function initializes the communication power + * accounting module. The function is called by the system + * during boot-up. + */ +void compower_init(void); + +/** + * \brief Accumulate power contumption for a communication activity + * \param a A pointer to an activity structure. + * + * This function accumulates power consumption information + * for a communication activity. The function typically is + * called by a power-saving MAC protocol when the radio is + * switched off, or when a packet is received or + * transmitted. + * + */ +void compower_accumulate(struct compower_activity *a); + +/** + * \brief Clear power consumption information for a communication activity + * \param a A pointer to an activity structure. + * + * This function clears any power contumption information + * that has previously been accumulated in an activity + * structure. + * + */ +void compower_clear(struct compower_activity *a); + +/** + * \brief Convert power contumption information to packet attributes + * \param a A pointer to an activity structure. + * + * This function converts accumulated power consumption + * information for a communication activity to packet + * attributes (see \ref packetbufattr "packet attributes"). + */ +void compower_attrconv(struct compower_activity *a); + +/** + * \brief Accumulate power contumption for a communication activity based on energy data in packet attributes + * \param a A pointer to an activity structure. + * + * This function accumulates power consumption information + * for a communication activity from packet attributes + * (see \ref packetbufattr "packet attributes"). + */ +void compower_accumulate_attrs(struct compower_activity *a); + +#endif /* COMPOWER_H_ */ + +/** @} */ +/** @} */ diff --git a/lib/pbio/sys/ctimer.c b/lib/pbio/sys/ctimer.c new file mode 100644 index 000000000..66698a8e6 --- /dev/null +++ b/lib/pbio/sys/ctimer.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2006, 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. + * + */ + +/** + * \file + * Callback timer implementation + * \author + * Adam Dunkels + */ + +/** + * \addtogroup ctimer + * @{ + */ + +#include "sys/ctimer.h" +#include "contiki.h" +#include "lib/list.h" + +LIST(ctimer_list); + +static char initialized; + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*---------------------------------------------------------------------------*/ +PROCESS(ctimer_process, "Ctimer process"); +PROCESS_THREAD(ctimer_process, ev, data) +{ + struct ctimer *c; + PROCESS_BEGIN(); + + for(c = list_head(ctimer_list); c != NULL; c = c->next) { + etimer_set(&c->etimer, c->etimer.timer.interval); + } + initialized = 1; + + while(1) { + PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_TIMER); + for(c = list_head(ctimer_list); c != NULL; c = c->next) { + if(&c->etimer == data) { + list_remove(ctimer_list, c); + PROCESS_CONTEXT_BEGIN(c->p); + if(c->f != NULL) { + c->f(c->ptr); + } + PROCESS_CONTEXT_END(c->p); + break; + } + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +void +ctimer_init(void) +{ + initialized = 0; + list_init(ctimer_list); + process_start(&ctimer_process, NULL); +} +/*---------------------------------------------------------------------------*/ +void +ctimer_set(struct ctimer *c, clock_time_t t, + void (*f)(void *), void *ptr) +{ + ctimer_set_with_process(c, t, f, ptr, PROCESS_CURRENT()); +} +/*---------------------------------------------------------------------------*/ +void +ctimer_set_with_process(struct ctimer *c, clock_time_t t, + void (*f)(void *), void *ptr, struct process *p) +{ + PRINTF("ctimer_set %p %u\n", c, (unsigned)t); + c->p = p; + c->f = f; + c->ptr = ptr; + if(initialized) { + PROCESS_CONTEXT_BEGIN(&ctimer_process); + etimer_set(&c->etimer, t); + PROCESS_CONTEXT_END(&ctimer_process); + } else { + c->etimer.timer.interval = t; + } + + list_add(ctimer_list, c); +} +/*---------------------------------------------------------------------------*/ +void +ctimer_reset(struct ctimer *c) +{ + if(initialized) { + PROCESS_CONTEXT_BEGIN(&ctimer_process); + etimer_reset(&c->etimer); + PROCESS_CONTEXT_END(&ctimer_process); + } + + list_add(ctimer_list, c); +} +/*---------------------------------------------------------------------------*/ +void +ctimer_restart(struct ctimer *c) +{ + if(initialized) { + PROCESS_CONTEXT_BEGIN(&ctimer_process); + etimer_restart(&c->etimer); + PROCESS_CONTEXT_END(&ctimer_process); + } + + list_add(ctimer_list, c); +} +/*---------------------------------------------------------------------------*/ +void +ctimer_stop(struct ctimer *c) +{ + if(initialized) { + etimer_stop(&c->etimer); + } else { + c->etimer.next = NULL; + c->etimer.p = PROCESS_NONE; + } + list_remove(ctimer_list, c); +} +/*---------------------------------------------------------------------------*/ +int +ctimer_expired(struct ctimer *c) +{ + struct ctimer *t; + if(initialized) { + return etimer_expired(&c->etimer); + } + for(t = list_head(ctimer_list); t != NULL; t = t->next) { + if(t == c) { + return 0; + } + } + return 1; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/lib/pbio/sys/ctimer.h b/lib/pbio/sys/ctimer.h new file mode 100644 index 000000000..dabf43d8a --- /dev/null +++ b/lib/pbio/sys/ctimer.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2006, 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. + * + */ + +/** + * \file + * Header file for the callback timer + * \author + * Adam Dunkels + */ + +/** + * \addtogroup sys + * @{ + */ + +/** + * \defgroup ctimer Callback timer + * @{ + * + * The ctimer module provides a timer mechanism that calls a specified + * C function when a ctimer expires. + * + */ + +#ifndef CTIMER_H_ +#define CTIMER_H_ + +#include "sys/etimer.h" + +struct ctimer { + struct ctimer *next; + struct etimer etimer; + struct process *p; + void (*f)(void *); + void *ptr; +}; + +/** + * \brief Reset a callback timer with the same interval as was + * previously set. + * \param c A pointer to the callback timer. + * + * This function resets the callback timer with the same + * interval that was given to the callback timer with the + * ctimer_set() function. The start point of the interval + * is the exact time that the callback timer last + * expired. Therefore, this function will cause the timer + * to be stable over time, unlike the ctimer_restart() + * function. + * + * \sa ctimer_restart() + */ +void ctimer_reset(struct ctimer *c); + +/** + * \brief Restart a callback timer from the current point in time + * \param c A pointer to the callback timer. + * + * This function restarts the callback timer with the same + * interval that was given to the ctimer_set() + * function. The callback timer will start at the current + * time. + * + * \note A periodic timer will drift if this function is + * used to reset it. For periodic timers, use the + * ctimer_reset() function instead. + * + * \sa ctimer_reset() + */ +void ctimer_restart(struct ctimer *c); + +/** + * \brief Set a callback timer. + * \param c A pointer to the callback timer. + * \param t The interval before the timer expires. + * \param f A function to be called when the timer expires. + * \param ptr An opaque pointer that will be supplied as an argument to the callback function. + * + * This function is used to set a callback timer for a time + * sometime in the future. When the callback timer expires, + * the callback function f will be called with ptr as argument. + * + * This essentially does ctimer_set_process(c, t, f, ptr, PROCESS_CURRENT()); + * + */ +void ctimer_set(struct ctimer *c, clock_time_t t, + void (*f)(void *), void *ptr); + +/** + * \brief Set a callback timer. + * \param c A pointer to the callback timer. + * \param t The interval before the timer expires. + * \param f A function to be called when the timer expires. + * \param ptr An opaque pointer that will be supplied as an argument to the callback function. + * \param p A pointer to the process the timer belongs to + * + * This function is used to set a callback timer for a time + * sometime in the future. When the callback timer expires, + * the callback function f will be called with ptr as argument. + * + */ +void ctimer_set_with_process(struct ctimer *c, clock_time_t t, + void (*f)(void *), void *ptr, struct process *p); + +/** + * \brief Stop a pending callback timer. + * \param c A pointer to the pending callback timer. + * + * This function stops a callback timer that has previously + * been set with ctimer_set(), ctimer_reset(), or ctimer_restart(). + * After this function has been called, the callback timer will be + * expired and will not call the callback function. + * + */ +void ctimer_stop(struct ctimer *c); + +/** + * \brief Check if a callback timer has expired. + * \param c A pointer to the callback timer + * \return Non-zero if the timer has expired, zero otherwise. + * + * This function tests if a callback timer has expired and + * returns true or false depending on its status. + */ +int ctimer_expired(struct ctimer *c); + +/** + * \brief Initialize the callback timer library. + * + * This function initializes the callback timer library and + * should be called from the system boot up code. + */ +void ctimer_init(void); + +#endif /* CTIMER_H_ */ +/** @} */ +/** @} */ diff --git a/lib/pbio/sys/dsc.h b/lib/pbio/sys/dsc.h new file mode 100644 index 000000000..b8b70433e --- /dev/null +++ b/lib/pbio/sys/dsc.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2003, Adam Dunkels. + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 desktop environment + * + * + */ + +/** + * \file + * Declaration of the DSC program description structure. + * \author Adam Dunkels + * + */ + +/** + * \addtogroup loader + * @{ + */ + +/** + * \page dsc The program description structure + * + * The Contiki DSC structure is used for describing programs. It + * includes a string describing the program, the name of the program + * file on disk (or a pointer to the programs initialization function + * for systems without disk support), a bitmap icon and a text version + * of the same icon. + * + * The DSC is saved into a file which can be loaded by programs such + * as the "Directory" application which reads all DSC files on disk + * and presents the icons and descriptions in a window. + * + */ + +#ifndef DSC_H_ +#define DSC_H_ + +#include "ctk/ctk.h" + +/** + * The DSC program description structure. + * + * The DSC structure is used for describing a Contiki program. It + * includes a short textual description of the program, either the + * name of the program on disk, or a pointer to the init() function, + * and an icon for the program. + */ +struct dsc { + char *description; /**< A text string containing a one-line + description of the program */ + +#if WITH_LOADER_ARCH + char *prgname; /**< The name of the program on disk. */ +#else /* WITH_LOADER_ARCH */ + struct process *process; /**< A pointer to the program's process. */ +#endif /* WITH_LOADER_ARCH */ + +#if CTK_CONF_ICONS + struct ctk_icon *icon; /**< A pointer to the ctk_icon structure for + the DSC. */ +#endif /* CTK_CONF_ICONS */ + +#if WITH_LOADER_ARCH + void *loadaddr; /**< The loading address of the DSC. Used by + the LOADER_UNLOAD() function when + deallocating the memory allocated for the + DSC when loading it. */ +#endif /* WITH_LOADER_ARCH */ +}; + +/** + * Instantiating macro for the DSC structure. + * + * \param dscname The name of the C variable which is to contain the + * DSC. + * + * \param description A one-line text describing the program. + * + * \param prgname The name of the program on disk. + * + * \param process A pointer to the initialization function of the + * program. + * + * \param icon A pointer to the CTK icon. + */ +#if WITH_LOADER_ARCH +#if CTK_CONF_ICONS +#define DSC(dscname, description, prgname, process, icon) \ + CLIF const struct dsc dscname = {description, prgname, icon} +#else /* CTK_CONF_ICONS */ +#define DSC(dscname, description, prgname, process, icon) \ + CLIF const struct dsc dscname = {description, prgname} +#endif /* CTK_CONF_ICONS */ +#else /* WITH_LOADER_ARCH */ +#if CTK_CONF_ICONS +#define DSC(dscname, description, prgname, process, icon) \ + PROCESS_NAME(process); \ + const struct dsc dscname = {description, &process, icon} +#else /* CTK_CONF_ICONS */ +#define DSC(dscname, description, prgname, process, icon) \ + PROCESS_NAME(process); \ + const struct dsc dscname = {description, &process} +#endif /* CTK_CONF_ICONS */ +#endif /* WITH_LOADER_ARCH */ + +#define DSC_HEADER(name) extern struct dsc name + +#ifndef NULL +#define NULL 0 +#endif /* NULL */ + +/** @} */ + +#endif /*DSC_H__ */ diff --git a/lib/pbio/sys/energest.c b/lib/pbio/sys/energest.c new file mode 100644 index 000000000..5b0f6cb86 --- /dev/null +++ b/lib/pbio/sys/energest.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2007, 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. + * + */ + +/** + * \file + * Implementation of the energy estimation module + * \author + * Adam Dunkels + */ + +#include "sys/energest.h" +#include "contiki-conf.h" + +#if ENERGEST_CONF_ON + +int energest_total_count; +energest_t energest_total_time[ENERGEST_TYPE_MAX]; +rtimer_clock_t energest_current_time[ENERGEST_TYPE_MAX]; +#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS +energest_t energest_leveldevice_current_leveltime[ENERGEST_CONF_LEVELDEVICE_LEVELS]; +#endif +unsigned char energest_current_mode[ENERGEST_TYPE_MAX]; + +/*---------------------------------------------------------------------------*/ +void +energest_init(void) +{ + int i; + for(i = 0; i < ENERGEST_TYPE_MAX; ++i) { + energest_total_time[i].current = energest_current_time[i] = 0; + energest_current_mode[i] = 0; + } +#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS + for(i = 0; i < ENERGEST_CONF_LEVELDEVICE_LEVELS; ++i) { + energest_leveldevice_current_leveltime[i].current = 0; + } +#endif +} +/*---------------------------------------------------------------------------*/ +unsigned long +energest_type_time(int type) +{ + /* Note: does not support ENERGEST_CONF_LEVELDEVICE_LEVELS! */ +#ifndef ENERGEST_CONF_LEVELDEVICE_LEVELS + if(energest_current_mode[type]) { + rtimer_clock_t now = RTIMER_NOW(); + energest_total_time[type].current += (rtimer_clock_t) + (now - energest_current_time[type]); + energest_current_time[type] = now; + } +#endif /* ENERGEST_CONF_LEVELDEVICE_LEVELS */ + return energest_total_time[type].current; +} +/*---------------------------------------------------------------------------*/ +unsigned long +energest_leveldevice_leveltime(int powerlevel) +{ +#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS + return energest_leveldevice_current_leveltime[powerlevel].current; +#else + return 0; +#endif +} +/*---------------------------------------------------------------------------*/ +void +energest_type_set(int type, unsigned long val) +{ + energest_total_time[type].current = val; +} +/*---------------------------------------------------------------------------*/ +/* Note: does not support ENERGEST_CONF_LEVELDEVICE_LEVELS! */ +void +energest_flush(void) +{ + rtimer_clock_t now; + int i; + for(i = 0; i < ENERGEST_TYPE_MAX; i++) { + if(energest_current_mode[i]) { + now = RTIMER_NOW(); + energest_total_time[i].current += (rtimer_clock_t) + (now - energest_current_time[i]); + energest_current_time[i] = now; + } + } +} +/*---------------------------------------------------------------------------*/ +#else /* ENERGEST_CONF_ON */ +void energest_type_set(int type, unsigned long val) {} +void energest_init(void) {} +unsigned long energest_type_time(int type) { return 0; } +void energest_flush(void) {} +#endif /* ENERGEST_CONF_ON */ diff --git a/lib/pbio/sys/energest.h b/lib/pbio/sys/energest.h new file mode 100644 index 000000000..a8f445b65 --- /dev/null +++ b/lib/pbio/sys/energest.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2007, 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. + * + */ + +/** + * \file + * Header file for the energy estimation mechanism + * \author + * Adam Dunkels + */ + +#ifndef ENERGEST_H_ +#define ENERGEST_H_ + +#include "sys/rtimer.h" + +typedef struct { + /* unsigned long cumulative[2];*/ + unsigned long current; +} energest_t; + +enum energest_type { + ENERGEST_TYPE_CPU, + ENERGEST_TYPE_LPM, + ENERGEST_TYPE_IRQ, + ENERGEST_TYPE_LED_GREEN, + ENERGEST_TYPE_LED_YELLOW, + ENERGEST_TYPE_LED_RED, + ENERGEST_TYPE_TRANSMIT, + ENERGEST_TYPE_LISTEN, + + ENERGEST_TYPE_FLASH_READ, + ENERGEST_TYPE_FLASH_WRITE, + + ENERGEST_TYPE_SENSORS, + + ENERGEST_TYPE_SERIAL, + + ENERGEST_TYPE_MAX +}; + +void energest_init(void); +unsigned long energest_type_time(int type); +#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS +unsigned long energest_leveldevice_leveltime(int powerlevel); +#endif +void energest_type_set(int type, unsigned long value); +void energest_flush(void); + +#if ENERGEST_CONF_ON +/*extern int energest_total_count;*/ +extern energest_t energest_total_time[ENERGEST_TYPE_MAX]; +extern rtimer_clock_t energest_current_time[ENERGEST_TYPE_MAX]; +extern unsigned char energest_current_mode[ENERGEST_TYPE_MAX]; + +#ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS +extern energest_t energest_leveldevice_current_leveltime[ENERGEST_CONF_LEVELDEVICE_LEVELS]; +#endif + +#define ENERGEST_ON(type) do { \ + /*++energest_total_count;*/ \ + energest_current_time[type] = RTIMER_NOW(); \ + energest_current_mode[type] = 1; \ + } while(0) +#ifdef __AVR__ +/* Handle 16 bit rtimer wraparound */ +#define ENERGEST_OFF(type) if(energest_current_mode[type] != 0) do { \ + if (RTIMER_NOW() < energest_current_time[type]) energest_total_time[type].current += RTIMER_ARCH_SECOND; \ + energest_total_time[type].current += (rtimer_clock_t)(RTIMER_NOW() - \ + energest_current_time[type]); \ + energest_current_mode[type] = 0; \ + } while(0) + +#define ENERGEST_OFF_LEVEL(type,level) do { \ + if (RTIMER_NOW() < energest_current_time[type]) energest_total_time[type].current += RTIMER_ARCH_SECOND; \ + energest_leveldevice_current_leveltime[level].current += (rtimer_clock_t)(RTIMER_NOW() - \ + energest_current_time[type]); \ + energest_current_mode[type] = 0; \ + } while(0) + +#define ENERGEST_SWITCH(type_off, type_on) do { \ + rtimer_clock_t energest_local_variable_now = RTIMER_NOW(); \ + if(energest_current_mode[type_off] != 0) { \ + if (energest_local_variable_now < energest_current_time[type_off]) { \ + energest_total_time[type_off].current += RTIMER_ARCH_SECOND; \ + } \ + energest_total_time[type_off].current += (rtimer_clock_t)(energest_local_variable_now - \ + energest_current_time[type_off]); \ + energest_current_mode[type_off] = 0; \ + } \ + energest_current_time[type_on] = energest_local_variable_now; \ + energest_current_mode[type_on] = 1; \ + } while(0) + +#else +#define ENERGEST_OFF(type) if(energest_current_mode[type] != 0) do { \ + energest_total_time[type].current += (rtimer_clock_t)(RTIMER_NOW() - \ + energest_current_time[type]); \ + energest_current_mode[type] = 0; \ + } while(0) + +#define ENERGEST_OFF_LEVEL(type,level) do { \ + energest_leveldevice_current_leveltime[level].current += (rtimer_clock_t)(RTIMER_NOW() - \ + energest_current_time[type]); \ + energest_current_mode[type] = 0; \ + } while(0) + +#define ENERGEST_SWITCH(type_off, type_on) do { \ + rtimer_clock_t energest_local_variable_now = RTIMER_NOW(); \ + if(energest_current_mode[type_off] != 0) { \ + energest_total_time[type_off].current += (rtimer_clock_t)(energest_local_variable_now - \ + energest_current_time[type_off]); \ + energest_current_mode[type_off] = 0; \ + } \ + energest_current_time[type_on] = energest_local_variable_now; \ + energest_current_mode[type_on] = 1; \ + } while(0) +#endif + +#else /* ENERGEST_CONF_ON */ +#define ENERGEST_ON(type) do { } while(0) +#define ENERGEST_OFF(type) do { } while(0) +#define ENERGEST_OFF_LEVEL(type,level) do { } while(0) +#define ENERGEST_SWITCH(type_off, type_on) do { } while(0) +#endif /* ENERGEST_CONF_ON */ + +#endif /* ENERGEST_H_ */ diff --git a/lib/pbio/sys/etimer.c b/lib/pbio/sys/etimer.c new file mode 100644 index 000000000..17ac74285 --- /dev/null +++ b/lib/pbio/sys/etimer.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2004, 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. + * + * Author: Adam Dunkels + * + */ + +/** + * \addtogroup etimer + * @{ + */ + +/** + * \file + * Event timer library implementation. + * \author + * Adam Dunkels + */ + +#include "contiki-conf.h" + +#include "sys/etimer.h" +#include "sys/process.h" + +static struct etimer *timerlist; +static clock_time_t next_expiration; + +PROCESS(etimer_process, "Event timer"); +/*---------------------------------------------------------------------------*/ +static void +update_time(void) +{ + clock_time_t tdist; + clock_time_t now; + struct etimer *t; + + if (timerlist == NULL) { + next_expiration = 0; + } else { + now = clock_time(); + t = timerlist; + /* Must calculate distance to next time into account due to wraps */ + tdist = t->timer.start + t->timer.interval - now; + for(t = t->next; t != NULL; t = t->next) { + if(t->timer.start + t->timer.interval - now < tdist) { + tdist = t->timer.start + t->timer.interval - now; + } + } + next_expiration = now + tdist; + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(etimer_process, ev, data) +{ + struct etimer *t, *u; + + PROCESS_BEGIN(); + + timerlist = NULL; + + while(1) { + PROCESS_YIELD(); + + if(ev == PROCESS_EVENT_EXITED) { + struct process *p = data; + + while(timerlist != NULL && timerlist->p == p) { + timerlist = timerlist->next; + } + + if(timerlist != NULL) { + t = timerlist; + while(t->next != NULL) { + if(t->next->p == p) { + t->next = t->next->next; + } else + t = t->next; + } + } + continue; + } else if(ev != PROCESS_EVENT_POLL) { + continue; + } + + again: + + u = NULL; + + for(t = timerlist; t != NULL; t = t->next) { + if(timer_expired(&t->timer)) { + if(process_post(t->p, PROCESS_EVENT_TIMER, t) == PROCESS_ERR_OK) { + + /* Reset the process ID of the event timer, to signal that the + etimer has expired. This is later checked in the + etimer_expired() function. */ + t->p = PROCESS_NONE; + if(u != NULL) { + u->next = t->next; + } else { + timerlist = t->next; + } + t->next = NULL; + update_time(); + goto again; + } else { + etimer_request_poll(); + } + } + u = t; + } + + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +void +etimer_request_poll(void) +{ + process_poll(&etimer_process); +} +/*---------------------------------------------------------------------------*/ +static void +add_timer(struct etimer *timer) +{ + struct etimer *t; + + etimer_request_poll(); + + if(timer->p != PROCESS_NONE) { + for(t = timerlist; t != NULL; t = t->next) { + if(t == timer) { + /* Timer already on list, bail out. */ + timer->p = PROCESS_CURRENT(); + update_time(); + return; + } + } + } + + /* Timer not on list. */ + timer->p = PROCESS_CURRENT(); + timer->next = timerlist; + timerlist = timer; + + update_time(); +} +/*---------------------------------------------------------------------------*/ +void +etimer_set(struct etimer *et, clock_time_t interval) +{ + timer_set(&et->timer, interval); + add_timer(et); +} +/*---------------------------------------------------------------------------*/ +void +etimer_reset_with_new_interval(struct etimer *et, clock_time_t interval) +{ + timer_reset(&et->timer); + et->timer.interval = interval; + add_timer(et); +} +/*---------------------------------------------------------------------------*/ +void +etimer_reset(struct etimer *et) +{ + timer_reset(&et->timer); + add_timer(et); +} +/*---------------------------------------------------------------------------*/ +void +etimer_restart(struct etimer *et) +{ + timer_restart(&et->timer); + add_timer(et); +} +/*---------------------------------------------------------------------------*/ +void +etimer_adjust(struct etimer *et, int timediff) +{ + et->timer.start += timediff; + update_time(); +} +/*---------------------------------------------------------------------------*/ +int +etimer_expired(struct etimer *et) +{ + return et->p == PROCESS_NONE; +} +/*---------------------------------------------------------------------------*/ +clock_time_t +etimer_expiration_time(struct etimer *et) +{ + return et->timer.start + et->timer.interval; +} +/*---------------------------------------------------------------------------*/ +clock_time_t +etimer_start_time(struct etimer *et) +{ + return et->timer.start; +} +/*---------------------------------------------------------------------------*/ +int +etimer_pending(void) +{ + return timerlist != NULL; +} +/*---------------------------------------------------------------------------*/ +clock_time_t +etimer_next_expiration_time(void) +{ + return etimer_pending() ? next_expiration : 0; +} +/*---------------------------------------------------------------------------*/ +void +etimer_stop(struct etimer *et) +{ + struct etimer *t; + + /* First check if et is the first event timer on the list. */ + if(et == timerlist) { + timerlist = timerlist->next; + update_time(); + } else { + /* Else walk through the list and try to find the item before the + et timer. */ + for(t = timerlist; t != NULL && t->next != et; t = t->next); + + if(t != NULL) { + /* We've found the item before the event timer that we are about + to remove. We point the items next pointer to the event after + the removed item. */ + t->next = et->next; + + update_time(); + } + } + + /* Remove the next pointer from the item to be removed. */ + et->next = NULL; + /* Set the timer as expired */ + et->p = PROCESS_NONE; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/lib/pbio/sys/etimer.h b/lib/pbio/sys/etimer.h new file mode 100644 index 000000000..ebbcfc7fd --- /dev/null +++ b/lib/pbio/sys/etimer.h @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2004, 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. + * + * Author: Adam Dunkels + * + */ + +/** + * \file + * Event timer header file. + * \author + * Adam Dunkels + */ + +/** \addtogroup sys + * @{ */ + +/** + * \defgroup etimer Event timers + * + * Event timers provides a way to generate timed events. An event + * timer will post an event to the process that set the timer when the + * event timer expires. + * + * An event timer is declared as a \c struct \c etimer and all access + * to the event timer is made by a pointer to the declared event + * timer. + * + * \sa \ref timer "Simple timer library" + * \sa \ref clock "Clock library" (used by the timer library) + * + * @{ + */ + +#ifndef ETIMER_H_ +#define ETIMER_H_ + +#include "sys/timer.h" +#include "sys/process.h" + +/** + * A timer. + * + * This structure is used for declaring a timer. The timer must be set + * with etimer_set() before it can be used. + * + * \hideinitializer + */ +struct etimer { + struct timer timer; + struct etimer *next; + struct process *p; +}; + +/** + * \name Functions called from application programs + * @{ + */ + +/** + * \brief Set an event timer. + * \param et A pointer to the event timer + * \param interval The interval before the timer expires. + * + * This function is used to set an event timer for a time + * sometime in the future. When the event timer expires, + * the event PROCESS_EVENT_TIMER will be posted to the + * process that called the etimer_set() function. + * + */ +CCIF void etimer_set(struct etimer *et, clock_time_t interval); + +/** + * \brief Reset an event timer with the same interval as was + * previously set. + * \param et A pointer to the event timer. + * + * This function resets the event timer with the same + * interval that was given to the event timer with the + * etimer_set() function. The start point of the interval + * is the exact time that the event timer last + * expired. Therefore, this function will cause the timer + * to be stable over time, unlike the etimer_restart() + * function. + * + * \sa etimer_restart() + */ +CCIF void etimer_reset(struct etimer *et); + +/** + * \brief Reset an event timer with a new interval. + * \param et A pointer to the event timer. + * \param interval The interval before the timer expires. + * + * This function very similar to etimer_reset. Opposed to + * etimer_reset it is possible to change the timout. + * This allows accurate, non-periodic timers without drift. + * + * \sa etimer_reset() + */ +void etimer_reset_with_new_interval(struct etimer *et, clock_time_t interval); + +/** + * \brief Restart an event timer from the current point in time + * \param et A pointer to the event timer. + * + * This function restarts the event timer with the same + * interval that was given to the etimer_set() + * function. The event timer will start at the current + * time. + * + * \note A periodic timer will drift if this function is + * used to reset it. For periodic timers, use the + * etimer_reset() function instead. + * + * \sa etimer_reset() + */ +void etimer_restart(struct etimer *et); + +/** + * \brief Adjust the expiration time for an event timer + * \param et A pointer to the event timer. + * \param td The time difference to adjust the expiration time with. + * + * This function is used to adjust the time the event + * timer will expire. It can be used to synchronize + * periodic timers without the need to restart the timer + * or change the timer interval. + * + * \note This function should only be used for small + * adjustments. For large adjustments use etimer_set() + * instead. + * + * \note A periodic timer will drift unless the + * etimer_reset() function is used. + * + * \sa etimer_set() + * \sa etimer_reset() + */ +void etimer_adjust(struct etimer *et, int td); + +/** + * \brief Get the expiration time for the event timer. + * \param et A pointer to the event timer + * \return The expiration time for the event timer. + * + * This function returns the expiration time for an event timer. + */ +clock_time_t etimer_expiration_time(struct etimer *et); + +/** + * \brief Get the start time for the event timer. + * \param et A pointer to the event timer + * \return The start time for the event timer. + * + * This function returns the start time (when the timer + * was last set) for an event timer. + */ +clock_time_t etimer_start_time(struct etimer *et); + +/** + * \brief Check if an event timer has expired. + * \param et A pointer to the event timer + * \return Non-zero if the timer has expired, zero otherwise. + * + * This function tests if an event timer has expired and + * returns true or false depending on its status. + */ +CCIF int etimer_expired(struct etimer *et); + +/** + * \brief Stop a pending event timer. + * \param et A pointer to the pending event timer. + * + * This function stops an event timer that has previously + * been set with etimer_set() or etimer_reset(). After + * this function has been called, the event timer will not + * emit any event when it expires. + * + */ +void etimer_stop(struct etimer *et); + +/** @} */ + +/** + * \name Functions called from timer interrupts, by the system + * @{ + */ + +/** + * \brief Make the event timer aware that the clock has changed + * + * This function is used to inform the event timer module + * that the system clock has been updated. Typically, this + * function would be called from the timer interrupt + * handler when the clock has ticked. + */ +void etimer_request_poll(void); + +/** + * \brief Check if there are any non-expired event timers. + * \return True if there are active event timers, false if there are + * no active timers. + * + * This function checks if there are any active event + * timers that have not expired. + */ +int etimer_pending(void); + +/** + * \brief Get next event timer expiration time. + * \return Next expiration time of all pending event timers. + * If there are no pending event timers this function + * returns 0. + * + * This functions returns next expiration time of all + * pending event timers. + */ +clock_time_t etimer_next_expiration_time(void); + + +/** @} */ + +PROCESS_NAME(etimer_process); +#endif /* ETIMER_H_ */ +/** @} */ +/** @} */ diff --git a/lib/pbio/sys/lc-addrlabels.h b/lib/pbio/sys/lc-addrlabels.h new file mode 100644 index 000000000..fc86f92ce --- /dev/null +++ b/lib/pbio/sys/lc-addrlabels.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2004-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. + * + * Author: Adam Dunkels + * + */ + +/** + * \addtogroup lc + * @{ + */ + +/** + * \file + * Implementation of local continuations based on the "Labels as + * values" feature of gcc + * \author + * Adam Dunkels + * + * This implementation of local continuations is based on a special + * feature of the GCC C compiler called "labels as values". This + * feature allows assigning pointers with the address of the code + * corresponding to a particular C label. + * + * For more information, see the GCC documentation: + * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html + * + * Thanks to dividuum for finding the nice local scope label + * implementation. + */ + +#ifndef LC_ADDRLABELS_H_ +#define LC_ADDRLABELS_H_ + +/** \hideinitializer */ +typedef void * lc_t; + +#define LC_INIT(s) s = NULL + + +#define LC_RESUME(s) \ + do { \ + if(s != NULL) { \ + goto *s; \ + } \ + } while(0) + +#define LC_SET(s) \ + do { ({ __label__ resume; resume: (s) = &&resume; }); }while(0) + +#define LC_END(s) + +#endif /* LC_ADDRLABELS_H_ */ +/** @} */ diff --git a/lib/pbio/sys/lc-switch.h b/lib/pbio/sys/lc-switch.h new file mode 100644 index 000000000..8fcef3449 --- /dev/null +++ b/lib/pbio/sys/lc-switch.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2004-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. + * + * Author: Adam Dunkels + * + */ + +/** + * \addtogroup lc + * @{ + */ + +/** + * \file + * Implementation of local continuations based on switch() statement + * \author Adam Dunkels + * + * This implementation of local continuations uses the C switch() + * statement to resume execution of a function somewhere inside the + * function's body. The implementation is based on the fact that + * switch() statements are able to jump directly into the bodies of + * control structures such as if() or while() statements. + * + * This implementation borrows heavily from Simon Tatham's coroutines + * implementation in C: + * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html + */ + +#ifndef LC_SWITCH_H_ +#define LC_SWITCH_H_ + +/* WARNING! lc implementation using switch() does not work if an + LC_SET() is done within another switch() statement! */ + +/** \hideinitializer */ +typedef unsigned short lc_t; + +#define LC_INIT(s) s = 0; + +#define LC_RESUME(s) switch(s) { case 0: + +#define LC_SET(s) s = __LINE__; case __LINE__: + +#define LC_END(s) } + +#endif /* LC_SWITCH_H_ */ + +/** @} */ diff --git a/lib/pbio/sys/lc.h b/lib/pbio/sys/lc.h new file mode 100644 index 000000000..6062a21e2 --- /dev/null +++ b/lib/pbio/sys/lc.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2004-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. + * + * Author: Adam Dunkels + * + */ + +/** + * \addtogroup pt + * @{ + */ + +/** + * \defgroup lc Local continuations + * @{ + * + * Local continuations form the basis for implementing protothreads. A + * local continuation can be set in a specific function to + * capture the state of the function. After a local continuation has + * been set can be resumed in order to restore the state of the + * function at the point where the local continuation was set. + * + * + */ + +/** + * \file core/sys/lc.h + * Local continuations + * \author + * Adam Dunkels + * + */ + +#ifdef DOXYGEN +/** + * Initialize a local continuation. + * + * This operation initializes the local continuation, thereby + * unsetting any previously set continuation state. + * + * \hideinitializer + */ +#define LC_INIT(lc) + +/** + * Set a local continuation. + * + * The set operation saves the state of the function at the point + * where the operation is executed. As far as the set operation is + * concerned, the state of the function does not include the + * call-stack or local (automatic) variables, but only the program + * counter and such CPU registers that needs to be saved. + * + * \hideinitializer + */ +#define LC_SET(lc) + +/** + * Resume a local continuation. + * + * The resume operation resumes a previously set local continuation, thus + * restoring the state in which the function was when the local + * continuation was set. If the local continuation has not been + * previously set, the resume operation does nothing. + * + * \hideinitializer + */ +#define LC_RESUME(lc) + +/** + * Mark the end of local continuation usage. + * + * The end operation signifies that local continuations should not be + * used any more in the function. This operation is not needed for + * most implementations of local continuation, but is required by a + * few implementations. + * + * \hideinitializer + */ +#define LC_END(lc) + +/** + * \var typedef lc_t; + * + * The local continuation type. + * + * \hideinitializer + */ +#endif /* DOXYGEN */ + +#ifndef LC_H_ +#define LC_H_ + +#ifdef LC_CONF_INCLUDE +#include LC_CONF_INCLUDE +#else /* LC_CONF_INCLUDE */ +#include "sys/lc-switch.h" +#endif /* LC_CONF_INCLUDE */ + +#endif /* LC_H_ */ + +/** @} */ +/** @} */ diff --git a/lib/pbio/sys/loader.h b/lib/pbio/sys/loader.h new file mode 100644 index 000000000..7d2e264c6 --- /dev/null +++ b/lib/pbio/sys/loader.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2003, Adam Dunkels. + * 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. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 desktop OS + * + * + */ + +/** + * \file + * Default definitions and error values for the Contiki program loader. + * \author Adam Dunkels + * + */ + +/** \addtogroup sys + * @{ + */ + +/** + * \defgroup loader The Contiki program loader + * + * The Contiki program loader is an abstract interface for loading and + * starting programs. + * + * @{ + */ + +#ifndef LOADER_H_ +#define LOADER_H_ + +/* Errors that the LOADER_LOAD() function may return: */ + +#define LOADER_OK 0 /**< No error. */ +#define LOADER_ERR_READ 1 /**< Read error. */ +#define LOADER_ERR_HDR 2 /**< Header error. */ +#define LOADER_ERR_OS 3 /**< Wrong OS. */ +#define LOADER_ERR_FMT 4 /**< Data format error. */ +#define LOADER_ERR_MEM 5 /**< Not enough memory. */ +#define LOADER_ERR_OPEN 6 /**< Could not open file. */ +#define LOADER_ERR_ARCH 7 /**< Wrong architecture. */ +#define LOADER_ERR_VERSION 8 /**< Wrong OS version. */ +#define LOADER_ERR_NOLOADER 9 /**< Program loading not supported. */ + +#ifdef LOADER_CONF_ARCH +#include LOADER_CONF_ARCH +#endif /* LOADER_CONF_ARCH */ + +/** + * Load and execute a program. + * + * This macro is used for loading and executing a program, and + * requires support from the architecture dependent code. The actual + * program loading is made by architecture specific functions. + * + * \note A program loaded with LOADER_LOAD() must call the + * LOADER_UNLOAD() function to unload itself. + * + * \param name The name of the program to be loaded. + * + * \param arg A pointer argument that is passed to the program. + * + * \return A loader error, or LOADER_OK if loading was successful. + */ +#ifndef LOADER_LOAD +#define LOADER_LOAD(name, arg) LOADER_ERR_NOLOADER +#endif /* LOADER_LOAD */ + +/** + * Unload a program from memory. + * + * This macro is used for unloading a program and deallocating any + * memory that was allocated during the loading of the program. This + * function must be called by the program itself. + * + */ +#ifndef LOADER_UNLOAD +#define LOADER_UNLOAD() +#endif /* LOADER_UNLOAD */ + +/** + * Load a DSC (program description). + * + * Loads a DSC (program description) into memory and returns a pointer + * to the dsc. + * + * \return A pointer to the DSC or NULL if it could not be loaded. + */ +#ifndef LOADER_LOAD_DSC +#define LOADER_LOAD_DSC(name) NULL +#endif /* LOADER_LOAD_DSC */ + +/** + * Unload a DSC (program description). + * + * Unload a DSC from memory and deallocate any memory that was + * allocated when it was loaded. + */ +#ifndef LOADER_UNLOAD_DSC +#define LOADER_UNLOAD_DSC(dsc) +#endif /* LOADER_UNLOAD */ + +#endif /* LOADER_H_ */ + +/** @} */ +/** @} */ diff --git a/lib/pbio/sys/log.h b/lib/pbio/sys/log.h new file mode 100644 index 000000000..c6bc24737 --- /dev/null +++ b/lib/pbio/sys/log.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2004, 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. + * + * Author: Adam Dunkels + * + */ +#ifndef LOG_H_ +#define LOG_H_ + +#include "contiki-conf.h" + +#if LOG_CONF_ENABLED +void log_message(const char *part1, const char *part2); +#else /* LOG_CONF_ENABLED */ +#define log_message(p1, p2) +#endif /* LOG_CONF_ENABLED */ + +#endif /* LOG_H_ */ diff --git a/lib/pbio/sys/mt.c b/lib/pbio/sys/mt.c new file mode 100644 index 000000000..d5bc10398 --- /dev/null +++ b/lib/pbio/sys/mt.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2006, 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. + * + * Author: Adam Dunkels + * + */ + +/** + * \file + * Implementation of the archtecture agnostic parts of the preemptive + * multithreading library for Contiki. + * + * \author + * Adam Dunkels + * + */ + +#include "contiki.h" +#include "sys/mt.h" +#include "sys/cc.h" + +static struct mt_thread *current; + +/*--------------------------------------------------------------------------*/ +void +mt_init(void) +{ + mtarch_init(); +} +/*--------------------------------------------------------------------------*/ +void +mt_remove(void) +{ + mtarch_remove(); +} +/*--------------------------------------------------------------------------*/ +void +mt_start(struct mt_thread *thread, void (* function)(void *), void *data) +{ + /* Call the architecture dependant function to set up the processor + stack with the correct parameters. */ + mtarch_start(&thread->thread, function, data); + + thread->state = MT_STATE_STARTED; +} +/*--------------------------------------------------------------------------*/ +void +mt_exec(struct mt_thread *thread) +{ + if(thread->state == MT_STATE_STARTED) { + current = thread; + /* Switch context to the thread. The function call will not return + until the the thread has yielded, or is preempted. */ + mtarch_exec(&thread->thread); + } +} +/*--------------------------------------------------------------------------*/ +void +mt_yield(void) +{ + mtarch_pstop(); + /* This function is called from the running thread, and we call the + switch function in order to switch the thread to the main Contiki + program instead. For us, the switch function will not return + until the next time we are scheduled to run. */ + mtarch_yield(); +} +/*--------------------------------------------------------------------------*/ +void +mt_exit(void) +{ + mtarch_pstop(); + current->state = MT_STATE_EXITED; + mtarch_yield(); +} +/*--------------------------------------------------------------------------*/ +void +mt_stop(struct mt_thread *thread) +{ + mtarch_stop(&thread->thread); +} +/*--------------------------------------------------------------------------*/ diff --git a/lib/pbio/sys/mt.h b/lib/pbio/sys/mt.h new file mode 100644 index 000000000..b472b3197 --- /dev/null +++ b/lib/pbio/sys/mt.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2004, 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. + * + * Author: Adam Dunkels + * + */ + +/** \addtogroup sys + * @{ + */ + +/** + * \defgroup mt Multi-threading library + * + * The event driven Contiki kernel does not provide multi-threading + * by itself - instead, preemptive multi-threading is implemented + * as a library that optionally can be linked with applications. This + * library consists of two parts: a platform independent part, which is + * the same for all platforms on which Contiki runs, and a platform + * specific part, which must be implemented specifically for the + * platform that the multi-threading library should run. + * + * @{ + */ + +/** + * \defgroup mtarch Architecture support for multi-threading + * @{ + * + * The Contiki multi-threading library requires some architecture + * specific support for setting up and switching stacks. This support + * requires four stack manipulation functions to be implemented: + * mtarch_start(), which sets up the stack frame for a new thread, + * mtarch_exec(), which switches in the stack of a thread, + * mtarch_yield(), which restores the kernel stack from a thread's + * stack and mtarch_stop(), which cleans up the stack of a thread. + * Additionally, two functions for controlling the preemption + * (if any) must be implemented: mtarch_pstart() and mtarch_pstop(). + * If no preemption is used, these functions can be implemented as + * empty functions. Finally, the function mtarch_init() is called by + * mt_init(), and can be used for initialization of timer interrupts, + * or any other mechanisms required for correct operation of the + * architecture specific support functions while mtarch_remove() is + * called by mt_remove() to clean up those resources. + * + */ + +/** + * \file + * Header file for the preemptive multitasking library for Contiki. + * \author + * Adam Dunkels + * + */ +#ifndef MT_H_ +#define MT_H_ + +#include "contiki.h" + +#define MT_STATE_STARTED 1 +#define MT_STATE_EXITED 2 + +/** + * An opaque structure that is used for holding the state of a thread. + * + * The structure should be defined in the "mtarch.h" file. This + * structure typically holds the entire stack for the thread. + */ +struct mtarch_thread; + +/** + * Initialize the architecture specific support functions for the + * multi-thread library. + * + * This function is implemented by the architecture specific functions + * for the multi-thread library and is called by the mt_init() + * function as part of the initialization of the library. The + * mtarch_init() function can be used for, e.g., starting preemption + * timers or other architecture specific mechanisms required for the + * operation of the library. + */ +void mtarch_init(void); + +/** + * Uninstall library and clean up. + * + */ +void mtarch_remove(void); + +/** + * Setup the stack frame for a thread that is being started. + * + * This function is called by the mt_start() function in order to set + * up the architecture specific stack of the thread to be started. + * + * \param thread A pointer to a struct mtarch_thread for the thread to + * be started. + * + * \param function A pointer to the function that the thread will + * start executing the first time it is scheduled to run. + * + * \param data A pointer to the argument that the function should be + * passed. + */ +void mtarch_start(struct mtarch_thread *thread, + void (* function)(void *data), + void *data); + +/** + * Start executing a thread. + * + * This function is called from mt_exec() and the purpose of the + * function is to start execution of the thread. The function should + * switch in the stack of the thread, and does not return until the + * thread has explicitly yielded (using mt_yield()) or until it is + * preempted. + * + * \param thread A pointer to a struct mtarch_thread for the thread to + * be executed. + * + */ +void mtarch_exec(struct mtarch_thread *thread); + +/** + * Yield the processor. + * + * This function is called by the mt_yield() function, which is called + * from the running thread in order to give up the processor. + * + */ +void mtarch_yield(void); + +/** + * Clean up the stack of a thread. + * + * This function is called by the mt_stop() function in order to clean + * up the architecture specific stack of the thread to be stopped. + * + * \note If the stack is wholly contained in struct mtarch_thread this + * function may very well be empty. + * + * \param thread A pointer to a struct mtarch_thread for the thread to + * be stopped. + * + */ +void mtarch_stop(struct mtarch_thread *thread); + +void mtarch_pstart(void); +void mtarch_pstop(void); + +/** @} */ + + +#include "mtarch.h" + +struct mt_thread { + int state; + struct mtarch_thread thread; +}; + +/** + * Initializes the multithreading library. + * + */ +void mt_init(void); + +/** + * Uninstalls library and cleans up. + * + */ +void mt_remove(void); + + +/** + * Starts a multithreading thread. + * + * \param thread Pointer to an mt_thread struct that must have been + * previously allocated by the caller. + * + * \param function A pointer to the entry function of the thread that is + * to be set up. + * + * \param data A pointer that will be passed to the entry function. + * + */ +void mt_start(struct mt_thread *thread, void (* function)(void *), void *data); + +/** + * Execute parts of a thread. + * + * This function is called by a Contiki process and runs a + * thread. The function does not return until the thread has yielded, + * or is preempted. + * + * \note The thread library must first be initialized with the mt_init() + * function. + * + * \param thread A pointer to a struct mt_thread block that must be + * allocated by the caller. + * + */ +void mt_exec(struct mt_thread *thread); + +/** + * Voluntarily give up the processor. + * + * This function is called by a running thread in order to give up + * control of the CPU. + * + */ +void mt_yield(void); + +/** + * Exit a thread. + * + * This function is called from within an executing thread in order to + * exit the thread. The function never returns. + * + */ +void mt_exit(void); + +/** + * Stop a thread. + * + * This function is called by a Contiki process in order to clean up a + * thread. The struct mt_thread block may then be discarded by the caller. + * + * \param thread A pointer to a struct mt_thread block that must be + * allocated by the caller. + * + */ +void mt_stop(struct mt_thread *thread); + +/** @} */ +/** @} */ +#endif /* MT_H_ */ diff --git a/lib/pbio/sys/node-id.h b/lib/pbio/sys/node-id.h new file mode 100644 index 000000000..0b6ebe6b1 --- /dev/null +++ b/lib/pbio/sys/node-id.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2006, 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. + * + * Author: Adam Dunkels + * + */ + +#ifndef NODE_ID_H_ +#define NODE_ID_H_ + +void node_id_restore(void); +void node_id_burn(unsigned short node_id); + +extern unsigned short node_id; + +#endif /* NODE_ID_H_ */ diff --git a/lib/pbio/sys/process.c b/lib/pbio/sys/process.c new file mode 100644 index 000000000..f98057cd3 --- /dev/null +++ b/lib/pbio/sys/process.c @@ -0,0 +1,388 @@ +/* + * 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 + * + */ + +#include + +#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; +#endif + +static volatile unsigned char poll_requested; + +#define PROCESS_STATE_NONE 0 +#define PROCESS_STATE_RUNNING 1 +#define PROCESS_STATE_CALLED 2 + +static void call_process(struct process *p, process_event_t ev, process_data_t data); + +#define DEBUG 0 +#if DEBUG +#include +#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 is + already 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 to + exit 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 DEBUG + if(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_STATS + process_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 upwards + and decrease the number of events. */ + fevent = (fevent + 1) % PROCESS_CONF_NUMEVENTS; + --nevents; + + /* If this is a broadcast event, we deliver it to all events, in + order 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 in + between 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 the + specified process. */ + /* If the event was an INIT event, we should also update the + state 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? "": PROCESS_NAME_STRING(p), nevents); + } + + if(nevents == PROCESS_CONF_NUMEVENTS) { +#if DEBUG + if(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_STATS + if(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; +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/lib/pbio/sys/process.h b/lib/pbio/sys/process.h new file mode 100644 index 000000000..2d15ca89c --- /dev/null +++ b/lib/pbio/sys/process.h @@ -0,0 +1,531 @@ +/* + * 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 + * + */ +#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) "" +#else + const char *name; +#define PROCESS_NAME_STRING(process) (process)->name +#endif + PT_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: + \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(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_ */ + +/** @} */ +/** @} */ diff --git a/lib/pbio/sys/procinit.c b/lib/pbio/sys/procinit.c new file mode 100644 index 000000000..dfac1bf00 --- /dev/null +++ b/lib/pbio/sys/procinit.c @@ -0,0 +1,48 @@ +/* + * 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. + * + */ + +#include "contiki.h" +#include "sys/procinit.h" + +extern const struct process *procinit[]; + +/*---------------------------------------------------------------------------*/ +void +procinit_init(void) +{ + int i; + + for(i = 0; procinit[i] != NULL; ++i) { + process_start((struct process *)procinit[i], NULL); + } +} +/*---------------------------------------------------------------------------*/ diff --git a/lib/pbio/sys/procinit.h b/lib/pbio/sys/procinit.h new file mode 100644 index 000000000..5e65a6de6 --- /dev/null +++ b/lib/pbio/sys/procinit.h @@ -0,0 +1,44 @@ +/* + * 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. + * + */ +#ifndef PROCINIT_H_ +#define PROCINIT_H_ + +#include "sys/process.h" + +#if ! CC_NO_VA_ARGS +#define PROCINIT(...) \ +const struct process *procinit[] = {__VA_ARGS__, NULL} +#endif + +void procinit_init(void); + +#endif /* PROCINIT_H_ */ diff --git a/lib/pbio/sys/pt-sem.h b/lib/pbio/sys/pt-sem.h new file mode 100644 index 000000000..27effa57a --- /dev/null +++ b/lib/pbio/sys/pt-sem.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2004, 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. + * + * Author: Adam Dunkels + * + */ + +/** + * \addtogroup pt + * @{ + */ + +/** + * \defgroup ptsem Protothread semaphores + * @{ + * + * This module implements counting semaphores on top of + * protothreads. Semaphores are a synchronization primitive that + * provide two operations: "wait" and "signal". The "wait" operation + * checks the semaphore counter and blocks the thread if the counter + * is zero. The "signal" operation increases the semaphore counter but + * does not block. If another thread has blocked waiting for the + * semaphore that is signaled, the blocked thread will become + * runnable again. + * + * Semaphores can be used to implement other, more structured, + * synchronization primitives such as monitors and message + * queues/bounded buffers (see below). + * + * The following example shows how the producer-consumer problem, also + * known as the bounded buffer problem, can be solved using + * protothreads and semaphores. Notes on the program follow after the + * example. + * + \code +#include "pt-sem.h" + +#define NUM_ITEMS 32 +#define BUFSIZE 8 + +static struct pt_sem mutex, full, empty; + +PT_THREAD(producer(struct pt *pt)) +{ + static int produced; + + PT_BEGIN(pt); + + for(produced = 0; produced < NUM_ITEMS; ++produced) { + + PT_SEM_WAIT(pt, &full); + + PT_SEM_WAIT(pt, &mutex); + add_to_buffer(produce_item()); + PT_SEM_SIGNAL(pt, &mutex); + + PT_SEM_SIGNAL(pt, &empty); + } + + PT_END(pt); +} + +PT_THREAD(consumer(struct pt *pt)) +{ + static int consumed; + + PT_BEGIN(pt); + + for(consumed = 0; consumed < NUM_ITEMS; ++consumed) { + + PT_SEM_WAIT(pt, &empty); + + PT_SEM_WAIT(pt, &mutex); + consume_item(get_from_buffer()); + PT_SEM_SIGNAL(pt, &mutex); + + PT_SEM_SIGNAL(pt, &full); + } + + PT_END(pt); +} + +PT_THREAD(driver_thread(struct pt *pt)) +{ + static struct pt pt_producer, pt_consumer; + + PT_BEGIN(pt); + + PT_SEM_INIT(&empty, 0); + PT_SEM_INIT(&full, BUFSIZE); + PT_SEM_INIT(&mutex, 1); + + PT_INIT(&pt_producer); + PT_INIT(&pt_consumer); + + PT_WAIT_THREAD(pt, producer(&pt_producer) & + consumer(&pt_consumer)); + + PT_END(pt); +} + \endcode + * + * The program uses three protothreads: one protothread that + * implements the consumer, one thread that implements the producer, + * and one protothread that drives the two other protothreads. The + * program uses three semaphores: "full", "empty" and "mutex". The + * "mutex" semaphore is used to provide mutual exclusion for the + * buffer, the "empty" semaphore is used to block the consumer is the + * buffer is empty, and the "full" semaphore is used to block the + * producer is the buffer is full. + * + * The "driver_thread" holds two protothread state variables, + * "pt_producer" and "pt_consumer". It is important to note that both + * these variables are declared as static. If the static + * keyword is not used, both variables are stored on the stack. Since + * protothreads do not store the stack, these variables may be + * overwritten during a protothread wait operation. Similarly, both + * the "consumer" and "producer" protothreads declare their local + * variables as static, to avoid them being stored on the stack. + * + * + */ + +/** + * \file + * Counting semaphores implemented on protothreads + * \author + * Adam Dunkels + * + */ + +#ifndef PT_SEM_H_ +#define PT_SEM_H_ + +#include "sys/pt.h" + +struct pt_sem { + unsigned int head, tail; +}; + +#define PT_SEM_COUNT(s) ((s)->head - (s)->tail) + +/** + * Initialize a semaphore + * + * This macro initializes a semaphore with a value for the + * counter. Internally, the semaphores use an "unsigned int" to + * represent the counter, and therefore the "count" argument should be + * within range of an unsigned int. + * + * \param s (struct pt_sem *) A pointer to the pt_sem struct + * representing the semaphore + * + * \param c (unsigned int) The initial count of the semaphore. + * \hideinitializer + */ +#define PT_SEM_INIT(s, c) \ + do { \ + (s)->tail = 0; \ + (s)->head = (c); \ + } while(0) + +/** + * Wait for a semaphore + * + * This macro carries out the "wait" operation on the semaphore. The + * wait operation causes the protothread to block while the counter is + * zero. When the counter reaches a value larger than zero, the + * protothread will continue. + * + * \param pt (struct pt *) A pointer to the protothread (struct pt) in + * which the operation is executed. + * + * \param s (struct pt_sem *) A pointer to the pt_sem struct + * representing the semaphore + * + * \hideinitializer + */ +#define PT_SEM_WAIT(pt, s) \ + do { \ + PT_WAIT_UNTIL(pt, PT_SEM_COUNT(s) > 0); \ + ++(s)->tail; \ + } while(0) + +/** + * Signal a semaphore + * + * This macro carries out the "signal" operation on the semaphore. The + * signal operation increments the counter inside the semaphore, which + * eventually will cause waiting protothreads to continue executing. + * + * \param pt (struct pt *) A pointer to the protothread (struct pt) in + * which the operation is executed. + * + * \param s (struct pt_sem *) A pointer to the pt_sem struct + * representing the semaphore + * + * \hideinitializer + */ +#define PT_SEM_SIGNAL(pt, s) (++(s)->head) + +#endif /* PT_SEM_H_ */ + +/** @} */ +/** @} */ + diff --git a/lib/pbio/sys/pt.h b/lib/pbio/sys/pt.h new file mode 100644 index 000000000..c9549119e --- /dev/null +++ b/lib/pbio/sys/pt.h @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2004-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. + * + * Author: Adam Dunkels + * + */ + +/** + * \addtogroup pt + * @{ + */ + +/** + * \file + * Protothreads implementation. + * \author + * Adam Dunkels + * + */ + +#ifndef PT_H_ +#define PT_H_ + +#include "sys/lc.h" + +struct pt { + lc_t lc; +}; + +#define PT_WAITING 0 +#define PT_YIELDED 1 +#define PT_EXITED 2 +#define PT_ENDED 3 + +/** + * \name Initialization + * @{ + */ + +/** + * Initialize a protothread. + * + * Initializes a protothread. Initialization must be done prior to + * starting to execute the protothread. + * + * \param pt A pointer to the protothread control structure. + * + * \sa PT_SPAWN() + * + * \hideinitializer + */ +#define PT_INIT(pt) LC_INIT((pt)->lc) + +/** @} */ + +/** + * \name Declaration and definition + * @{ + */ + +/** + * Declaration of a protothread. + * + * This macro is used to declare a protothread. All protothreads must + * be declared with this macro. + * + * \param name_args The name and arguments of the C function + * implementing the protothread. + * + * \hideinitializer + */ +#define PT_THREAD(name_args) char name_args + +/** + * Declare the start of a protothread inside the C function + * implementing the protothread. + * + * This macro is used to declare the starting point of a + * protothread. It should be placed at the start of the function in + * which the protothread runs. All C statements above the PT_BEGIN() + * invokation will be executed each time the protothread is scheduled. + * + * \param pt A pointer to the protothread control structure. + * + * \hideinitializer + */ +#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; if (PT_YIELD_FLAG) {;} LC_RESUME((pt)->lc) + +/** + * Declare the end of a protothread. + * + * This macro is used for declaring that a protothread ends. It must + * always be used together with a matching PT_BEGIN() macro. + * + * \param pt A pointer to the protothread control structure. + * + * \hideinitializer + */ +#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \ + PT_INIT(pt); return PT_ENDED; } + +/** @} */ + +/** + * \name Blocked wait + * @{ + */ + +/** + * Block and wait until condition is true. + * + * This macro blocks the protothread until the specified condition is + * true. + * + * \param pt A pointer to the protothread control structure. + * \param condition The condition. + * + * \hideinitializer + */ +#define PT_WAIT_UNTIL(pt, condition) \ + do { \ + LC_SET((pt)->lc); \ + if(!(condition)) { \ + return PT_WAITING; \ + } \ + } while(0) + +/** + * Block and wait while condition is true. + * + * This function blocks and waits while condition is true. See + * PT_WAIT_UNTIL(). + * + * \param pt A pointer to the protothread control structure. + * \param cond The condition. + * + * \hideinitializer + */ +#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond)) + +/** @} */ + +/** + * \name Hierarchical protothreads + * @{ + */ + +/** + * Block and wait until a child protothread completes. + * + * This macro schedules a child protothread. The current protothread + * will block until the child protothread completes. + * + * \note The child protothread must be manually initialized with the + * PT_INIT() function before this function is used. + * + * \param pt A pointer to the protothread control structure. + * \param thread The child protothread with arguments + * + * \sa PT_SPAWN() + * + * \hideinitializer + */ +#define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread)) + +/** + * Spawn a child protothread and wait until it exits. + * + * This macro spawns a child protothread and waits until it exits. The + * macro can only be used within a protothread. + * + * \param pt A pointer to the protothread control structure. + * \param child A pointer to the child protothread's control structure. + * \param thread The child protothread with arguments + * + * \hideinitializer + */ +#define PT_SPAWN(pt, child, thread) \ + do { \ + PT_INIT((child)); \ + PT_WAIT_THREAD((pt), (thread)); \ + } while(0) + +/** @} */ + +/** + * \name Exiting and restarting + * @{ + */ + +/** + * Restart the protothread. + * + * This macro will block and cause the running protothread to restart + * its execution at the place of the PT_BEGIN() call. + * + * \param pt A pointer to the protothread control structure. + * + * \hideinitializer + */ +#define PT_RESTART(pt) \ + do { \ + PT_INIT(pt); \ + return PT_WAITING; \ + } while(0) + +/** + * Exit the protothread. + * + * This macro causes the protothread to exit. If the protothread was + * spawned by another protothread, the parent protothread will become + * unblocked and can continue to run. + * + * \param pt A pointer to the protothread control structure. + * + * \hideinitializer + */ +#define PT_EXIT(pt) \ + do { \ + PT_INIT(pt); \ + return PT_EXITED; \ + } while(0) + +/** @} */ + +/** + * \name Calling a protothread + * @{ + */ + +/** + * Schedule a protothread. + * + * This function schedules a protothread. The return value of the + * function is non-zero if the protothread is running or zero if the + * protothread has exited. + * + * \param f The call to the C function implementing the protothread to + * be scheduled + * + * \hideinitializer + */ +#define PT_SCHEDULE(f) ((f) < PT_EXITED) + +/** @} */ + +/** + * \name Yielding from a protothread + * @{ + */ + +/** + * Yield from the current protothread. + * + * This function will yield the protothread, thereby allowing other + * processing to take place in the system. + * + * \param pt A pointer to the protothread control structure. + * + * \hideinitializer + */ +#define PT_YIELD(pt) \ + do { \ + PT_YIELD_FLAG = 0; \ + LC_SET((pt)->lc); \ + if(PT_YIELD_FLAG == 0) { \ + return PT_YIELDED; \ + } \ + } while(0) + +/** + * \brief Yield from the protothread until a condition occurs. + * \param pt A pointer to the protothread control structure. + * \param cond The condition. + * + * This function will yield the protothread, until the + * specified condition evaluates to true. + * + * + * \hideinitializer + */ +#define PT_YIELD_UNTIL(pt, cond) \ + do { \ + PT_YIELD_FLAG = 0; \ + LC_SET((pt)->lc); \ + if((PT_YIELD_FLAG == 0) || !(cond)) { \ + return PT_YIELDED; \ + } \ + } while(0) + +/** @} */ + +#endif /* PT_H_ */ + +/** @} */ diff --git a/lib/pbio/sys/rtimer.c b/lib/pbio/sys/rtimer.c new file mode 100644 index 000000000..cf96a17bf --- /dev/null +++ b/lib/pbio/sys/rtimer.c @@ -0,0 +1,108 @@ +/* + * 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. + * + */ + +/** + * \file + * Implementation of the architecture-agnostic parts of the real-time timer module. + * \author + * Adam Dunkels + * + */ + +/** + * \addtogroup rt + * @{ + */ + +#include "sys/rtimer.h" +#include "contiki.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +static struct rtimer *next_rtimer; + +/*---------------------------------------------------------------------------*/ +void +rtimer_init(void) +{ + rtimer_arch_init(); +} +/*---------------------------------------------------------------------------*/ +int +rtimer_set(struct rtimer *rtimer, rtimer_clock_t time, + rtimer_clock_t duration, + rtimer_callback_t func, void *ptr) +{ + int first = 0; + + PRINTF("rtimer_set time %d\n", time); + + if(next_rtimer == NULL) { + first = 1; + } + + rtimer->func = func; + rtimer->ptr = ptr; + + rtimer->time = time; + next_rtimer = rtimer; + + if(first == 1) { + rtimer_arch_schedule(time); + } + return RTIMER_OK; +} +/*---------------------------------------------------------------------------*/ +void +rtimer_run_next(void) +{ + struct rtimer *t; + if(next_rtimer == NULL) { + return; + } + t = next_rtimer; + next_rtimer = NULL; + t->func(t, t->ptr); + if(next_rtimer != NULL) { + rtimer_arch_schedule(next_rtimer->time); + } + return; +} +/*---------------------------------------------------------------------------*/ + +/** @}*/ diff --git a/lib/pbio/sys/rtimer.h b/lib/pbio/sys/rtimer.h new file mode 100644 index 000000000..a89ed8299 --- /dev/null +++ b/lib/pbio/sys/rtimer.h @@ -0,0 +1,169 @@ +/* + * 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. + * + */ + +/** + * \file + * Header file for the real-time timer module. + * \author + * Adam Dunkels + * + */ + +/** \addtogroup sys + * @{ */ + +/** + * \defgroup rt Real-time task scheduling + * + * The real-time module handles the scheduling and execution of + * real-time tasks (with predictable execution times). + * + * @{ + */ + +#ifndef RTIMER_H_ +#define RTIMER_H_ + +#include "contiki-conf.h" + +#ifndef RTIMER_CLOCK_DIFF +typedef unsigned short rtimer_clock_t; +#define RTIMER_CLOCK_DIFF(a,b) ((signed short)((a)-(b))) +#endif /* RTIMER_CLOCK_DIFF */ + +#define RTIMER_CLOCK_LT(a, b) (RTIMER_CLOCK_DIFF((a),(b)) < 0) + +#include "rtimer-arch.h" + +/** + * \brief Initialize the real-time scheduler. + * + * This function initializes the real-time scheduler and + * must be called at boot-up, before any other functions + * from the real-time scheduler is called. + */ +void rtimer_init(void); + +struct rtimer; +typedef void (* rtimer_callback_t)(struct rtimer *t, void *ptr); + +/** + * \brief Representation of a real-time task + * + * This structure represents a real-time task and is used + * by the real-time module and the architecture specific + * support module for the real-time module. + */ +struct rtimer { + rtimer_clock_t time; + rtimer_callback_t func; + void *ptr; +}; + +enum { + RTIMER_OK, + RTIMER_ERR_FULL, + RTIMER_ERR_TIME, + RTIMER_ERR_ALREADY_SCHEDULED, +}; + +/** + * \brief Post a real-time task. + * \param task A pointer to the task variable previously declared with RTIMER_TASK(). + * \param time The time when the task is to be executed. + * \param duration Unused argument. + * \param func A function to be called when the task is executed. + * \param ptr An opaque pointer that will be supplied as an argument to the callback function. + * \return Non-zero (true) if the task could be scheduled, zero + * (false) if the task could not be scheduled. + * + * This function schedules a real-time task at a specified + * time in the future. + * + */ +int rtimer_set(struct rtimer *task, rtimer_clock_t time, + rtimer_clock_t duration, rtimer_callback_t func, void *ptr); + +/** + * \brief Execute the next real-time task and schedule the next task, if any + * + * This function is called by the architecture dependent + * code to execute and schedule the next real-time task. + * + */ +void rtimer_run_next(void); + +/** + * \brief Get the current clock time + * \return The current time + * + * This function returns what the real-time module thinks + * is the current time. The current time is used to set + * the timeouts for real-time tasks. + * + * \hideinitializer + */ +#define RTIMER_NOW() rtimer_arch_now() + +/** + * \brief Get the time that a task last was executed + * \param task The task + * \return The time that a task last was executed + * + * This function returns the time that the task was last + * executed. This typically is used to get a periodic + * execution of a task without clock drift. + * + * \hideinitializer + */ +#define RTIMER_TIME(task) ((task)->time) + +void rtimer_arch_init(void); +void rtimer_arch_schedule(rtimer_clock_t t); +/*rtimer_clock_t rtimer_arch_now(void);*/ + +#define RTIMER_SECOND RTIMER_ARCH_SECOND + +/* RTIMER_GUARD_TIME is the minimum amount of rtimer ticks between + the current time and the future time when a rtimer is scheduled. + Necessary to avoid accidentally scheduling a rtimer in the past + on platforms with fast rtimer ticks. Should be >= 2. */ +#ifdef RTIMER_CONF_GUARD_TIME +#define RTIMER_GUARD_TIME RTIMER_CONF_GUARD_TIME +#else /* RTIMER_CONF_GUARD_TIME */ +#define RTIMER_GUARD_TIME (RTIMER_ARCH_SECOND >> 14) +#endif /* RTIMER_CONF_GUARD_TIME */ + +#endif /* RTIMER_H_ */ + +/** @} */ +/** @} */ diff --git a/lib/pbio/sys/stimer.c b/lib/pbio/sys/stimer.c new file mode 100644 index 000000000..86545f59e --- /dev/null +++ b/lib/pbio/sys/stimer.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2004, 2008, 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. + * + * Author: Adam Dunkels , Nicolas Tsiftes + * + */ + +/** + * \file + * Timer of seconds library implementation. + * \author + * Adam Dunkels , Nicolas Tsiftes + */ + +/** + * \addtogroup stimer + * @{ + */ + +#include "contiki-conf.h" +#include "sys/clock.h" +#include "sys/stimer.h" + +#define SCLOCK_GEQ(a, b) ((unsigned long)((a) - (b)) < \ + ((unsigned long)(~((unsigned long)0)) >> 1)) + +/*---------------------------------------------------------------------------*/ +/** + * Set a timer. + * + * This function is used to set a timer for a time sometime in the + * future. The function stimer_expired() will evaluate to true after + * the timer has expired. + * + * \param t A pointer to the timer + * \param interval The interval before the timer expires. + * + */ +void +stimer_set(struct stimer *t, unsigned long interval) +{ + t->interval = interval; + t->start = clock_seconds(); +} +/*---------------------------------------------------------------------------*/ +/** + * Reset the timer with the same interval. + * + * This function resets the timer with the same interval that was + * given to the stimer_set() function. The start point of the interval + * is the exact time that the timer last expired. Therefore, this + * function will cause the timer to be stable over time, unlike the + * stimer_restart() function. + * + * \param t A pointer to the timer. + * + * \sa stimer_restart() + */ +void +stimer_reset(struct stimer *t) +{ + t->start += t->interval; +} +/*---------------------------------------------------------------------------*/ +/** + * Restart the timer from the current point in time + * + * This function restarts a timer with the same interval that was + * given to the stimer_set() function. The timer will start at the + * current time. + * + * \note A periodic timer will drift if this function is used to reset + * it. For preioric timers, use the stimer_reset() function instead. + * + * \param t A pointer to the timer. + * + * \sa stimer_reset() + */ +void +stimer_restart(struct stimer *t) +{ + t->start = clock_seconds(); +} +/*---------------------------------------------------------------------------*/ +/** + * Check if a timer has expired. + * + * This function tests if a timer has expired and returns true or + * false depending on its status. + * + * \param t A pointer to the timer + * + * \return Non-zero if the timer has expired, zero otherwise. + * + */ +int +stimer_expired(struct stimer *t) +{ + return SCLOCK_GEQ(clock_seconds(), t->start + t->interval); +} +/*---------------------------------------------------------------------------*/ +/** + * The time until the timer expires + * + * This function returns the time until the timer expires. + * + * \param t A pointer to the timer + * + * \return The time until the timer expires + * + */ +unsigned long +stimer_remaining(struct stimer *t) +{ + return t->start + t->interval - clock_seconds(); +} +/*---------------------------------------------------------------------------*/ +/** + * The time elapsed since the timer started + * + * This function returns the time elapsed. + * + * \param t A pointer to the timer + * + * \return The time elapsed since the last start of the timer + * + */ +unsigned long +stimer_elapsed(struct stimer *t) +{ + return clock_seconds() - t->start; +} + +/*---------------------------------------------------------------------------*/ + +/** @} */ diff --git a/lib/pbio/sys/stimer.h b/lib/pbio/sys/stimer.h new file mode 100644 index 000000000..6ef7db5de --- /dev/null +++ b/lib/pbio/sys/stimer.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2004, 2008, 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. + * + * Author: Adam Dunkels , Nicolas Tsiftes + * + */ + +/** + * \file + * Second timer library header file. + * \author + * Adam Dunkels , Nicolas Tsiftes + */ + +/** \addtogroup sys + * @{ */ + +/** + * \defgroup stimer Seconds timer library + * + * The stimer library provides functions for setting, resetting and + * restarting timers, and for checking if a timer has expired. An + * application must "manually" check if its timers have expired; this + * is not done automatically. + * + * A timer is declared as a \c struct \c stimer and all access to the + * timer is made by a pointer to the declared timer. + * + * \note The stimer library is not able to post events when a timer + * expires. The \ref etimer "Event timers" should be used for this + * purpose. + * + * \note The stimer library uses the \ref clock "Clock library" to + * measure time. Intervals should be specified in the seconds. + * + * \sa \ref etimer "Event timers" + * + * @{ + */ + +#ifndef STIMER_H_ +#define STIMER_H_ + +#include "sys/clock.h" + +/** + * A timer. + * + * This structure is used for declaring a timer. The timer must be set + * with stimer_set() before it can be used. + * + * \hideinitializer + */ +struct stimer { + unsigned long start; + unsigned long interval; +}; + +void stimer_set(struct stimer *t, unsigned long interval); +void stimer_reset(struct stimer *t); +void stimer_restart(struct stimer *t); +int stimer_expired(struct stimer *t); +unsigned long stimer_remaining(struct stimer *t); +unsigned long stimer_elapsed(struct stimer *t); + + +#endif /* STIMER_H_ */ + +/** @} */ +/** @} */ diff --git a/lib/pbio/sys/subprocess.h b/lib/pbio/sys/subprocess.h new file mode 100644 index 000000000..ebb95501e --- /dev/null +++ b/lib/pbio/sys/subprocess.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2006, 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 subprocess Contiki subprocesses + * @{ + * + * A Contiki subprocess is a "process-in-a-process". + */ + +/** + * \file + * Subprocesses for Contiki + * \author + * Adam Dunkels + */ + +#ifndef SUBPROCESS_H_ +#define SUBPROCESS_H_ + +#define SUBPROCESS_BEGIN(strname) \ +{ \ + static struct process subprocess_subprocess = {NULL, strname}; \ + subprocess_subprocess.thread = PROCESS_CURRENT()->thread; \ + process_start(&subprocess_subprocess, NULL); \ + PT_INIT(&subprocess_subprocess.pt); \ + LC_SET(subprocess_subprocess.pt.lc); \ + if(PROCESS_CURRENT() == &subprocess_subprocess) { + +#define SUBPROCESS_END() \ + PROCESS_EXIT(); \ + } \ +} + +#endif /* SUBPROCESS_H_ */ + +/** @}*/ +/** @}*/ diff --git a/lib/pbio/sys/timer.c b/lib/pbio/sys/timer.c new file mode 100644 index 000000000..6fe64119b --- /dev/null +++ b/lib/pbio/sys/timer.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2004, 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. + * + * Author: Adam Dunkels + * + */ + +/** + * \file + * Timer library implementation. + * \author + * Adam Dunkels + */ + +/** + * \addtogroup timer + * @{ + */ + +#include "contiki-conf.h" +#include "sys/clock.h" +#include "sys/timer.h" + +/*---------------------------------------------------------------------------*/ +/** + * Set a timer. + * + * This function is used to set a timer for a time sometime in the + * future. The function timer_expired() will evaluate to true after + * the timer has expired. + * + * \param t A pointer to the timer + * \param interval The interval before the timer expires. + * + */ +void +timer_set(struct timer *t, clock_time_t interval) +{ + t->interval = interval; + t->start = clock_time(); +} +/*---------------------------------------------------------------------------*/ +/** + * Reset the timer with the same interval. + * + * This function resets the timer with the same interval that was + * given to the timer_set() function. The start point of the interval + * is the exact time that the timer last expired. Therefore, this + * function will cause the timer to be stable over time, unlike the + * timer_restart() function. + * + * \note Must not be executed before timer expired + * + * \param t A pointer to the timer. + * \sa timer_restart() + */ +void +timer_reset(struct timer *t) +{ + t->start += t->interval; +} +/*---------------------------------------------------------------------------*/ +/** + * Restart the timer from the current point in time + * + * This function restarts a timer with the same interval that was + * given to the timer_set() function. The timer will start at the + * current time. + * + * \note A periodic timer will drift if this function is used to reset + * it. For preioric timers, use the timer_reset() function instead. + * + * \param t A pointer to the timer. + * + * \sa timer_reset() + */ +void +timer_restart(struct timer *t) +{ + t->start = clock_time(); +} +/*---------------------------------------------------------------------------*/ +/** + * Check if a timer has expired. + * + * This function tests if a timer has expired and returns true or + * false depending on its status. + * + * \param t A pointer to the timer + * + * \return Non-zero if the timer has expired, zero otherwise. + * + */ +int +timer_expired(struct timer *t) +{ + /* Note: Can not return diff >= t->interval so we add 1 to diff and return + t->interval < diff - required to avoid an internal error in mspgcc. */ + clock_time_t diff = (clock_time() - t->start) + 1; + return t->interval < diff; + +} +/*---------------------------------------------------------------------------*/ +/** + * The time until the timer expires + * + * This function returns the time until the timer expires. + * + * \param t A pointer to the timer + * + * \return The time until the timer expires + * + */ +clock_time_t +timer_remaining(struct timer *t) +{ + return t->start + t->interval - clock_time(); +} +/*---------------------------------------------------------------------------*/ + +/** @} */ diff --git a/lib/pbio/sys/timer.h b/lib/pbio/sys/timer.h new file mode 100644 index 000000000..969137507 --- /dev/null +++ b/lib/pbio/sys/timer.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2004, 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. + * + * Author: Adam Dunkels + * + */ + +/** + * \file + * Timer library header file. + * \author + * Adam Dunkels + */ + +/** \addtogroup sys + * @{ */ + +/** + * \defgroup timer Timer library + * + * The Contiki kernel does not provide support for timed + * events. Rather, an application that wants to use timers needs to + * explicitly use the timer library. + * + * The timer library provides functions for setting, resetting and + * restarting timers, and for checking if a timer has expired. An + * application must "manually" check if its timers have expired; this + * is not done automatically. + * + * A timer is declared as a \c struct \c timer and all access to the + * timer is made by a pointer to the declared timer. + * + * \note The timer library is not able to post events when a timer + * expires. The \ref etimer "Event timers" should be used for this + * purpose. + * + * \note The timer library uses the \ref clock "Clock library" to + * measure time. Intervals should be specified in the format used by + * the clock library. + * + * \sa \ref etimer "Event timers" + * + * @{ + */ + +#ifndef TIMER_H_ +#define TIMER_H_ + +#include "sys/clock.h" + +/** + * A timer. + * + * This structure is used for declaring a timer. The timer must be set + * with timer_set() before it can be used. + * + * \hideinitializer + */ +struct timer { + clock_time_t start; + clock_time_t interval; +}; + +CCIF void timer_set(struct timer *t, clock_time_t interval); +void timer_reset(struct timer *t); +void timer_restart(struct timer *t); +CCIF int timer_expired(struct timer *t); +clock_time_t timer_remaining(struct timer *t); + + +#endif /* TIMER_H_ */ + +/** @} */ +/** @} */