From 341c06b33955120c40bc7dc8afabe4d3a019f571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E9=80=B8=E5=87=A1?= <1343619937@qq.com> Date: Tue, 22 Nov 2022 09:59:34 +0800 Subject: [PATCH] 1 --- Makefile | 9 + README-VISUAL-C++.txt | 5 + README.md | 51 +++ doc/Doxyfile | 229 +++++++++++ doc/Makefile | 7 + doc/header.tex | 52 +++ doc/html/a00005.html | 40 ++ doc/html/a00006.html | 40 ++ doc/html/a00009.html | 61 +++ doc/html/a00010.html | 56 +++ doc/html/a00011.html | 51 +++ doc/html/a00012.html | 51 +++ doc/html/a00013.html | 100 +++++ doc/html/a00014.html | 627 ++++++++++++++++++++++++++++++ doc/html/a00015.html | 711 ++++++++++++++++++++++++++++++++++ doc/html/a00016.html | 246 ++++++++++++ doc/html/a00017.html | 226 +++++++++++ doc/html/a00018.html | 109 ++++++ doc/html/a00019.html | 100 +++++ doc/html/a00020.html | 156 ++++++++ doc/html/a00021.html | 252 ++++++++++++ doc/html/a00022.html | 347 +++++++++++++++++ doc/html/annotated.html | 29 ++ doc/html/doxygen.css | 310 +++++++++++++++ doc/html/doxygen.png | Bin 0 -> 1281 bytes doc/html/files.html | 31 ++ doc/html/ftv2blank.png | Bin 0 -> 174 bytes doc/html/ftv2doc.png | Bin 0 -> 255 bytes doc/html/ftv2folderclosed.png | Bin 0 -> 259 bytes doc/html/ftv2folderopen.png | Bin 0 -> 261 bytes doc/html/ftv2lastnode.png | Bin 0 -> 233 bytes doc/html/ftv2link.png | Bin 0 -> 358 bytes doc/html/ftv2mlastnode.png | Bin 0 -> 160 bytes doc/html/ftv2mnode.png | Bin 0 -> 194 bytes doc/html/ftv2node.png | Bin 0 -> 235 bytes doc/html/ftv2plastnode.png | Bin 0 -> 165 bytes doc/html/ftv2pnode.png | Bin 0 -> 200 bytes doc/html/ftv2vertline.png | Bin 0 -> 229 bytes doc/html/functions.html | 37 ++ doc/html/functions_vars.html | 37 ++ doc/html/globals.html | 62 +++ doc/html/globals_defs.html | 61 +++ doc/html/globals_type.html | 36 ++ doc/html/hierarchy.html | 29 ++ doc/html/index.hhc | 43 ++ doc/html/index.hhk | 56 +++ doc/html/index.hhp | 44 +++ doc/html/index.html | 8 + doc/html/main.html | 81 ++++ doc/html/modules.html | 27 ++ doc/html/tab_b.gif | Bin 0 -> 35 bytes doc/html/tab_l.gif | Bin 0 -> 706 bytes doc/html/tab_r.gif | Bin 0 -> 2585 bytes doc/html/tabs.css | 102 +++++ doc/html/tree.html | 108 ++++++ doc/pt-doc.txt | 58 +++ doc/pt-mainpage.txt | 156 ++++++++ doc/pt-refman.pdf | Bin 0 -> 226750 bytes doc/sicslogo.pdf | Bin 0 -> 4547 bytes example-buffer.c | 165 ++++++++ example-codelock.c | 414 ++++++++++++++++++++ example-small.c | 97 +++++ lc-addrlabels.h | 85 ++++ lc-switch.h | 76 ++++ lc.h | 132 +++++++ pt-sem.h | 228 +++++++++++ pt.h | 315 +++++++++++++++ 67 files changed, 6353 insertions(+) create mode 100644 Makefile create mode 100644 README-VISUAL-C++.txt create mode 100644 README.md create mode 100644 doc/Doxyfile create mode 100644 doc/Makefile create mode 100644 doc/header.tex create mode 100644 doc/html/a00005.html create mode 100644 doc/html/a00006.html create mode 100644 doc/html/a00009.html create mode 100644 doc/html/a00010.html create mode 100644 doc/html/a00011.html create mode 100644 doc/html/a00012.html create mode 100644 doc/html/a00013.html create mode 100644 doc/html/a00014.html create mode 100644 doc/html/a00015.html create mode 100644 doc/html/a00016.html create mode 100644 doc/html/a00017.html create mode 100644 doc/html/a00018.html create mode 100644 doc/html/a00019.html create mode 100644 doc/html/a00020.html create mode 100644 doc/html/a00021.html create mode 100644 doc/html/a00022.html create mode 100644 doc/html/annotated.html create mode 100644 doc/html/doxygen.css create mode 100644 doc/html/doxygen.png create mode 100644 doc/html/files.html create mode 100644 doc/html/ftv2blank.png create mode 100644 doc/html/ftv2doc.png create mode 100644 doc/html/ftv2folderclosed.png create mode 100644 doc/html/ftv2folderopen.png create mode 100644 doc/html/ftv2lastnode.png create mode 100644 doc/html/ftv2link.png create mode 100644 doc/html/ftv2mlastnode.png create mode 100644 doc/html/ftv2mnode.png create mode 100644 doc/html/ftv2node.png create mode 100644 doc/html/ftv2plastnode.png create mode 100644 doc/html/ftv2pnode.png create mode 100644 doc/html/ftv2vertline.png create mode 100644 doc/html/functions.html create mode 100644 doc/html/functions_vars.html create mode 100644 doc/html/globals.html create mode 100644 doc/html/globals_defs.html create mode 100644 doc/html/globals_type.html create mode 100644 doc/html/hierarchy.html create mode 100644 doc/html/index.hhc create mode 100644 doc/html/index.hhk create mode 100644 doc/html/index.hhp create mode 100644 doc/html/index.html create mode 100644 doc/html/main.html create mode 100644 doc/html/modules.html create mode 100644 doc/html/tab_b.gif create mode 100644 doc/html/tab_l.gif create mode 100644 doc/html/tab_r.gif create mode 100644 doc/html/tabs.css create mode 100644 doc/html/tree.html create mode 100644 doc/pt-doc.txt create mode 100644 doc/pt-mainpage.txt create mode 100644 doc/pt-refman.pdf create mode 100644 doc/sicslogo.pdf create mode 100644 example-buffer.c create mode 100644 example-codelock.c create mode 100644 example-small.c create mode 100644 lc-addrlabels.h create mode 100644 lc-switch.h create mode 100644 lc.h create mode 100644 pt-sem.h create mode 100644 pt.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ff573ef --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +CFLAGS=-O -Wuninitialized -Werror + +all: example-codelock example-buffer example-small + +example-codelock: example-codelock.c pt.h lc.h + +example-buffer: example-buffer.c pt.h lc.h + +example-small: example-small.c pt.h lc.h diff --git a/README-VISUAL-C++.txt b/README-VISUAL-C++.txt new file mode 100644 index 0000000..3b09a69 --- /dev/null +++ b/README-VISUAL-C++.txt @@ -0,0 +1,5 @@ +Protothreads can in some cases fail to compile under Visual C++ +version 6.0 due to a bug in the compiler. See the following page for a +solution to the problem: + +http://support.microsoft.com/default.aspx?scid=kb;en-us;199057 diff --git a/README.md b/README.md new file mode 100644 index 0000000..eeace5d --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +Protothreads are extremely lightweight stackless threads designed for +severely memory constrained systems such as small embedded systems or +sensor network nodes. Protothreads can be used with or without an +underlying operating system. + +Protothreads provides a blocking context on top of an event-driven +system, without the overhead of per-thread stacks. The purpose of +protothreads is to implement sequential flow of control without +complex state machines or full multi-threading. + +Main features: + + * No machine specific code - the protothreads library is pure C + * Does not use error-prone functions such as longjmp() + * Very small RAM overhead - only two bytes per protothread + * Can be used with or without an OS + * Provides blocking wait without full multi-threading or + stack-switching + * Freely available under a BSD-like open source license + +Example applications: + + * Memory constrained systems + * Event-driven protocol stacks + * Small embedded systems + * Sensor network nodes + +The protothreads library is released under an open source BSD-style +license that allows for both non-commercial and commercial usage. The +only requirement is that credit is given. + +The protothreads library was written by Adam Dunkels +with support from Oliver Schmidt . + +More information and new versions can be found at the protothreads +homepage: + http://www.sics.se/~adam/pt/ + +Documentation can be found in the doc/ subdirectory. + +Two example programs illustrating the use of protothreads can be found +in this directory: + + example-small.c A small example showing how to use protothreads + example-buffer.c The bounded buffer problem with protothreads + example-codelock.c A code lock with simulated key input + +To compile the examples, simply run "make". + + +Adam Dunkels, 3 June 2006 diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..cecf583 --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,229 @@ +# Doxyfile 1.4.6 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = "The Protothreads Library 1.4" +PROJECT_NUMBER = +OUTPUT_DIRECTORY = . +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = ../ +STRIP_FROM_INC_PATH = +SHORT_NAMES = YES +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = YES +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_JAVA = NO +BUILTIN_STL_SUPPORT = NO +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = NO +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = YES +HIDE_UNDOC_CLASSES = YES +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = NO +GENERATE_DEPRECATEDLIST= NO +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = NO +SHOW_DIRECTORIES = NO +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = pt-mainpage.txt \ + pt-doc.txt \ + ../pt.h \ + ../pt-sem.h \ + ../lc.h \ + ../lc-switch.h \ + ../lc-addrlabels.h +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = .. +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = YES +STRIP_CODE_COMMENTS = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = YES +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = YES +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = YES +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = header.tex +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = DOXYGEN +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = NO +HIDE_UNDOC_RELATIONS = NO +HAVE_DOT = NO +CLASS_GRAPH = NO +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..fd0c7d1 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,7 @@ +dox: + doxygen Doxyfile + + +pdf: dox + (cd latex; $(MAKE) refman.pdf) + mv latex/refman.pdf pt-refman.pdf \ No newline at end of file diff --git a/doc/header.tex b/doc/header.tex new file mode 100644 index 0000000..5899653 --- /dev/null +++ b/doc/header.tex @@ -0,0 +1,52 @@ +\documentclass[a4paper]{article} +\usepackage{a4wide} +\usepackage{makeidx} +\usepackage{fancyhdr} +\usepackage{graphicx} +\usepackage{multicol} +\usepackage{float} +\usepackage{textcomp} +\usepackage{alltt} +\usepackage{times} +\usepackage{epsfig} +\ifx\pdfoutput\undefined +\usepackage[ps2pdf, + pagebackref=true, + colorlinks=true, + linkcolor=blue + ]{hyperref} +\usepackage{pspicture} +\else +\usepackage[pdftex, + pagebackref=true, + colorlinks=true, + linkcolor=blue + ]{hyperref} +\fi +\usepackage{doxygen} +\makeindex +\setcounter{tocdepth}{1} +\renewcommand{\footrulewidth}{0.4pt} +\begin{document} +\begin{titlepage} +\vspace*{5cm} +\begin{center} +{\Huge Protothreads}\\ +\vspace*{1cm} +{\LARGE The Protothreads Library 1.3 Reference Manual}\\ +\vspace*{3cm} +{\Large June 2006}\\ +\vspace*{2cm} +\includegraphics[width=6cm]{../sicslogo.pdf}\\ +\vspace*{1cm} +{\Large Adam Dunkels}\\ +{\Large \texttt{adam@sics.se}}\\ +\vspace*{1cm} +{\LARGE Swedish Institute of Computer Science}\\ +\vspace*{0.5cm} + +\end{center} +\end{titlepage} +\pagenumbering{roman} +\tableofcontents +\pagenumbering{arabic} diff --git a/doc/html/a00005.html b/doc/html/a00005.html new file mode 100644 index 0000000..4f2e17d --- /dev/null +++ b/doc/html/a00005.html @@ -0,0 +1,40 @@ + + +The Protothreads Library 1.4: pt Struct Reference + + + + + + +

pt Struct Reference
+ +[Protothreads] +


Detailed Description

+ +

+ +

+Definition at line 54 of file pt.h. + + + + +

Data Fields

+lc_t lc
+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00006.html b/doc/html/a00006.html new file mode 100644 index 0000000..2ea0775 --- /dev/null +++ b/doc/html/a00006.html @@ -0,0 +1,40 @@ + + +The Protothreads Library 1.4: pt_sem Struct Reference + + + + + + +

pt_sem Struct Reference
+ +[Protothread semaphores] +


Detailed Description

+ +

+ +

+Definition at line 165 of file pt-sem.h. + + + + +

Data Fields

+unsigned int count
+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00009.html b/doc/html/a00009.html new file mode 100644 index 0000000..b15ca22 --- /dev/null +++ b/doc/html/a00009.html @@ -0,0 +1,61 @@ + + +The Protothreads Library 1.4: lc-addrlabels.h File Reference + + + + + + +

lc-addrlabels.h File Reference


Detailed Description

+Implementation of local continuations based on the "Labels as values" feature of gcc. +

+

Author:
Adam Dunkels <adam@sics.se>
+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 +

+Definition in file lc-addrlabels.h. +

+ +

+Go to the source code of this file. + + + + + + + + + + + + + + + + + +

Defines

+#define LC_INIT(s)   s = NULL
+#define LC_RESUME(s)
+#define LC_CONCAT2(s1, s2)   s1##s2
+#define LC_CONCAT(s1, s2)   LC_CONCAT2(s1, s2)
+#define LC_SET(s)
+#define LC_END(s)

Typedefs

+typedef void * lc_t
+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00010.html b/doc/html/a00010.html new file mode 100644 index 0000000..4ba31de --- /dev/null +++ b/doc/html/a00010.html @@ -0,0 +1,56 @@ + + +The Protothreads Library 1.4: lc-switch.h File Reference + + + + + + +

lc-switch.h File Reference


Detailed Description

+Implementation of local continuations based on switch() statment. +

+

Author:
Adam Dunkels <adam@sics.se>
+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() statmenets.

+This implementation borrows heavily from Simon Tatham's coroutines implementation in C: http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html +

+Definition in file lc-switch.h. +

+ +

+Go to the source code of this file. + + + + + + + + + + + + + + +

Defines

+#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)   }

Typedefs

+typedef unsigned short lc_t
 The local continuation type.
+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00011.html b/doc/html/a00011.html new file mode 100644 index 0000000..b9bf8ac --- /dev/null +++ b/doc/html/a00011.html @@ -0,0 +1,51 @@ + + +The Protothreads Library 1.4: lc.h File Reference + + + + + + +

lc.h File Reference


Detailed Description

+Local continuations. +

+

Author:
Adam Dunkels <adam@sics.se>
+ +

+Definition in file lc.h. +

+#include "lc-switch.h"
+ +

+Go to the source code of this file. + + + + + + + + + + + + + + +

Defines

#define LC_INIT(lc)
 Initialize a local continuation.
#define LC_SET(lc)
 Set a local continuation.
#define LC_RESUME(lc)
 Resume a local continuation.
#define LC_END(lc)
 Mark the end of local continuation usage.
+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00012.html b/doc/html/a00012.html new file mode 100644 index 0000000..25054d5 --- /dev/null +++ b/doc/html/a00012.html @@ -0,0 +1,51 @@ + + +The Protothreads Library 1.4: pt-sem.h File Reference + + + + + + +

pt-sem.h File Reference


Detailed Description

+Couting semaphores implemented on protothreads. +

+

Author:
Adam Dunkels <adam@sics.se>
+ +

+Definition in file pt-sem.h. +

+#include "pt.h"
+ +

+Go to the source code of this file. + + + + + + + + + + + + + + +

Data Structures

struct  pt_sem

Defines

#define PT_SEM_INIT(s, c)
 Initialize a semaphore.
#define PT_SEM_WAIT(pt, s)
 Wait for a semaphore.
#define PT_SEM_SIGNAL(pt, s)
 Signal a semaphore.
+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00013.html b/doc/html/a00013.html new file mode 100644 index 0000000..76430ea --- /dev/null +++ b/doc/html/a00013.html @@ -0,0 +1,100 @@ + + +The Protothreads Library 1.4: pt.h File Reference + + + + + + +

pt.h File Reference


Detailed Description

+Protothreads implementation. +

+

Author:
Adam Dunkels <adam@sics.se>
+ +

+Definition in file pt.h. +

+#include "lc.h"
+ +

+Go to the source code of this file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Data Structures

struct  pt

Initialization

#define PT_INIT(pt)
 Initialize a protothread.

Declaration and definition

#define PT_THREAD(name_args)
 Declaration of a protothread.
#define PT_BEGIN(pt)
 Declare the start of a protothread inside the C function implementing the protothread.
#define PT_END(pt)
 Declare the end of a protothread.

Blocked wait

#define PT_WAIT_UNTIL(pt, condition)
 Block and wait until condition is true.
#define PT_WAIT_WHILE(pt, cond)
 Block and wait while condition is true.

Hierarchical protothreads

#define PT_WAIT_THREAD(pt, thread)
 Block and wait until a child protothread completes.
#define PT_SPAWN(pt, child, thread)
 Spawn a child protothread and wait until it exits.

Exiting and restarting

#define PT_RESTART(pt)
 Restart the protothread.
#define PT_EXIT(pt)
 Exit the protothread.

Calling a protothread

#define PT_SCHEDULE(f)
 Schedule a protothread.

Yielding from a protothread

#define PT_YIELD(pt)
 Yield from the current protothread.
#define PT_YIELD_UNTIL(pt, cond)
 Yield from the protothread until a condition occurs.

Defines

+#define PT_WAITING   0
+#define PT_YIELDED   1
+#define PT_EXITED   2
+#define PT_ENDED   3
+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00014.html b/doc/html/a00014.html new file mode 100644 index 0000000..424adc4 --- /dev/null +++ b/doc/html/a00014.html @@ -0,0 +1,627 @@ + + +The Protothreads Library 1.4: Protothreads + + + + + +

Protothreads


Detailed Description

+Protothreads are implemented in a single header file, pt.h, which includes the local continuations header file, lc.h. +

+This file in turn includes the actual implementation of local continuations, which typically also is contained in a single header file. +

+ + + + + + + +

+

+ + + + +

+

+ + + +

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Files

file  pt.h
 Protothreads implementation.

Modules

 Protothread semaphores
 This module implements counting semaphores on top of protothreads.
 Local continuations
 Local continuations form the basis for implementing protothreads.

Data Structures

struct  pt

Initialization

#define PT_INIT(pt)
 Initialize a protothread.

Declaration and definition

#define PT_THREAD(name_args)
 Declaration of a protothread.
#define PT_BEGIN(pt)
 Declare the start of a protothread inside the C function implementing the protothread.
#define PT_END(pt)
 Declare the end of a protothread.

Blocked wait

#define PT_WAIT_UNTIL(pt, condition)
 Block and wait until condition is true.
#define PT_WAIT_WHILE(pt, cond)
 Block and wait while condition is true.

Hierarchical protothreads

#define PT_WAIT_THREAD(pt, thread)
 Block and wait until a child protothread completes.
#define PT_SPAWN(pt, child, thread)
 Spawn a child protothread and wait until it exits.

Exiting and restarting

#define PT_RESTART(pt)
 Restart the protothread.
#define PT_EXIT(pt)
 Exit the protothread.

Calling a protothread

#define PT_SCHEDULE(f)
 Schedule a protothread.

Yielding from a protothread

#define PT_YIELD(pt)
 Yield from the current protothread.
#define PT_YIELD_UNTIL(pt, cond)
 Yield from the protothread until a condition occurs.

Defines

+#define PT_WAITING   0
+#define PT_YIELDED   1
+#define PT_EXITED   2
+#define PT_ENDED   3
+


Define Documentation

+

+ + + + +
+ + + + + + + + + +
#define PT_BEGIN pt   ) 
+
+ + + + + +
+   + + +

+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.

+

Parameters:
+ + +
pt A pointer to the protothread control structure.
+
+ +

+Definition at line 115 of file pt.h.

+

+ + + + +
+ + + + + + + + + +
#define PT_END pt   ) 
+
+ + + + + +
+   + + +

+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.

+

Parameters:
+ + +
pt A pointer to the protothread control structure.
+
+ +

+Definition at line 127 of file pt.h.

+

+ + + + +
+ + + + + + + + + +
#define PT_EXIT pt   ) 
+
+ + + + + +
+   + + +

+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.

+

Parameters:
+ + +
pt A pointer to the protothread control structure.
+
+ +

+Definition at line 246 of file pt.h.

+

+ + + + +
+ + + + + + + + + +
#define PT_INIT pt   ) 
+
+ + + + + +
+   + + +

+Initialize a protothread. +

+Initializes a protothread. Initialization must be done prior to starting to execute the protothread.

+

Parameters:
+ + +
pt A pointer to the protothread control structure.
+
+
See also:
PT_SPAWN()
+ +

+Definition at line 80 of file pt.h.

+

+ + + + +
+ + + + + + + + + +
#define PT_RESTART pt   ) 
+
+ + + + + +
+   + + +

+Restart the protothread. +

+This macro will block and cause the running protothread to restart its execution at the place of the PT_BEGIN() call.

+

Parameters:
+ + +
pt A pointer to the protothread control structure.
+
+ +

+Definition at line 229 of file pt.h.

+

+ + + + +
+ + + + + + + + + +
#define PT_SCHEDULE  ) 
+
+ + + + + +
+   + + +

+Schedule a protothread. +

+This function shedules a protothread. The return value of the function is non-zero if the protothread is running or zero if the protothread has exited.

+

Parameters:
+ + +
f The call to the C function implementing the protothread to be scheduled
+
+ +

+Definition at line 271 of file pt.h.

+

+ + + + +
+ + + + + + + + + + + + + + + +
#define PT_SPAWN pt,
child,
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.

+

Parameters:
+ + + + +
pt A pointer to the protothread control structure.
child A pointer to the child protothread's control structure.
thread The child protothread with arguments
+
+ +

+Definition at line 206 of file pt.h.

+

+ + + + +
+ + + + + + + + + +
#define PT_THREAD name_args   ) 
+
+ + + + + +
+   + + +

+Declaration of a protothread. +

+This macro is used to declare a protothread. All protothreads must be declared with this macro.

+

Parameters:
+ + +
name_args The name and arguments of the C function implementing the protothread.
+
+ +

+Definition at line 100 of file pt.h.

+

+ + + + +
+ + + + + + + + + + + + +
#define PT_WAIT_THREAD pt,
thread   ) 
+
+ + + + + +
+   + + +

+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.
+
Parameters:
+ + + +
pt A pointer to the protothread control structure.
thread The child protothread with arguments
+
+
See also:
PT_SPAWN()
+ +

+Definition at line 192 of file pt.h.

+

+ + + + +
+ + + + + + + + + + + + +
#define PT_WAIT_UNTIL pt,
condition   ) 
+
+ + + + + +
+   + + +

+Block and wait until condition is true. +

+This macro blocks the protothread until the specified condition is true.

+

Parameters:
+ + + +
pt A pointer to the protothread control structure.
condition The condition.
+
+ +

+Definition at line 148 of file pt.h.

+

+ + + + +
+ + + + + + + + + + + + +
#define PT_WAIT_WHILE pt,
cond   ) 
+
+ + + + + +
+   + + +

+Block and wait while condition is true. +

+This function blocks and waits while condition is true. See PT_WAIT_UNTIL().

+

Parameters:
+ + + +
pt A pointer to the protothread control structure.
cond The condition.
+
+ +

+Definition at line 167 of file pt.h.

+

+ + + + +
+ + + + + + + + + +
#define PT_YIELD pt   ) 
+
+ + + + + +
+   + + +

+Yield from the current protothread. +

+This function will yield the protothread, thereby allowing other processing to take place in the system.

+

Parameters:
+ + +
pt A pointer to the protothread control structure.
+
+ +

+Definition at line 290 of file pt.h.

+

+ + + + +
+ + + + + + + + + + + + +
#define PT_YIELD_UNTIL pt,
cond   ) 
+
+ + + + + +
+   + + +

+Yield from the protothread until a condition occurs. +

+

Parameters:
+ + + +
pt A pointer to the protothread control structure.
cond The condition.
+
+This function will yield the protothread, until the specified condition evaluates to true. +

+Definition at line 310 of file pt.h.

+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00015.html b/doc/html/a00015.html new file mode 100644 index 0000000..1a0d69a --- /dev/null +++ b/doc/html/a00015.html @@ -0,0 +1,711 @@ + + +The Protothreads Library 1.4: Examples + + + + + +

Examples

+A small example

+This first example shows a very simple program: two protothreads waiting for each other to toggle two flags. The code illustrates how to write protothreads code, how to initialize protothreads, and how to schedule them.

+

/**
+ * This is a very small example that shows how to use
+ * protothreads. The program consists of two protothreads that wait
+ * for each other to toggle a variable.
+ */
+
+/* We must always include pt.h in our protothreads code. */
+#include "pt.h"
+
+#include <stdio.h> /* For printf(). */
+
+/* Two flags that the two protothread functions use. */
+static int protothread1_flag, protothread2_flag;
+
+/**
+ * The first protothread function. A protothread function must always
+ * return an integer, but must never explicitly return - returning is
+ * performed inside the protothread statements.
+ *
+ * The protothread function is driven by the main loop further down in
+ * the code.
+ */
+static int
+protothread1(struct pt *pt)
+{
+  /* A protothread function must begin with PT_BEGIN() which takes a
+     pointer to a struct pt. */
+  PT_BEGIN(pt);
+
+  /* We loop forever here. */
+  while(1) {
+    /* Wait until the other protothread has set its flag. */
+    PT_WAIT_UNTIL(pt, protothread2_flag != 0);
+    printf("Protothread 1 running\n");
+
+    /* We then reset the other protothread's flag, and set our own
+       flag so that the other protothread can run. */
+    protothread2_flag = 0;
+    protothread1_flag = 1;
+
+    /* And we loop. */
+  }
+
+  /* All protothread functions must end with PT_END() which takes a
+     pointer to a struct pt. */
+  PT_END(pt);
+}
+
+/**
+ * The second protothread function. This is almost the same as the
+ * first one.
+ */
+static int
+protothread2(struct pt *pt)
+{
+  PT_BEGIN(pt);
+
+  while(1) {
+    /* Let the other protothread run. */
+    protothread2_flag = 1;
+
+    /* Wait until the other protothread has set its flag. */
+    PT_WAIT_UNTIL(pt, protothread1_flag != 0);
+    printf("Protothread 2 running\n");
+    
+    /* We then reset the other protothread's flag. */
+    protothread1_flag = 0;
+
+    /* And we loop. */
+  }
+  PT_END(pt);
+}
+
+/**
+ * Finally, we have the main loop. Here is where the protothreads are
+ * initialized and scheduled. First, however, we define the
+ * protothread state variables pt1 and pt2, which hold the state of
+ * the two protothreads.
+ */
+static struct pt pt1, pt2;
+int
+main(void)
+{
+  /* Initialize the protothread state variables with PT_INIT(). */
+  PT_INIT(&pt1);
+  PT_INIT(&pt2);
+  
+  /*
+   * Then we schedule the two protothreads by repeatedly calling their
+   * protothread functions and passing a pointer to the protothread
+   * state variables as arguments.
+   */
+  while(1) {
+    protothread1(&pt1);
+    protothread2(&pt2);
+  }
+}
+

+A code-lock

+This example shows how to implement a simple code lock - the kind of device that is placed next to doors and that you have to push a four digit number into in order to unlock the door.

+The code lock waits for key presses from a numeric keyboard and if the correct code is entered, the lock is unlocked. There is a maximum time of one second between each key press, and after the correct code has been entered, no more keys must be pressed for 0.5 seconds before the lock is opened.

+

/*
+ * 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 protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: example-codelock.c,v 1.5 2005/10/06 07:57:08 adam Exp $
+ */
+
+/*
+ *
+ * This example shows how to implement a simple code lock. The code
+ * lock waits for key presses from a numeric keyboard and if the
+ * correct code is entered, the lock is unlocked. There is a maximum
+ * time of one second between each key press, and after the correct
+ * code has been entered, no more keys must be pressed for 0.5 seconds
+ * before the lock is opened.
+ *
+ * This is an example that shows two things:
+ * - how to implement a code lock key input mechanism, and
+ * - how to implement a sequential timed routine.
+ *
+ * The program consists of two protothreads, one that implements the
+ * code lock reader and one that implements simulated keyboard input.
+ *
+ *
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+#include <stdio.h>
+
+#include "pt.h"
+
+/*---------------------------------------------------------------------------*/
+/*
+ * The following definitions are just for the simple timer library
+ * used in this example. The actual implementation of the functions
+ * can be found at the end of this file.
+ */
+struct timer { int start, interval; };
+static int  timer_expired(struct timer *t);
+static void timer_set(struct timer *t, int usecs);
+/*---------------------------------------------------------------------------*/
+/*
+ * This example uses two timers: one for the code lock protothread and
+ * one for the simulated key input protothread.
+ */
+static struct timer codelock_timer, input_timer;
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the code that has to be entered.
+ */
+static const char code[4] = {'1', '4', '2', '3'};
+/*---------------------------------------------------------------------------*/
+/*
+ * This example has two protothread and therefor has two protothread
+ * control structures of type struct pt. These are initialized with
+ * PT_INIT() in the main() function below.
+ */
+static struct pt codelock_pt, input_pt;
+/*---------------------------------------------------------------------------*/
+/*
+ * The following code implements a simple key input. Input is made
+ * with the press_key() function, and the function key_pressed()
+ * checks if a key has been pressed. The variable "key" holds the
+ * latest key that was pressed. The variable "key_pressed_flag" is set
+ * when a key is pressed and cleared when a key press is checked.
+ */
+static char key, key_pressed_flag;
+
+static void
+press_key(char k)
+{
+  printf("--- Key '%c' pressed\n", k);
+  key = k;
+  key_pressed_flag = 1;
+}
+
+static int
+key_pressed(void)
+{
+  if(key_pressed_flag != 0) {
+    key_pressed_flag = 0;
+    return 1;
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * Declaration of the protothread function implementing the code lock
+ * logic. The protothread function is declared using the PT_THREAD()
+ * macro. The function is declared with the "static" keyword since it
+ * is local to this file. The name of the function is codelock_thread
+ * and it takes one argument, pt, of the type struct pt.
+ *
+ */
+static
+PT_THREAD(codelock_thread(struct pt *pt))
+{
+  /* This is a local variable that holds the number of keys that have
+   * been pressed. Note that it is declared with the "static" keyword
+   * to make sure that the variable is *not* allocated on the stack.
+   */
+  static int keys;
+
+  /*
+   * Declare the beginning of the protothread.
+   */
+  PT_BEGIN(pt);
+
+  /*
+   * We'll let the protothread loop until the protothread is
+   * expliticly exited with PT_EXIT().
+   */
+  while(1) {
+
+    /*
+     * We'll be reading key presses until we get the right amount of
+     * correct keys.
+     */ 
+    for(keys = 0; keys < sizeof(code); ++keys) {
+
+      /*
+       * If we haven't gotten any keypresses, we'll simply wait for one.
+       */
+      if(keys == 0) {
+
+        /*
+         * The PT_WAIT_UNTIL() function will block until the condition
+         * key_pressed() is true.
+         */
+        PT_WAIT_UNTIL(pt, key_pressed());
+      } else {
+        
+        /*
+         * If the "key" variable was larger than zero, we have already
+         * gotten at least one correct key press. If so, we'll not
+         * only wait for the next key, but we'll also set a timer that
+         * expires in one second. This gives the person pressing the
+         * keys one second to press the next key in the code.
+         */
+        timer_set(&codelock_timer, 1000);
+
+        /*
+         * The following statement shows how complex blocking
+         * conditions can be easily expressed with protothreads and
+         * the PT_WAIT_UNTIL() function.
+         */
+        PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer));
+
+        /*
+         * If the timer expired, we should break out of the for() loop
+         * and start reading keys from the beginning of the while(1)
+         * loop instead.
+         */
+        if(timer_expired(&codelock_timer)) {
+          printf("Code lock timer expired.\n");
+          
+          /*
+           * Break out from the for() loop and start from the
+           * beginning of the while(1) loop.
+           */
+          break;
+        }
+      }
+
+      /*
+       * Check if the pressed key was correct.
+       */
+      if(key != code[keys]) {
+        printf("Incorrect key '%c' found\n", key);
+        /*
+         * Break out of the for() loop since the key was incorrect.
+         */
+        break;
+      } else {
+        printf("Correct key '%c' found\n", key);
+      }
+    }
+
+    /*
+     * Check if we have gotten all keys.
+     */
+    if(keys == sizeof(code)) {
+      printf("Correct code entered, waiting for 500 ms before unlocking.\n");
+
+      /*
+       * Ok, we got the correct code. But to make sure that the code
+       * was not just a fluke of luck by an intruder, but the correct
+       * code entered by a person that knows the correct code, we'll
+       * wait for half a second before opening the lock. If another
+       * key is pressed during this time, we'll assume that it was a
+       * fluke of luck that the correct code was entered the first
+       * time.
+       */
+      timer_set(&codelock_timer, 500);      
+      PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer));
+
+      /*
+       * If we continued from the PT_WAIT_UNTIL() statement without
+       * the timer expired, we don't open the lock.
+       */
+      if(!timer_expired(&codelock_timer)) {
+        printf("Key pressed during final wait, code lock locked again.\n");
+      } else {
+
+        /*
+         * If the timer expired, we'll open the lock and exit from the
+         * protothread.
+         */
+        printf("Code lock unlocked.\n");
+        PT_EXIT(pt);
+      }
+    }
+  }
+
+  /*
+   * Finally, we'll mark the end of the protothread.
+   */
+  PT_END(pt);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the second protothread in this example. It implements a
+ * simulated user pressing the keys. This illustrates how a linear
+ * sequence of timed instructions can be implemented with
+ * protothreads.
+ */
+static
+PT_THREAD(input_thread(struct pt *pt))
+{
+  PT_BEGIN(pt);
+
+  printf("Waiting 1 second before entering first key.\n");
+  
+  timer_set(&input_timer, 1000);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+
+  press_key('1');
+  
+  timer_set(&input_timer, 100);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('2');
+
+  timer_set(&input_timer, 100);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('3');
+
+  timer_set(&input_timer, 2000);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('1');
+
+  timer_set(&input_timer, 200);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('4');
+
+  timer_set(&input_timer, 200);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('2');
+  
+  timer_set(&input_timer, 2000);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('3');
+
+  timer_set(&input_timer, 200);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('1');
+
+  timer_set(&input_timer, 200);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('4');
+
+  timer_set(&input_timer, 200);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('2');
+  
+  timer_set(&input_timer, 100);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('3');
+
+  timer_set(&input_timer, 100);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('4');
+
+  timer_set(&input_timer, 1500);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('1');
+
+  timer_set(&input_timer, 300);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('4');
+
+  timer_set(&input_timer, 400);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('2');
+
+  timer_set(&input_timer, 500);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  press_key('3');
+
+  timer_set(&input_timer, 2000);
+  PT_WAIT_UNTIL(pt, timer_expired(&input_timer));
+  
+  PT_END(pt);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * This is the main function. It initializes the two protothread
+ * control structures and schedules the two protothreads. The main
+ * function returns when the protothread the runs the code lock exits.
+ */
+int
+main(void)
+{
+  /*
+   * Initialize the two protothread control structures.
+   */
+  PT_INIT(&input_pt);
+  PT_INIT(&codelock_pt);
+
+  /*
+   * Schedule the two protothreads until the codelock_thread() exits.
+   */
+  while(PT_SCHEDULE(codelock_thread(&codelock_pt))) {
+    PT_SCHEDULE(input_thread(&input_pt));
+    
+    /*
+     * When running this example on a multitasking system, we must
+     * give other processes a chance to run too and therefore we call
+     * usleep() resp. Sleep() here. On a dedicated embedded system,
+     * we usually do not need to do this.
+     */
+#ifdef _WIN32
+    Sleep(0);
+#else
+    usleep(10);
+#endif
+  }
+
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * Finally, the implementation of the simple timer library follows.
+ */
+#ifdef _WIN32
+
+static int clock_time(void)
+{ return (int)GetTickCount(); }
+
+#else /* _WIN32 */
+
+static int clock_time(void)
+{
+  struct timeval tv;
+  struct timezone tz;   
+  gettimeofday(&tv, &tz); 
+  return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+#endif /* _WIN32 */
+
+static int timer_expired(struct timer *t)
+{ return (int)(clock_time() - t->start) >= (int)t->interval; }
+
+static void timer_set(struct timer *t, int interval)
+{ t->interval = interval; t->start = clock_time(); }
+/*---------------------------------------------------------------------------*/
+

+The bounded buffer with protothread semaphores

+The following example shows how to implement the bounded buffer problem using the protothreads semaphore library. The example uses three protothreads: one producer() protothread that produces items, one consumer() protothread that consumes items, and one driver_thread() that schedules the producer and consumer protothreads.

+Note that there is no need for a mutex to guard the add_to_buffer() and get_from_buffer() functions because of the implicit locking semantics of protothreads - a protothread will never be preempted and will never block except in an explicit PT_WAIT statement.

+

/*
+ * 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 protothreads library.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $Id: example-buffer.c,v 1.5 2005/10/07 05:21:33 adam Exp $
+ */
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+#include <stdio.h>
+
+#include "pt-sem.h"
+ 
+#define NUM_ITEMS 32
+#define BUFSIZE 8
+
+static int buffer[BUFSIZE];
+static int bufptr;
+
+static void
+add_to_buffer(int item)
+{
+  printf("Item %d added to buffer at place %d\n", item, bufptr);  
+  buffer[bufptr] = item;
+  bufptr = (bufptr + 1) % BUFSIZE;
+}
+static int
+get_from_buffer(void)
+{
+  int item;
+  item = buffer[bufptr];
+  printf("Item %d retrieved from buffer at place %d\n",
+         item, bufptr);
+  bufptr = (bufptr + 1) % BUFSIZE;
+  return item;
+}
+
+static int
+produce_item(void)
+{
+  static int item = 0;
+  printf("Item %d produced\n", item);
+  return item++;
+}
+
+static void
+consume_item(int item)
+{
+  printf("Item %d consumed\n", item);
+}
+
+static struct pt_sem full, empty;
+ 
+static 
+PT_THREAD(producer(struct pt *pt))
+{
+  static int produced;
+  
+  PT_BEGIN(pt);
+  
+  for(produced = 0; produced < NUM_ITEMS; ++produced) {
+  
+    PT_SEM_WAIT(pt, &full);
+    
+    add_to_buffer(produce_item());
+    
+    PT_SEM_SIGNAL(pt, &empty);
+  }
+
+  PT_END(pt);
+}
+ 
+static 
+PT_THREAD(consumer(struct pt *pt))
+{
+  static int consumed;
+  
+  PT_BEGIN(pt);
+ 
+  for(consumed = 0; consumed < NUM_ITEMS; ++consumed) {
+    
+    PT_SEM_WAIT(pt, &empty);
+    
+    consume_item(get_from_buffer());    
+    
+    PT_SEM_SIGNAL(pt, &full);
+  }
+ 
+  PT_END(pt);
+}
+ 
+static 
+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_INIT(&pt_producer);
+  PT_INIT(&pt_consumer);
+ 
+  PT_WAIT_THREAD(pt, producer(&pt_producer) &
+                     consumer(&pt_consumer));
+ 
+  PT_END(pt);
+}
+
+
+int
+main(void)
+{
+  struct pt driver_pt;
+
+  PT_INIT(&driver_pt);
+
+  while(PT_SCHEDULE(driver_thread(&driver_pt))) {
+
+    /*
+     * When running this example on a multitasking system, we must
+     * give other processes a chance to run too and therefore we call
+     * usleep() resp. Sleep() here. On a dedicated embedded system,
+     * we usually do not need to do this.
+     */
+#ifdef _WIN32
+    Sleep(0);
+#else
+    usleep(10);
+#endif
+  }
+  return 0;
+}
+
+

+ + +
+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00016.html b/doc/html/a00016.html new file mode 100644 index 0000000..743f2bd --- /dev/null +++ b/doc/html/a00016.html @@ -0,0 +1,246 @@ + + +The Protothreads Library 1.4: Protothread semaphores + + + + + +

Protothread semaphores
+ +[Protothreads] +


Detailed Description

+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 signalled, 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.

+

#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);
+}
+

+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. +

+ + + + + + + +

+

+ + + + + + + + + + + + +

Files

file  pt-sem.h
 Couting semaphores implemented on protothreads.

Data Structures

struct  pt_sem

Defines

#define PT_SEM_INIT(s, c)
 Initialize a semaphore.
#define PT_SEM_WAIT(pt, s)
 Wait for a semaphore.
#define PT_SEM_SIGNAL(pt, s)
 Signal a semaphore.
+


Define Documentation

+

+ + + + +
+ + + + + + + + + + + + +
#define PT_SEM_INIT s,
 ) 
+
+ + + + + +
+   + + +

+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.

+

Parameters:
+ + + +
s (struct pt_sem *) A pointer to the pt_sem struct representing the semaphore
c (unsigned int) The initial count of the semaphore.
+
+ +

+Definition at line 183 of file pt-sem.h.

+

+ + + + +
+ + + + + + + + + + + + +
#define PT_SEM_SIGNAL pt,
 ) 
+
+ + + + + +
+   + + +

+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.

+

Parameters:
+ + + +
pt (struct pt *) A pointer to the protothread (struct pt) in which the operation is executed.
s (struct pt_sem *) A pointer to the pt_sem struct representing the semaphore
+
+ +

+Definition at line 222 of file pt-sem.h.

+

+ + + + +
+ + + + + + + + + + + + +
#define PT_SEM_WAIT pt,
 ) 
+
+ + + + + +
+   + + +

+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.

+

Parameters:
+ + + +
pt (struct pt *) A pointer to the protothread (struct pt) in which the operation is executed.
s (struct pt_sem *) A pointer to the pt_sem struct representing the semaphore
+
+ +

+Definition at line 201 of file pt-sem.h.

+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00017.html b/doc/html/a00017.html new file mode 100644 index 0000000..9a37968 --- /dev/null +++ b/doc/html/a00017.html @@ -0,0 +1,226 @@ + + +The Protothreads Library 1.4: Local continuations + + + + + +

Local continuations
+ +[Protothreads] +


Detailed Description

+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. +

+ + + + + + + +

+

+ + + +

+

+ + + +

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Files

file  lc.h
 Local continuations.
file  lc-switch.h
 Implementation of local continuations based on switch() statment.
file  lc-addrlabels.h
 Implementation of local continuations based on the "Labels as values" feature of gcc.

Defines

#define LC_INIT(lc)
 Initialize a local continuation.
#define LC_SET(lc)
 Set a local continuation.
#define LC_RESUME(lc)
 Resume a local continuation.
#define LC_END(lc)
 Mark the end of local continuation usage.
+#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)   }
+#define LC_INIT(s)   s = NULL
+#define LC_RESUME(s)
+#define LC_CONCAT2(s1, s2)   s1##s2
+#define LC_CONCAT(s1, s2)   LC_CONCAT2(s1, s2)
+#define LC_SET(s)
+#define LC_END(s)

Typedefs

+typedef unsigned short lc_t
 The local continuation type.
+typedef void * lc_t
+


Define Documentation

+

+ + + + +
+ + + + + + + + + +
#define LC_END 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. +

+Definition at line 108 of file lc.h.

+

+ + + + +
+ + + + + + + + + +
#define LC_INIT lc   ) 
+
+ + + + + +
+   + + +

+Initialize a local continuation. +

+This operation initializes the local continuation, thereby unsetting any previously set continuation state. +

+Definition at line 71 of file lc.h.

+

+ + + + +
+ + + + + + + + + +
#define LC_RESUME 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. +

+Definition at line 96 of file lc.h.

+

+ + + + +
+ + + + + + + + + +
#define LC_SET 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. +

+Definition at line 84 of file lc.h.

+


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00018.html b/doc/html/a00018.html new file mode 100644 index 0000000..8f20cba --- /dev/null +++ b/doc/html/a00018.html @@ -0,0 +1,109 @@ + + +The Protothreads Library 1.4: lc-addrlabels.h Source File + + + + + + +

lc-addrlabels.h

Go to the documentation of this file.
00001 /*
+00002  * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+00003  * All rights reserved.
+00004  *
+00005  * Redistribution and use in source and binary forms, with or without
+00006  * modification, are permitted provided that the following conditions
+00007  * are met:
+00008  * 1. Redistributions of source code must retain the above copyright
+00009  *    notice, this list of conditions and the following disclaimer.
+00010  * 2. Redistributions in binary form must reproduce the above copyright
+00011  *    notice, this list of conditions and the following disclaimer in the
+00012  *    documentation and/or other materials provided with the distribution.
+00013  * 3. Neither the name of the Institute nor the names of its contributors
+00014  *    may be used to endorse or promote products derived from this software
+00015  *    without specific prior written permission.
+00016  *
+00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+00027  * SUCH DAMAGE.
+00028  *
+00029  * This file is part of the Contiki operating system.
+00030  *
+00031  * Author: Adam Dunkels <adam@sics.se>
+00032  *
+00033  * $Id: lc-addrlabels.h,v 1.4 2006/06/03 11:29:43 adam Exp $
+00034  */
+00035 
+00036 /**
+00037  * \addtogroup lc
+00038  * @{
+00039  */
+00040 
+00041 /**
+00042  * \file
+00043  * Implementation of local continuations based on the "Labels as
+00044  * values" feature of gcc
+00045  * \author
+00046  * Adam Dunkels <adam@sics.se>
+00047  *
+00048  * This implementation of local continuations is based on a special
+00049  * feature of the GCC C compiler called "labels as values". This
+00050  * feature allows assigning pointers with the address of the code
+00051  * corresponding to a particular C label.
+00052  *
+00053  * For more information, see the GCC documentation:
+00054  * http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
+00055  *
+00056  */
+00057 
+00058 #ifndef __LC_ADDRLABELS_H__
+00059 #define __LC_ADDRLABELS_H__
+00060 
+00061 /** \hideinitializer */
+00062 typedef void * lc_t;
+00063 
+00064 #define LC_INIT(s) s = NULL
+00065 
+00066 #define LC_RESUME(s)                            \
+00067   do {                                          \
+00068     if(s != NULL) {                             \
+00069       goto *s;                                  \
+00070     }                                           \
+00071   } while(0)
+00072 
+00073 #define LC_CONCAT2(s1, s2) s1##s2
+00074 #define LC_CONCAT(s1, s2) LC_CONCAT2(s1, s2)
+00075 
+00076 #define LC_SET(s)                               \
+00077   do {                                          \
+00078     LC_CONCAT(LC_LABEL, __LINE__):              \
+00079     (s) = &&LC_CONCAT(LC_LABEL, __LINE__);      \
+00080   } while(0)
+00081 
+00082 #define LC_END(s)
+00083 
+00084 #endif /* __LC_ADDRLABELS_H__ */
+00085 /** @} */
+

Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00019.html b/doc/html/a00019.html new file mode 100644 index 0000000..a443882 --- /dev/null +++ b/doc/html/a00019.html @@ -0,0 +1,100 @@ + + +The Protothreads Library 1.4: lc-switch.h Source File + + + + + + +

lc-switch.h

Go to the documentation of this file.
00001 /*
+00002  * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+00003  * All rights reserved.
+00004  *
+00005  * Redistribution and use in source and binary forms, with or without
+00006  * modification, are permitted provided that the following conditions
+00007  * are met:
+00008  * 1. Redistributions of source code must retain the above copyright
+00009  *    notice, this list of conditions and the following disclaimer.
+00010  * 2. Redistributions in binary form must reproduce the above copyright
+00011  *    notice, this list of conditions and the following disclaimer in the
+00012  *    documentation and/or other materials provided with the distribution.
+00013  * 3. Neither the name of the Institute nor the names of its contributors
+00014  *    may be used to endorse or promote products derived from this software
+00015  *    without specific prior written permission.
+00016  *
+00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+00027  * SUCH DAMAGE.
+00028  *
+00029  * This file is part of the Contiki operating system.
+00030  *
+00031  * Author: Adam Dunkels <adam@sics.se>
+00032  *
+00033  * $Id: lc-switch.h,v 1.4 2006/06/03 11:29:43 adam Exp $
+00034  */
+00035 
+00036 /**
+00037  * \addtogroup lc
+00038  * @{
+00039  */
+00040 
+00041 /**
+00042  * \file
+00043  * Implementation of local continuations based on switch() statment
+00044  * \author Adam Dunkels <adam@sics.se>
+00045  *
+00046  * This implementation of local continuations uses the C switch()
+00047  * statement to resume execution of a function somewhere inside the
+00048  * function's body. The implementation is based on the fact that
+00049  * switch() statements are able to jump directly into the bodies of
+00050  * control structures such as if() or while() statmenets.
+00051  *
+00052  * This implementation borrows heavily from Simon Tatham's coroutines
+00053  * implementation in C:
+00054  * http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
+00055  */
+00056 
+00057 #ifndef __LC_SWITCH_H__
+00058 #define __LC_SWITCH_H__
+00059 
+00060 /* WARNING! lc implementation using switch() does not work if an
+00061    LC_SET() is done within another switch() statement! */
+00062 
+00063 /** \hideinitializer */
+00064 typedef unsigned short lc_t;
+00065 
+00066 #define LC_INIT(s) s = 0;
+00067 
+00068 #define LC_RESUME(s) switch(s) { case 0:
+00069 
+00070 #define LC_SET(s) s = __LINE__; case __LINE__:
+00071 
+00072 #define LC_END(s) }
+00073 
+00074 #endif /* __LC_SWITCH_H__ */
+00075 
+00076 /** @} */
+

Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00020.html b/doc/html/a00020.html new file mode 100644 index 0000000..0381a4c --- /dev/null +++ b/doc/html/a00020.html @@ -0,0 +1,156 @@ + + +The Protothreads Library 1.4: lc.h Source File + + + + + + +

lc.h

Go to the documentation of this file.
00001 /*
+00002  * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+00003  * All rights reserved. 
+00004  *
+00005  * Redistribution and use in source and binary forms, with or without 
+00006  * modification, are permitted provided that the following conditions 
+00007  * are met: 
+00008  * 1. Redistributions of source code must retain the above copyright 
+00009  *    notice, this list of conditions and the following disclaimer. 
+00010  * 2. Redistributions in binary form must reproduce the above copyright 
+00011  *    notice, this list of conditions and the following disclaimer in the 
+00012  *    documentation and/or other materials provided with the distribution. 
+00013  * 3. Neither the name of the Institute nor the names of its contributors 
+00014  *    may be used to endorse or promote products derived from this software 
+00015  *    without specific prior written permission. 
+00016  *
+00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+00027  * SUCH DAMAGE. 
+00028  *
+00029  * This file is part of the protothreads library.
+00030  * 
+00031  * Author: Adam Dunkels <adam@sics.se>
+00032  *
+00033  * $Id: lc.h,v 1.2 2005/02/24 10:36:59 adam Exp $
+00034  */
+00035 
+00036 /**
+00037  * \addtogroup pt
+00038  * @{
+00039  */
+00040 
+00041 /**
+00042  * \defgroup lc Local continuations
+00043  * @{
+00044  *
+00045  * Local continuations form the basis for implementing protothreads. A
+00046  * local continuation can be <i>set</i> in a specific function to
+00047  * capture the state of the function. After a local continuation has
+00048  * been set can be <i>resumed</i> in order to restore the state of the
+00049  * function at the point where the local continuation was set.
+00050  *
+00051  *
+00052  */
+00053 
+00054 /**
+00055  * \file lc.h
+00056  * Local continuations
+00057  * \author
+00058  * Adam Dunkels <adam@sics.se>
+00059  *
+00060  */
+00061 
+00062 #ifdef DOXYGEN
+00063 /**
+00064  * Initialize a local continuation.
+00065  *
+00066  * This operation initializes the local continuation, thereby
+00067  * unsetting any previously set continuation state.
+00068  *
+00069  * \hideinitializer
+00070  */
+00071 #define LC_INIT(lc)
+00072 
+00073 /**
+00074  * Set a local continuation.
+00075  *
+00076  * The set operation saves the state of the function at the point
+00077  * where the operation is executed. As far as the set operation is
+00078  * concerned, the state of the function does <b>not</b> include the
+00079  * call-stack or local (automatic) variables, but only the program
+00080  * counter and such CPU registers that needs to be saved.
+00081  *
+00082  * \hideinitializer
+00083  */
+00084 #define LC_SET(lc)
+00085 
+00086 /**
+00087  * Resume a local continuation.
+00088  *
+00089  * The resume operation resumes a previously set local continuation, thus
+00090  * restoring the state in which the function was when the local
+00091  * continuation was set. If the local continuation has not been
+00092  * previously set, the resume operation does nothing.
+00093  *
+00094  * \hideinitializer
+00095  */
+00096 #define LC_RESUME(lc)
+00097 
+00098 /**
+00099  * Mark the end of local continuation usage.
+00100  *
+00101  * The end operation signifies that local continuations should not be
+00102  * used any more in the function. This operation is not needed for
+00103  * most implementations of local continuation, but is required by a
+00104  * few implementations.
+00105  *
+00106  * \hideinitializer 
+00107  */
+00108 #define LC_END(lc)
+00109 
+00110 /**
+00111  * \var typedef lc_t;
+00112  *
+00113  * The local continuation type.
+00114  *
+00115  * \hideinitializer
+00116  */
+00117 #endif /* DOXYGEN */
+00118 
+00119 #ifndef __LC_H__
+00120 #define __LC_H__
+00121 
+00122 
+00123 #ifdef LC_INCLUDE
+00124 #include LC_INCLUDE
+00125 #else
+00126 #include "lc-switch.h"
+00127 #endif /* LC_INCLUDE */
+00128 
+00129 #endif /* __LC_H__ */
+00130 
+00131 /** @} */
+00132 /** @} */
+

Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00021.html b/doc/html/a00021.html new file mode 100644 index 0000000..1c4f116 --- /dev/null +++ b/doc/html/a00021.html @@ -0,0 +1,252 @@ + + +The Protothreads Library 1.4: pt-sem.h Source File + + + + + + +

pt-sem.h

Go to the documentation of this file.
00001 /*
+00002  * Copyright (c) 2004, Swedish Institute of Computer Science.
+00003  * All rights reserved. 
+00004  *
+00005  * Redistribution and use in source and binary forms, with or without 
+00006  * modification, are permitted provided that the following conditions 
+00007  * are met: 
+00008  * 1. Redistributions of source code must retain the above copyright 
+00009  *    notice, this list of conditions and the following disclaimer. 
+00010  * 2. Redistributions in binary form must reproduce the above copyright 
+00011  *    notice, this list of conditions and the following disclaimer in the 
+00012  *    documentation and/or other materials provided with the distribution. 
+00013  * 3. Neither the name of the Institute nor the names of its contributors 
+00014  *    may be used to endorse or promote products derived from this software 
+00015  *    without specific prior written permission. 
+00016  *
+00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+00027  * SUCH DAMAGE. 
+00028  *
+00029  * This file is part of the protothreads library.
+00030  * 
+00031  * Author: Adam Dunkels <adam@sics.se>
+00032  *
+00033  * $Id: pt-sem.h,v 1.2 2005/02/24 10:36:59 adam Exp $
+00034  */
+00035 
+00036 /**
+00037  * \addtogroup pt
+00038  * @{
+00039  */
+00040 
+00041 /**
+00042  * \defgroup ptsem Protothread semaphores
+00043  * @{
+00044  *
+00045  * This module implements counting semaphores on top of
+00046  * protothreads. Semaphores are a synchronization primitive that
+00047  * provide two operations: "wait" and "signal". The "wait" operation
+00048  * checks the semaphore counter and blocks the thread if the counter
+00049  * is zero. The "signal" operation increases the semaphore counter but
+00050  * does not block. If another thread has blocked waiting for the
+00051  * semaphore that is signalled, the blocked thread will become
+00052  * runnable again.
+00053  *
+00054  * Semaphores can be used to implement other, more structured,
+00055  * synchronization primitives such as monitors and message
+00056  * queues/bounded buffers (see below).
+00057  *
+00058  * The following example shows how the producer-consumer problem, also
+00059  * known as the bounded buffer problem, can be solved using
+00060  * protothreads and semaphores. Notes on the program follow after the
+00061  * example.
+00062  *
+00063  \code
+00064 #include "pt-sem.h"
+00065 
+00066 #define NUM_ITEMS 32
+00067 #define BUFSIZE 8
+00068 
+00069 static struct pt_sem mutex, full, empty;
+00070 
+00071 PT_THREAD(producer(struct pt *pt))
+00072 {
+00073   static int produced;
+00074   
+00075   PT_BEGIN(pt);
+00076   
+00077   for(produced = 0; produced < NUM_ITEMS; ++produced) {
+00078   
+00079     PT_SEM_WAIT(pt, &full);
+00080     
+00081     PT_SEM_WAIT(pt, &mutex);
+00082     add_to_buffer(produce_item());    
+00083     PT_SEM_SIGNAL(pt, &mutex);
+00084     
+00085     PT_SEM_SIGNAL(pt, &empty);
+00086   }
+00087 
+00088   PT_END(pt);
+00089 }
+00090 
+00091 PT_THREAD(consumer(struct pt *pt))
+00092 {
+00093   static int consumed;
+00094   
+00095   PT_BEGIN(pt);
+00096 
+00097   for(consumed = 0; consumed < NUM_ITEMS; ++consumed) {
+00098     
+00099     PT_SEM_WAIT(pt, &empty);
+00100     
+00101     PT_SEM_WAIT(pt, &mutex);    
+00102     consume_item(get_from_buffer());    
+00103     PT_SEM_SIGNAL(pt, &mutex);
+00104     
+00105     PT_SEM_SIGNAL(pt, &full);
+00106   }
+00107 
+00108   PT_END(pt);
+00109 }
+00110 
+00111 PT_THREAD(driver_thread(struct pt *pt))
+00112 {
+00113   static struct pt pt_producer, pt_consumer;
+00114 
+00115   PT_BEGIN(pt);
+00116   
+00117   PT_SEM_INIT(&empty, 0);
+00118   PT_SEM_INIT(&full, BUFSIZE);
+00119   PT_SEM_INIT(&mutex, 1);
+00120 
+00121   PT_INIT(&pt_producer);
+00122   PT_INIT(&pt_consumer);
+00123 
+00124   PT_WAIT_THREAD(pt, producer(&pt_producer) &
+00125                      consumer(&pt_consumer));
+00126 
+00127   PT_END(pt);
+00128 }
+00129  \endcode
+00130  *
+00131  * The program uses three protothreads: one protothread that
+00132  * implements the consumer, one thread that implements the producer,
+00133  * and one protothread that drives the two other protothreads. The
+00134  * program uses three semaphores: "full", "empty" and "mutex". The
+00135  * "mutex" semaphore is used to provide mutual exclusion for the
+00136  * buffer, the "empty" semaphore is used to block the consumer is the
+00137  * buffer is empty, and the "full" semaphore is used to block the
+00138  * producer is the buffer is full.
+00139  *
+00140  * The "driver_thread" holds two protothread state variables,
+00141  * "pt_producer" and "pt_consumer". It is important to note that both
+00142  * these variables are declared as <i>static</i>. If the static
+00143  * keyword is not used, both variables are stored on the stack. Since
+00144  * protothreads do not store the stack, these variables may be
+00145  * overwritten during a protothread wait operation. Similarly, both
+00146  * the "consumer" and "producer" protothreads declare their local
+00147  * variables as static, to avoid them being stored on the stack.
+00148  * 
+00149  *
+00150  */
+00151    
+00152 /**
+00153  * \file
+00154  * Couting semaphores implemented on protothreads
+00155  * \author
+00156  * Adam Dunkels <adam@sics.se>
+00157  *
+00158  */
+00159 
+00160 #ifndef __PT_SEM_H__
+00161 #define __PT_SEM_H__
+00162 
+00163 #include "pt.h"
+00164 
+00165 struct pt_sem {
+00166   unsigned int count;
+00167 };
+00168 
+00169 /**
+00170  * Initialize a semaphore
+00171  *
+00172  * This macro initializes a semaphore with a value for the
+00173  * counter. Internally, the semaphores use an "unsigned int" to
+00174  * represent the counter, and therefore the "count" argument should be
+00175  * within range of an unsigned int.
+00176  *
+00177  * \param s (struct pt_sem *) A pointer to the pt_sem struct
+00178  * representing the semaphore
+00179  *
+00180  * \param c (unsigned int) The initial count of the semaphore.
+00181  * \hideinitializer
+00182  */
+00183 #define PT_SEM_INIT(s, c) (s)->count = c
+00184 
+00185 /**
+00186  * Wait for a semaphore
+00187  *
+00188  * This macro carries out the "wait" operation on the semaphore. The
+00189  * wait operation causes the protothread to block while the counter is
+00190  * zero. When the counter reaches a value larger than zero, the
+00191  * protothread will continue.
+00192  *
+00193  * \param pt (struct pt *) A pointer to the protothread (struct pt) in
+00194  * which the operation is executed.
+00195  *
+00196  * \param s (struct pt_sem *) A pointer to the pt_sem struct
+00197  * representing the semaphore
+00198  *
+00199  * \hideinitializer
+00200  */
+00201 #define PT_SEM_WAIT(pt, s)      \
+00202   do {                                          \
+00203     PT_WAIT_UNTIL(pt, (s)->count > 0);          \
+00204     --(s)->count;                               \
+00205   } while(0)
+00206 
+00207 /**
+00208  * Signal a semaphore
+00209  *
+00210  * This macro carries out the "signal" operation on the semaphore. The
+00211  * signal operation increments the counter inside the semaphore, which
+00212  * eventually will cause waiting protothreads to continue executing.
+00213  *
+00214  * \param pt (struct pt *) A pointer to the protothread (struct pt) in
+00215  * which the operation is executed.
+00216  *
+00217  * \param s (struct pt_sem *) A pointer to the pt_sem struct
+00218  * representing the semaphore
+00219  *
+00220  * \hideinitializer
+00221  */
+00222 #define PT_SEM_SIGNAL(pt, s) ++(s)->count
+00223 
+00224 #endif /* __PT_SEM_H__ */
+00225 
+00226 /** @} */
+00227 /** @} */
+00228    
+

Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/a00022.html b/doc/html/a00022.html new file mode 100644 index 0000000..ceb6716 --- /dev/null +++ b/doc/html/a00022.html @@ -0,0 +1,347 @@ + + +The Protothreads Library 1.4: pt.h Source File + + + + + + +

pt.h

Go to the documentation of this file.
00001 /*
+00002  * Copyright (c) 2004-2005, Swedish Institute of Computer Science.
+00003  * All rights reserved.
+00004  *
+00005  * Redistribution and use in source and binary forms, with or without
+00006  * modification, are permitted provided that the following conditions
+00007  * are met:
+00008  * 1. Redistributions of source code must retain the above copyright
+00009  *    notice, this list of conditions and the following disclaimer.
+00010  * 2. Redistributions in binary form must reproduce the above copyright
+00011  *    notice, this list of conditions and the following disclaimer in the
+00012  *    documentation and/or other materials provided with the distribution.
+00013  * 3. Neither the name of the Institute nor the names of its contributors
+00014  *    may be used to endorse or promote products derived from this software
+00015  *    without specific prior written permission.
+00016  *
+00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+00027  * SUCH DAMAGE.
+00028  *
+00029  * This file is part of the Contiki operating system.
+00030  *
+00031  * Author: Adam Dunkels <adam@sics.se>
+00032  *
+00033  * $Id: pt.h,v 1.7 2006/10/02 07:52:56 adam Exp $
+00034  */
+00035 
+00036 /**
+00037  * \addtogroup pt
+00038  * @{
+00039  */
+00040 
+00041 /**
+00042  * \file
+00043  * Protothreads implementation.
+00044  * \author
+00045  * Adam Dunkels <adam@sics.se>
+00046  *
+00047  */
+00048 
+00049 #ifndef __PT_H__
+00050 #define __PT_H__
+00051 
+00052 #include "lc.h"
+00053 
+00054 struct pt {
+00055   lc_t lc;
+00056 };
+00057 
+00058 #define PT_WAITING 0
+00059 #define PT_YIELDED 1
+00060 #define PT_EXITED  2
+00061 #define PT_ENDED   3
+00062 
+00063 /**
+00064  * \name Initialization
+00065  * @{
+00066  */
+00067 
+00068 /**
+00069  * Initialize a protothread.
+00070  *
+00071  * Initializes a protothread. Initialization must be done prior to
+00072  * starting to execute the protothread.
+00073  *
+00074  * \param pt A pointer to the protothread control structure.
+00075  *
+00076  * \sa PT_SPAWN()
+00077  *
+00078  * \hideinitializer
+00079  */
+00080 #define PT_INIT(pt)   LC_INIT((pt)->lc)
+00081 
+00082 /** @} */
+00083 
+00084 /**
+00085  * \name Declaration and definition
+00086  * @{
+00087  */
+00088 
+00089 /**
+00090  * Declaration of a protothread.
+00091  *
+00092  * This macro is used to declare a protothread. All protothreads must
+00093  * be declared with this macro.
+00094  *
+00095  * \param name_args The name and arguments of the C function
+00096  * implementing the protothread.
+00097  *
+00098  * \hideinitializer
+00099  */
+00100 #define PT_THREAD(name_args) char name_args
+00101 
+00102 /**
+00103  * Declare the start of a protothread inside the C function
+00104  * implementing the protothread.
+00105  *
+00106  * This macro is used to declare the starting point of a
+00107  * protothread. It should be placed at the start of the function in
+00108  * which the protothread runs. All C statements above the PT_BEGIN()
+00109  * invokation will be executed each time the protothread is scheduled.
+00110  *
+00111  * \param pt A pointer to the protothread control structure.
+00112  *
+00113  * \hideinitializer
+00114  */
+00115 #define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
+00116 
+00117 /**
+00118  * Declare the end of a protothread.
+00119  *
+00120  * This macro is used for declaring that a protothread ends. It must
+00121  * always be used together with a matching PT_BEGIN() macro.
+00122  *
+00123  * \param pt A pointer to the protothread control structure.
+00124  *
+00125  * \hideinitializer
+00126  */
+00127 #define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
+00128                    PT_INIT(pt); return PT_ENDED; }
+00129 
+00130 /** @} */
+00131 
+00132 /**
+00133  * \name Blocked wait
+00134  * @{
+00135  */
+00136 
+00137 /**
+00138  * Block and wait until condition is true.
+00139  *
+00140  * This macro blocks the protothread until the specified condition is
+00141  * true.
+00142  *
+00143  * \param pt A pointer to the protothread control structure.
+00144  * \param condition The condition.
+00145  *
+00146  * \hideinitializer
+00147  */
+00148 #define PT_WAIT_UNTIL(pt, condition)            \
+00149   do {                                          \
+00150     LC_SET((pt)->lc);                           \
+00151     if(!(condition)) {                          \
+00152       return PT_WAITING;                        \
+00153     }                                           \
+00154   } while(0)
+00155 
+00156 /**
+00157  * Block and wait while condition is true.
+00158  *
+00159  * This function blocks and waits while condition is true. See
+00160  * PT_WAIT_UNTIL().
+00161  *
+00162  * \param pt A pointer to the protothread control structure.
+00163  * \param cond The condition.
+00164  *
+00165  * \hideinitializer
+00166  */
+00167 #define PT_WAIT_WHILE(pt, cond)  PT_WAIT_UNTIL((pt), !(cond))
+00168 
+00169 /** @} */
+00170 
+00171 /**
+00172  * \name Hierarchical protothreads
+00173  * @{
+00174  */
+00175 
+00176 /**
+00177  * Block and wait until a child protothread completes.
+00178  *
+00179  * This macro schedules a child protothread. The current protothread
+00180  * will block until the child protothread completes.
+00181  *
+00182  * \note The child protothread must be manually initialized with the
+00183  * PT_INIT() function before this function is used.
+00184  *
+00185  * \param pt A pointer to the protothread control structure.
+00186  * \param thread The child protothread with arguments
+00187  *
+00188  * \sa PT_SPAWN()
+00189  *
+00190  * \hideinitializer
+00191  */
+00192 #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))
+00193 
+00194 /**
+00195  * Spawn a child protothread and wait until it exits.
+00196  *
+00197  * This macro spawns a child protothread and waits until it exits. The
+00198  * macro can only be used within a protothread.
+00199  *
+00200  * \param pt A pointer to the protothread control structure.
+00201  * \param child A pointer to the child protothread's control structure.
+00202  * \param thread The child protothread with arguments
+00203  *
+00204  * \hideinitializer
+00205  */
+00206 #define PT_SPAWN(pt, child, thread)             \
+00207   do {                                          \
+00208     PT_INIT((child));                           \
+00209     PT_WAIT_THREAD((pt), (thread));             \
+00210   } while(0)
+00211 
+00212 /** @} */
+00213 
+00214 /**
+00215  * \name Exiting and restarting
+00216  * @{
+00217  */
+00218 
+00219 /**
+00220  * Restart the protothread.
+00221  *
+00222  * This macro will block and cause the running protothread to restart
+00223  * its execution at the place of the PT_BEGIN() call.
+00224  *
+00225  * \param pt A pointer to the protothread control structure.
+00226  *
+00227  * \hideinitializer
+00228  */
+00229 #define PT_RESTART(pt)                          \
+00230   do {                                          \
+00231     PT_INIT(pt);                                \
+00232     return PT_WAITING;                  \
+00233   } while(0)
+00234 
+00235 /**
+00236  * Exit the protothread.
+00237  *
+00238  * This macro causes the protothread to exit. If the protothread was
+00239  * spawned by another protothread, the parent protothread will become
+00240  * unblocked and can continue to run.
+00241  *
+00242  * \param pt A pointer to the protothread control structure.
+00243  *
+00244  * \hideinitializer
+00245  */
+00246 #define PT_EXIT(pt)                             \
+00247   do {                                          \
+00248     PT_INIT(pt);                                \
+00249     return PT_EXITED;                   \
+00250   } while(0)
+00251 
+00252 /** @} */
+00253 
+00254 /**
+00255  * \name Calling a protothread
+00256  * @{
+00257  */
+00258 
+00259 /**
+00260  * Schedule a protothread.
+00261  *
+00262  * This function shedules a protothread. The return value of the
+00263  * function is non-zero if the protothread is running or zero if the
+00264  * protothread has exited.
+00265  *
+00266  * \param f The call to the C function implementing the protothread to
+00267  * be scheduled
+00268  *
+00269  * \hideinitializer
+00270  */
+00271 #define PT_SCHEDULE(f) ((f) < PT_EXITED)
+00272 
+00273 /** @} */
+00274 
+00275 /**
+00276  * \name Yielding from a protothread
+00277  * @{
+00278  */
+00279 
+00280 /**
+00281  * Yield from the current protothread.
+00282  *
+00283  * This function will yield the protothread, thereby allowing other
+00284  * processing to take place in the system.
+00285  *
+00286  * \param pt A pointer to the protothread control structure.
+00287  *
+00288  * \hideinitializer
+00289  */
+00290 #define PT_YIELD(pt)                            \
+00291   do {                                          \
+00292     PT_YIELD_FLAG = 0;                          \
+00293     LC_SET((pt)->lc);                           \
+00294     if(PT_YIELD_FLAG == 0) {                    \
+00295       return PT_YIELDED;                        \
+00296     }                                           \
+00297   } while(0)
+00298 
+00299 /**
+00300  * \brief      Yield from the protothread until a condition occurs.
+00301  * \param pt   A pointer to the protothread control structure.
+00302  * \param cond The condition.
+00303  *
+00304  *             This function will yield the protothread, until the
+00305  *             specified condition evaluates to true.
+00306  *
+00307  *
+00308  * \hideinitializer
+00309  */
+00310 #define PT_YIELD_UNTIL(pt, cond)                \
+00311   do {                                          \
+00312     PT_YIELD_FLAG = 0;                          \
+00313     LC_SET((pt)->lc);                           \
+00314     if((PT_YIELD_FLAG == 0) || !(cond)) {       \
+00315       return PT_YIELDED;                        \
+00316     }                                           \
+00317   } while(0)
+00318 
+00319 /** @} */
+00320 
+00321 #endif /* __PT_H__ */
+00322 
+00323 /** @} */
+

Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/annotated.html b/doc/html/annotated.html new file mode 100644 index 0000000..461fec4 --- /dev/null +++ b/doc/html/annotated.html @@ -0,0 +1,29 @@ + + +The Protothreads Library 1.4: Data Structures + + + + + + +

The Protothreads Library 1.4 Data Structures

Here are the data structures with brief descriptions: + + +
pt
pt_sem
+
Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/doxygen.css b/doc/html/doxygen.css new file mode 100644 index 0000000..05615b2 --- /dev/null +++ b/doc/html/doxygen.css @@ -0,0 +1,310 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Geneva, Arial, Helvetica, sans-serif; +} +BODY,TD { + font-size: 90%; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} +CAPTION { font-weight: bold } +DIV.qindex { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.nav { + width: 100%; + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + padding: 2px; + line-height: 140%; +} +DIV.navtab { + background-color: #e8eef2; + border: 1px solid #84b0c7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} +TD.navtab { + font-size: 70%; +} +A.qindex { + text-decoration: none; + font-weight: bold; + color: #1A419D; +} +A.qindex:visited { + text-decoration: none; + font-weight: bold; + color: #1A419D +} +A.qindex:hover { + text-decoration: none; + background-color: #ddddff; +} +A.qindexHL { + text-decoration: none; + font-weight: bold; + background-color: #6666cc; + color: #ffffff; + border: 1px double #9295C2; +} +A.qindexHL:hover { + text-decoration: none; + background-color: #6666cc; + color: #ffffff; +} +A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } +A.el { text-decoration: none; font-weight: bold } +A.elRef { font-weight: bold } +A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} +A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} +A.codeRef:link { font-weight: normal; color: #0000FF} +A.codeRef:visited { font-weight: normal; color: #0000FF} +A:hover { text-decoration: none; background-color: #f2f2ff } +DL.el { margin-left: -1cm } +.fragment { + font-family: Fixed, monospace; + font-size: 95%; +} +PRE.fragment { + border: 1px solid #CCCCCC; + background-color: #f5f5f5; + margin-top: 4px; + margin-bottom: 4px; + margin-left: 2px; + margin-right: 8px; + padding-left: 6px; + padding-right: 6px; + padding-top: 4px; + padding-bottom: 4px; +} +DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } +TD.md { background-color: #F4F4FB; font-weight: bold; } +TD.mdPrefix { + background-color: #F4F4FB; + color: #606060; + font-size: 80%; +} +TD.mdname1 { background-color: #F4F4FB; font-weight: bold; color: #602020; } +TD.mdname { background-color: #F4F4FB; font-weight: bold; color: #602020; width: 600px; } +DIV.groupHeader { + margin-left: 16px; + margin-top: 12px; + margin-bottom: 6px; + font-weight: bold; +} +DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } +BODY { + background: white; + color: black; + margin-right: 20px; + margin-left: 20px; +} +TD.indexkey { + background-color: #e8eef2; + font-weight: bold; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TD.indexvalue { + background-color: #e8eef2; + font-style: italic; + padding-right : 10px; + padding-top : 2px; + padding-left : 10px; + padding-bottom : 2px; + margin-left : 0px; + margin-right : 0px; + margin-top : 2px; + margin-bottom : 2px; + border: 1px solid #CCCCCC; +} +TR.memlist { + background-color: #f0f0f0; +} +P.formulaDsp { text-align: center; } +IMG.formulaDsp { } +IMG.formulaInl { vertical-align: middle; } +SPAN.keyword { color: #008000 } +SPAN.keywordtype { color: #604020 } +SPAN.keywordflow { color: #e08000 } +SPAN.comment { color: #800000 } +SPAN.preprocessor { color: #806020 } +SPAN.stringliteral { color: #002080 } +SPAN.charliteral { color: #008080 } +.mdTable { + border: 1px solid #868686; + background-color: #F4F4FB; +} +.mdRow { + padding: 8px 10px; +} +.mdescLeft { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.mdescRight { + padding: 0px 8px 4px 8px; + font-size: 80%; + font-style: italic; + background-color: #FAFAFA; + border-top: 1px none #E0E0E0; + border-right: 1px none #E0E0E0; + border-bottom: 1px none #E0E0E0; + border-left: 1px none #E0E0E0; + margin: 0px; +} +.memItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemLeft { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplItemRight { + padding: 1px 8px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: none; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + background-color: #FAFAFA; + font-size: 80%; +} +.memTemplParams { + padding: 1px 0px 0px 8px; + margin: 4px; + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-color: #E0E0E0; + border-right-color: #E0E0E0; + border-bottom-color: #E0E0E0; + border-left-color: #E0E0E0; + border-top-style: solid; + border-right-style: none; + border-bottom-style: none; + border-left-style: none; + color: #606060; + background-color: #FAFAFA; + font-size: 80%; +} +.search { color: #003399; + font-weight: bold; +} +FORM.search { + margin-bottom: 0px; + margin-top: 0px; +} +INPUT.search { font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +TD.tiny { font-size: 75%; +} +a { + color: #1A41A8; +} +a:visited { + color: #2A3798; +} +.dirtab { padding: 4px; + border-collapse: collapse; + border: 1px solid #84b0c7; +} +TH.dirtab { background: #e8eef2; + font-weight: bold; +} +HR { height: 1px; + border: none; + border-top: 1px solid black; +} + diff --git a/doc/html/doxygen.png b/doc/html/doxygen.png new file mode 100644 index 0000000000000000000000000000000000000000..f0a274bbaffdd67f6d784c894d9cf28729db0e14 GIT binary patch literal 1281 zcmaJ>ZA?>F7(Vx-ms?uoS`b@hdRtpo6o^%HU>M$hfGrBvQnk$LE?p^P!kn&ikhyq! zX~V@&tPF5Qt@V?oTL96Bi%aRiwbe1)9DWQI#?)=HxS7QSw`J`5fAJ*eJbB;uNuKA& zdERDo*{Y<(If(#(B$Lr#;nB(8Y#ia=ZCeW?JfPLuQY`=@cW$k}Rivq|vbxGrRq1Tl9;+(gNt?}UtVKM2`T5t1jLzuL@0UIs`S#vlhl4)^ zLgSYrPj@$+`|j?eSbXTmiHGkWxV8V}BzNR?pl9k_s4pDu9vd5a_UzZEPk)}Ad{AV_ zzddrjrh4=Imr`E06;LY{)YYt?o}L~H@7C}F^WB!Ra=v`Q0bj{>5&$66CWF>mf6vjP z2N>RRY6ZYa=K`76>+|_)Xdwko+7wv}7cN|btOhWb(*{sta~6b?S8Omrxw}!4`NhGr zZVpNqpu1@BE`QGWNTpEpcJVW5izu~2B^GlM?1(OPg)zwW;QcP@Ltcclm>XbJL9C|j z=9!2?ua=uIlf0%AndzHsRC}IyTL$EhAee(fdKB`?27KeS^2M8M_7b~PiCFO&r5LC7 z7gl1*a<8;SjNaw#h=843_AV9iZbWQOAp5YOC^&_F*9K0> zB|6%IDb?aM#3viTxkLU4aXg&@+CkNTOnQ1iMP*^?b|^lJy$4C)Zk4isV!|RZ*XhXh zw8q3$=*0LeGC!XI_Wc?dkT~3+*Gu%%yIqP+Wr3H$=&ROMQU6q}Ag^P~>c5vAEO;a- z_dK-3PPeKar%)6$j~vI2#*-YH!1h6HYVtwCX5_wM`iF#UKz&&@9Oo5w3%XGYrX zW>dY~)SG-((Yim%`InwgTvyRC?e=Wh^8KCao!R6Eg&TpVWUY1sN~4G}V?nFnEGo-; zHZ_$eW9-GnC%^WS9b z@p;-$oH#MtC0v>Q$HX%4^JdFdO$0cbv-W)Q TtK}Eh@>>I#ipmV1>S*>q-hkC} literal 0 HcmV?d00001 diff --git a/doc/html/files.html b/doc/html/files.html new file mode 100644 index 0000000..bdb9c7f --- /dev/null +++ b/doc/html/files.html @@ -0,0 +1,31 @@ + + +The Protothreads Library 1.4: File Index + + + + + + +

The Protothreads Library 1.4 File List

Here is a list of all documented files with brief descriptions: + + + + + +
lc-addrlabels.h [code]Implementation of local continuations based on the "Labels as values" feature of gcc
lc-switch.h [code]Implementation of local continuations based on switch() statment
lc.h [code]Local continuations
pt-sem.h [code]Couting semaphores implemented on protothreads
pt.h [code]Protothreads implementation
+
Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/ftv2blank.png b/doc/html/ftv2blank.png new file mode 100644 index 0000000000000000000000000000000000000000..493c3c0b615ade5b22027bde773faf2c0e076d66 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr2qYM%T@!Q%(o7{me!&ckj8p!u14)&*MwA5S zr6z#mEsk^N1FBF3sc_EE%}vcKVF=AhO-xa6_jFST&P^;T z2~I3aEm8;rVk12R#UIz>f`J-DJY5_^DsClP9B62eH+WF*G=YJMp~A-KbWwke5Kx}M M)78&qol`;+0EL(^EC2ui literal 0 HcmV?d00001 diff --git a/doc/html/ftv2doc.png b/doc/html/ftv2doc.png new file mode 100644 index 0000000000000000000000000000000000000000..f72999f92172cca6edaa2538286b3e369bec9f49 GIT binary patch literal 255 zcmeAS@N?(olHy`uVBq!ia0vp^5yjnX4egh%q=bp-`Pe zR7&bp17l3gfhmh7Fm(iZ2eAfco|q!h5)>qKG?UBh!IC9QGMbJAHf6IEiufk_g|d7~ qkWqJ4k(|I-Aeo-5U~n{Fnc?dN!3Uwu?t6hQVDNPHb6Mw<&;$TLIZ`G7 literal 0 HcmV?d00001 diff --git a/doc/html/ftv2folderclosed.png b/doc/html/ftv2folderclosed.png new file mode 100644 index 0000000000000000000000000000000000000000..d6d063440cbf13c4128dacd96661b6fce58abf26 GIT binary patch literal 259 zcmeAS@N?(olHy`uVBq!ia0vp^55uo^`BphW;jCHO69?}tw{JfcdnZ<*@N=4I z?xF5Qc|QYEmKAIZ;JRGVHe=bn*tx1_|J^^vyg*oVM#A1kZlFULJYD@<);T3K0RTgB BWg7qh literal 0 HcmV?d00001 diff --git a/doc/html/ftv2folderopen.png b/doc/html/ftv2folderopen.png new file mode 100644 index 0000000000000000000000000000000000000000..bbe2c913cf493ee37ad8e3a5132382138d93ac92 GIT binary patch literal 261 zcmeAS@N?(olHy`uVBq!ia0vp^5u(C zYP)Mg%H-DB+{J~>rPn_#pYTax?r*V6ubqGX{lvROQ{?n5_cbm+cQAOm`njxgN@xNA D92;js literal 0 HcmV?d00001 diff --git a/doc/html/ftv2lastnode.png b/doc/html/ftv2lastnode.png new file mode 100644 index 0000000000000000000000000000000000000000..e7b9ba90cb0cf71c8ce662956bfee7d64cf60fa6 GIT binary patch literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!py+H=+kU?6UZ?L@CkAK|NlRbNhD}!Xpp$P zU;Pg)ksC(lf|p%(p+w2Gk+!>EaktaVt4N i!r*{E4>QXNV>t$uAA#a^n)TVt_DW*G8-srQl%FeIsRSdYm zeDdtWec}u&7@8h5rqv#p7g*pRdwwmugmlS-+cHV~j}#7`Nwj9m+AU)JGGo`8z_}`K z?s#Xsy%Z;1_jl5Y+?Gum8WyK6`MBvup0SAOKJ)mWcHyteJ?WLL>>-)=?&<$H&t5oH Vd!azZ1yDdSc)I$ztaD0e0sw}(dc*(# literal 0 HcmV?d00001 diff --git a/doc/html/ftv2mlastnode.png b/doc/html/ftv2mlastnode.png new file mode 100644 index 0000000000000000000000000000000000000000..09ceb6adb01054ce799ad20c0e818ab9272f2df2 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr#LU3Jc=+&fg$isFPOjJ*AaIJQGm()YSDb0rfjgNefXW#>UHx3vIVCg! E0ORy6RsaA1 literal 0 HcmV?d00001 diff --git a/doc/html/ftv2mnode.png b/doc/html/ftv2mnode.png new file mode 100644 index 0000000000000000000000000000000000000000..3254c05112199fbc80aad313611c58a5b388792d GIT binary patch literal 194 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!py+H=+kU?6Ub2s@Ck7}aNq!ti3c<^Gz9OH zn+a6GSQ6wH%;50sMjDVKR^l2_5}cn_Ql40p%8;I!W>k=uu3)5RqGz-?&YcgaLd(;| zF{I*Fa>4?=2W(CyOv{5p*uLi}G<-ambjQcb>&~4!CzK3KXWY6d$*{eWU47N}X+XCz OFnGH9xvXPg)ksC(lf|p%(p+w2Gk+y>EaktaVt4N l!r*{E4>Lv;t literal 0 HcmV?d00001 diff --git a/doc/html/ftv2plastnode.png b/doc/html/ftv2plastnode.png new file mode 100644 index 0000000000000000000000000000000000000000..0b07e00913d8069ebbb51bd7fd6d70d8bba88f75 GIT binary patch literal 165 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr#LU3Jc=+&MJ literal 0 HcmV?d00001 diff --git a/doc/html/ftv2pnode.png b/doc/html/ftv2pnode.png new file mode 100644 index 0000000000000000000000000000000000000000..2001b797ba2b98a4127f1d3efca64aef08bf6d51 GIT binary patch literal 200 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!py+H=+kU?6Ub2s@Ck7}aNq!ti3c<^Gz9OH zn+a6GSQ6wH%;50sMjDVKR^l2_5}cn_Ql40p%8;I!W>k=uu3)5RqGz-?&Ycga!obtT zF{I*Fa>4?=2W(Dkd1@Anj~<0|oqBMOmqox%*rjK-r)THv+0v0L%h-agt(X~hWwYzA SIxU|Ma*U^|pUXO@geCywmoZiV literal 0 HcmV?d00001 diff --git a/doc/html/ftv2vertline.png b/doc/html/ftv2vertline.png new file mode 100644 index 0000000000000000000000000000000000000000..b330f3a33c0085c183ff39fc56b1b274160c1da0 GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^0zfRr!py+H=+kU?6UZ?L@CkAK|NlRbNhD}!Xpp$P zU;Pg)ksC(lf|p%(p+w2Gqgt>EaktaVt4N e!r*{^G#i7W2*a|cHZQDzQVgE1elF{r5}E+)J2fZ( literal 0 HcmV?d00001 diff --git a/doc/html/functions.html b/doc/html/functions.html new file mode 100644 index 0000000..fd14c80 --- /dev/null +++ b/doc/html/functions.html @@ -0,0 +1,37 @@ + + +The Protothreads Library 1.4: Data Fields + + + + + + +
+ +
+Here is a list of all documented struct and union fields with links to the struct/union documentation for each field: +

+

+
Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/functions_vars.html b/doc/html/functions_vars.html new file mode 100644 index 0000000..11f2c17 --- /dev/null +++ b/doc/html/functions_vars.html @@ -0,0 +1,37 @@ + + +The Protothreads Library 1.4: Data Fields - Variables + + + + + + +
+ +
+  +

+

+
Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/globals.html b/doc/html/globals.html new file mode 100644 index 0000000..4263758 --- /dev/null +++ b/doc/html/globals.html @@ -0,0 +1,62 @@ + + +The Protothreads Library 1.4: Data Fields + + + + + + +
+ +
+Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation: +

+

+
Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/globals_defs.html b/doc/html/globals_defs.html new file mode 100644 index 0000000..e97df36 --- /dev/null +++ b/doc/html/globals_defs.html @@ -0,0 +1,61 @@ + + +The Protothreads Library 1.4: Data Fields + + + + + + +
+ +
+  +

+

+
Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/globals_type.html b/doc/html/globals_type.html new file mode 100644 index 0000000..1cfd1df --- /dev/null +++ b/doc/html/globals_type.html @@ -0,0 +1,36 @@ + + +The Protothreads Library 1.4: Data Fields + + + + + + +
+ +
+  +

+

+
Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/hierarchy.html b/doc/html/hierarchy.html new file mode 100644 index 0000000..1a654ba --- /dev/null +++ b/doc/html/hierarchy.html @@ -0,0 +1,29 @@ + + +The Protothreads Library 1.4: Hierarchical Index + + + + + + +

The Protothreads Library 1.4 Class Hierarchy

This inheritance list is sorted roughly, but not completely, alphabetically: +
Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/index.hhc b/doc/html/index.hhc new file mode 100644 index 0000000..7e0f7f4 --- /dev/null +++ b/doc/html/index.hhc @@ -0,0 +1,43 @@ + + + + + +
    +
  • +
  • +
      +
    • +
    • +
    • +
    • +
    • +
    +
  • +
      +
    • +
    • +
    +
  • +
      +
    • +
    • +
    +
  • +
  • +
      +
    • +
        +
      • +
          +
        +
      • +
          +
        +
      +
    • +
        +
      +
    +
  • +
diff --git a/doc/html/index.hhk b/doc/html/index.hhk new file mode 100644 index 0000000..837b6f0 --- /dev/null +++ b/doc/html/index.hhk @@ -0,0 +1,56 @@ + + + + + +
    +
  • +
  • +
  • +
  • +
  • +
      +
    • +
    • +
    • +
    • +
    +
  • +
      +
    • +
    • +
    • +
    +
  • +
      +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
diff --git a/doc/html/index.hhp b/doc/html/index.hhp new file mode 100644 index 0000000..071ac3d --- /dev/null +++ b/doc/html/index.hhp @@ -0,0 +1,44 @@ +[OPTIONS] +Compatibility=1.1 +Full-text search=Yes +Contents file=index.hhc +Default Window=main +Default topic=main.html +Index file=index.hhk +Language=0x409 English (United States) +Title=The Protothreads Library 1.4 + +[WINDOWS] +main="The Protothreads Library 1.4","index.hhc","index.hhk","main.html","main.html",,,,,0x23520,,0x387e,,,,,,,,0 + +[FILES] +main.html +files.html +a00018.html +a00019.html +a00020.html +a00021.html +a00022.html +a00009.html +a00010.html +a00011.html +a00012.html +a00013.html +annotated.html +hierarchy.html +functions.html +functions_vars.html +a00005.html +a00006.html +a00014.html +a00015.html +a00016.html +a00017.html +modules.html +globals.html +globals_type.html +globals_defs.html +tabs.css +tab_b.gif +tab_l.gif +tab_r.gif diff --git a/doc/html/index.html b/doc/html/index.html new file mode 100644 index 0000000..a0bcca8 --- /dev/null +++ b/doc/html/index.html @@ -0,0 +1,8 @@ + + +The Protothreads Library 1.4 + + + + + diff --git a/doc/html/main.html b/doc/html/main.html new file mode 100644 index 0000000..d539dbc --- /dev/null +++ b/doc/html/main.html @@ -0,0 +1,81 @@ + + +The Protothreads Library 1.4: The Protothreads Library + + + + + +

The Protothreads Library

+

+

Author:
Adam Dunkels <adam@sics.se>
+Protothreads are a type of lightweight stackless threads designed for severly memory constrained systems such as deeply embedded systems or sensor network nodes. Protothreads provides linear code execution for event-driven systems implemented in C. Protothreads can be used with or without an RTOS.

+Protothreads are a extremely lightweight, stackless type of threads that provides a blocking context on top of an event-driven system, without the overhead of per-thread stacks. The purpose of protothreads is to implement sequential flow of control without complex state machines or full multi-threading. Protothreads provides conditional blocking inside C functions.

+Main features:

+

    +
  • No machine specific code - the protothreads library is pure C
+

+

    +
  • Does not use error-prone functions such as longjmp()
+

+

    +
  • Very small RAM overhead - only two bytes per protothread
+

+

    +
  • Can be used with or without an OS
+

+

    +
  • Provides blocking wait without full multi-threading or stack-switching
+

+Examples applications:

+

    +
  • Memory constrained systems
+

+

    +
  • Event-driven protocol stacks
+

+

    +
  • Deeply embedded systems
+

+

    +
  • Sensor network nodes
+

+

See also:
Example programs

+Protothreads API documentation

+The protothreads library is released under a BSD-style license that allows for both non-commercial and commercial usage. The only requirement is that credit is given.

+More information and new version of the code can be found at the Protothreads homepage:

+http://www.sics.se/~adam/pt/

+Authors

+The protothreads library was written by Adam Dunkels <adam@sics.se> with support from Oliver Schmidt <ol.sc@web.de>.

+Using protothreads

+Using protothreads in a project is easy: simply copy the files pt.h, lc.h and lc-switch.h into the include files directory of the project, and #include "pt.h" in all files that should use protothreads.

+Protothreads

+Protothreads are a extremely lightweight, stackless threads that provides a blocking context on top of an event-driven system, without the overhead of per-thread stacks. The purpose of protothreads is to implement sequential flow of control without using complex state machines or full multi-threading. Protothreads provides conditional blocking inside a C function.

+In memory constrained systems, such as deeply embedded systems, traditional multi-threading may have a too large memory overhead. In traditional multi-threading, each thread requires its own stack, that typically is over-provisioned. The stacks may use large parts of the available memory.

+The main advantage of protothreads over ordinary threads is that protothreads are very lightweight: a protothread does not require its own stack. Rather, all protothreads run on the same stack and context switching is done by stack rewinding. This is advantageous in memory constrained systems, where a stack for a thread might use a large part of the available memory. A protothread only requires only two bytes of memory per protothread. Moreover, protothreads are implemented in pure C and do not require any machine-specific assembler code.

+A protothread runs within a single C function and cannot span over other functions. A protothread may call normal C functions, but cannot block inside a called function. Blocking inside nested function calls is instead made by spawning a separate protothread for each potentially blocking function. The advantage of this approach is that blocking is explicit: the programmer knows exactly which functions that block that which functions the never blocks.

+Protothreads are similar to asymmetric co-routines. The main difference is that co-routines uses a separate stack for each co-routine, whereas protothreads are stackless. The most similar mechanism to protothreads are Python generators. These are also stackless constructs, but have a different purpose. Protothreads provides blocking contexts inside a C function, whereas Python generators provide multiple exit points from a generator function.

+Local variables

+
Note:
Because protothreads do not save the stack context across a blocking call, local variables are not preserved when the protothread blocks. This means that local variables should be used with utmost care - if in doubt, do not use local variables inside a protothread!
+

+Scheduling

+A protothread is driven by repeated calls to the function in which the protothread is running. Each time the function is called, the protothread will run until it blocks or exits. Thus the scheduling of protothreads is done by the application that uses protothreads.

+Implementation

+Protothreads are implemented using local continuations. A local continuation represents the current state of execution at a particular place in the program, but does not provide any call history or local variables. 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.

+Local continuations can be implemented in a variety of ways:

+

    +
  1. by using machine specific assembler code,
  2. by using standard C constructs, or
  3. by using compiler extensions.
+

+The first way works by saving and restoring the processor state, except for stack pointers, and requires between 16 and 32 bytes of memory per protothread. The exact amount of memory required depends on the architecture.

+The standard C implementation requires only two bytes of state per protothread and utilizes the C switch() statement in a non-obvious way that is similar to Duff's device. This implementation does, however, impose a slight restriction to the code that uses protothreads: a protothread cannot perform a blocking wait (PT_WAIT_UNTIL() or PT_YIELD()) inside a switch() statement.

+Certain compilers has C extensions that can be used to implement protothreads. GCC supports label pointers that can be used for this purpose. With this implementation, protothreads require 4 bytes of RAM per protothread.


Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/modules.html b/doc/html/modules.html new file mode 100644 index 0000000..dcc1841 --- /dev/null +++ b/doc/html/modules.html @@ -0,0 +1,27 @@ + + +The Protothreads Library 1.4: Module Index + + + + + +

The Protothreads Library 1.4 Modules

Here is a list of all modules: +
Generated on Mon Oct 2 10:06:29 2006 for The Protothreads Library 1.4 by  + +doxygen 1.4.6
+ + diff --git a/doc/html/tab_b.gif b/doc/html/tab_b.gif new file mode 100644 index 0000000000000000000000000000000000000000..0d623483ffdf5f9f96900108042a7ab0643fe2a3 GIT binary patch literal 35 ncmZ?wbhEHbWMp7uXkcJy*>IeJfk6j|fqX^=1|}vKMh0sDa2W*H literal 0 HcmV?d00001 diff --git a/doc/html/tab_l.gif b/doc/html/tab_l.gif new file mode 100644 index 0000000000000000000000000000000000000000..9b1e6337c9299a700401a2a78a2c6ffced475216 GIT binary patch literal 706 zcmZ?wbhEHbZT`}F1e&(Gg}Y(8=I;HA5#Z$3JI=gGB)FQ#odI(O&E^@q;x zK6mr*m3xOS-#u~t!I@i+u0DKm^U160k6t`|^WpV}&n+8{U%dD9&a>B#U%!9-@yol< zU%&tQ{rk_K|NsC0`}dE5ET99@1@a36+kb~?0UJ*yc&I3X_m z!ND^5$O7$#8OFRuDhG}!?8z?cdZK&!`PWjdR;Aj^wZ` zeK{IEYHBJ)6K8VIp1`BVt++swf6j+=L{p1*nO(VhE`pFexG@5$|>uaCcd z`0m=9m+yak{QmXN#Sc$^{$X9h9&q2jiKAI|&T)a;PPx2K9p`YIdw8HtR5k2Q$2-O2 z*;3y{MQ-RnJTgJfI&R5|O)AHxDf_00XbPvDZPy4t=hHd)nfLPvms&O`Ok(sD()5v$ z5U@&h;a=#xbxVbo2~X&Xj0Ie(f{v>vERH+qC+nTG=B8Nca=wU-O$?1&vUgV~9=!H; zx>3p9Yn%*<>t~sk+&0xfyS8RsPfYBd<~wWK%j-LmpU>O7yX^h#UCp1x-p#i7@bE;py8XI6 zmY<)m>~)W~yIWcMVoiPg{duuf<*)9qZ9l$m*Ph&W&$jlv*Vpa+{pH@n=IQ$L?0$ax ec60Ul|8o2P|NVbd{6P)#weSbE3}s?04AuZvx_~SI literal 0 HcmV?d00001 diff --git a/doc/html/tab_r.gif b/doc/html/tab_r.gif new file mode 100644 index 0000000000000000000000000000000000000000..ce9dd9f533cb5486d6941844f442b59d4a9e9175 GIT binary patch literal 2585 zcmbV}`9Bkk1ILFF--w5zJc=ZZT(zjE=;2|_S)Qm~rCWz1Pc)KPl;jv%A#&v2*x}yc zmf2~Jm~&=xjJY?PqwIN}f8qQ2{r$uH{c*nJbmr{cR5??*egHrs-B=MzCF`3%e{FAW z{oL5xTHn~5TM{jaB;@|_Ue5F&Zb@p(kMyG{*;gWDg zyeL|eZf7Qd8=#bXzSiR{yzRgLSj-fJS8>lBjVHN z^o-0eS=nE6a`W;LChBs=`+QAJP~{b93>H^eRb5kCSC1zUNezun%`L5M?RDzv#%jk7 zYVRX=vATPD`+oEfum^{RM@GjuP?-r=yh0!p;Vx^T9G7~`7%5ydH%70=jyJ;;`d;hv92x3R=z{xp+Lg2!*@OK*K15-t&okoPtSED)h&$RLxdbA zseWm^C3d%-yRNi-ryk^!ek+C`n&~cd$#ZWct_cUL{l~i+Nzx^5d!n94(>bW-iL~Rl z&8r)?q|1DIo=0=judQ{FaGcfLERz8gfn3-Qt<2lksh{mzpT}DXxUuR^z=^key&q4! z+wWI45vL0k$R^(F#{qfqhUsN@WA+w-V?LPH33!Q?WFSB3)WBojE@hK41Nb?KfS+Qo zXgrzfsP$wr4Qzy*{OD>uJBjdgGM@VMml5)2f~_}lD*YyOb}Hjeobhz#4c`w(l^>KK zr?Ud;W~Z}*w;%hZ|2^p^+f06gJDJQD zeIhGADbDmm&6arh(q>EZ<7mjzg7l|z$hRL8=1>)Nv=S7CY$B}iYJ&*T_-T_OG*L1q ztZ3Lana33?y3AKnyq^YCF|4x%Rb5WU&2qcl{TFKey%QJeMxn^SdT!hZ5+0i1zeusiYVp-phBl7b5+Px-X&LhByq z0F&<;K0l2+v>qiHlXb#$jXMv$uK-dEGE9L~qtdU(XeRXmvu*K2Q&6!fD**JxYP4b4BR7FdJ$Qx9G9`J%-_X!a#LGpp3g9)VWytGCa;7`S1_e8F~!R+aSJ zOF17p2`H?2kPs8Q`_;U}+D%3p zs2-0BTqFwpUoBk`?P;iPQ(IbEA|JmMx!P&YYG|R@S=5Mnw;-?A6rEEVyV%d7{iU4a zNk`i!%F(Ykpm`}#oH;BjY->@b8vQedv;pza2FL&*6ufjd+*3Ute&>kes~TU?^KkojsTh(o~(3tk1Y6>4(yn( z#U*ID9@eg-beKo1B;HXe+}{Z%n@7m0+yxivuqk9~;!1LGQlah)xYK4>wgL}l6dsaN zIxlRlq`*`j9PG4*0hD6YV_b_2w5b#)o7J?`q#{GjvvKlD`T*dWcZx<-s(ZvLB44E# z=!|sw!?)@%y$oRNL#25WS3lzdii}TuQ3?CLnvQ1_n};2sT_;Y;#d3=+-(O% zMN$>O!3;ke(UuLR%h_&)N zs^!-@A>QR}4yB1bPp`9S19ikTbZ~O{&FF-yHK{En;mmShDUIEw03`j(DBIsM}Rjki2J#SQa3gFZTKBPDeIiLt9Z z%bL3(B@Qw%(B`wSMS~dPh$=R`(}lBoFXKy(s|*{#ru$wjsBc_O#zxNk9w+UUHmx(U zmJ8+M+ndtnZ<7|VU9Mbt61zpo9T&3%Wx&XII=#QJxjR`CZf22ac3d51Z?GD%LEe_&*t46Qf;4`bZ7p2K(Ab5>GfT^}4! zBT&HZD`^PEgWoI&{~o-ID0F?O`75sm(87x%A{(}Ch1)QlzdJ)1B-eqe5a(weg0`4lQIf1evjvbBY50DVbzO7CLf|vP z2#0(U-|jZ`H{y5N^o7%iK6H>_HEGN->U6^!)1{XpJV!!4(Ig7wzZQ*9WYF4X1rG0x z=1uA@i`rIAciubDC{;~b(|&|A@xkjRP5aRcvRU9tvIm}jDB6J eQ0-6-y)mpwdT=ayS0tBxKDA*~;EWmo literal 0 HcmV?d00001 diff --git a/doc/html/tabs.css b/doc/html/tabs.css new file mode 100644 index 0000000..a61552a --- /dev/null +++ b/doc/html/tabs.css @@ -0,0 +1,102 @@ +/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */ + +DIV.tabs +{ + float : left; + width : 100%; + background : url("tab_b.gif") repeat-x bottom; + margin-bottom : 4px; +} + +DIV.tabs UL +{ + margin : 0px; + padding-left : 10px; + list-style : none; +} + +DIV.tabs LI, DIV.tabs FORM +{ + display : inline; + margin : 0px; + padding : 0px; +} + +DIV.tabs FORM +{ + float : right; +} + +DIV.tabs A +{ + float : left; + background : url("tab_r.gif") no-repeat right top; + border-bottom : 1px solid #84B0C7; + font-size : x-small; + font-weight : bold; + text-decoration : none; +} + +DIV.tabs A:hover +{ + background-position: 100% -150px; +} + +DIV.tabs A:link, DIV.tabs A:visited, +DIV.tabs A:active, DIV.tabs A:hover +{ + color: #1A419D; +} + +DIV.tabs SPAN +{ + float : left; + display : block; + background : url("tab_l.gif") no-repeat left top; + padding : 5px 9px; + white-space : nowrap; +} + +DIV.tabs INPUT +{ + float : right; + display : inline; + font-size : 1em; +} + +DIV.tabs TD +{ + font-size : x-small; + font-weight : bold; + text-decoration : none; +} + + + +/* Commented Backslash Hack hides rule from IE5-Mac \*/ +DIV.tabs SPAN {float : none;} +/* End IE5-Mac hack */ + +DIV.tabs A:hover SPAN +{ + background-position: 0% -150px; +} + +DIV.tabs LI#current A +{ + background-position: 100% -150px; + border-width : 0px; +} + +DIV.tabs LI#current SPAN +{ + background-position: 0% -150px; + padding-bottom : 6px; +} + +DIV.nav +{ + background : none; + border : none; + border-bottom : 1px solid #84B0C7; +} diff --git a/doc/html/tree.html b/doc/html/tree.html new file mode 100644 index 0000000..be8ac5d --- /dev/null +++ b/doc/html/tree.html @@ -0,0 +1,108 @@ + + + + + + + TreeView + + + + + + + + diff --git a/doc/pt-doc.txt b/doc/pt-doc.txt new file mode 100644 index 0000000..2d6742e --- /dev/null +++ b/doc/pt-doc.txt @@ -0,0 +1,58 @@ +/** +\defgroup pt Protothreads +@{ +Protothreads are implemented in a single header file, pt.h, which +includes the local continuations header file, lc.h. This file in turn +includes the actual implementation of local continuations, which +typically also is contained in a single header file. + +*/ + +/** @} */ + +/** +\defgroup examples Examples +@{ + +\section example-small A small example + +This first example shows a very simple program: two protothreads +waiting for each other to toggle two flags. The code illustrates how +to write protothreads code, how to initialize protothreads, and how to +schedule them. + +\include example-small.c + + +\section example-code-lock A code-lock +This example shows how to implement a simple code lock - the kind of +device that is placed next to doors and that you have to push a four +digit number into in order to unlock the door. + +The code lock waits for key presses from a numeric keyboard and if the +correct code is entered, the lock is unlocked. There is a maximum time +of one second between each key press, and after the correct code has +been entered, no more keys must be pressed for 0.5 seconds before the +lock is opened. + +\include example-codelock.c + +\section example-buffer The bounded buffer with protothread semaphores + +The following example shows how to implement the bounded buffer +problem using the protothreads semaphore library. The example uses +three protothreads: one producer() protothread that produces items, +one consumer() protothread that consumes items, and one +driver_thread() that schedules the producer and consumer protothreads. + +Note that there is no need for a mutex to guard the add_to_buffer() +and get_from_buffer() functions because of the implicit locking +semantics of protothreads - a protothread will never be preempted and +will never block except in an explicit PT_WAIT statement. + +\include example-buffer.c + +*/ + + +/** @} */ diff --git a/doc/pt-mainpage.txt b/doc/pt-mainpage.txt new file mode 100644 index 0000000..60eb016 --- /dev/null +++ b/doc/pt-mainpage.txt @@ -0,0 +1,156 @@ +/** + +\mainpage The Protothreads Library + +\author Adam Dunkels + +Protothreads are a type of lightweight stackless threads designed for +severly memory constrained systems such as deeply embedded systems or +sensor network nodes. Protothreads provides linear code execution for +event-driven systems implemented in C. Protothreads can be used with +or without an RTOS. + +Protothreads are a extremely lightweight, stackless type of threads +that provides a blocking context on top of an event-driven system, +without the overhead of per-thread stacks. The purpose of protothreads +is to implement sequential flow of control without complex state +machines or full multi-threading. Protothreads provides conditional +blocking inside C functions. + +Main features: + + - No machine specific code - the protothreads library is pure C + + - Does not use error-prone functions such as longjmp() + + - Very small RAM overhead - only two bytes per protothread + + - Can be used with or without an OS + + - Provides blocking wait without full multi-threading or + stack-switching + +Examples applications: + + - Memory constrained systems + + - Event-driven protocol stacks + + - Deeply embedded systems + + - Sensor network nodes + + +\sa \ref examples "Example programs" +\sa \ref pt "Protothreads API documentation" + +The protothreads library is released under a BSD-style license that +allows for both non-commercial and commercial usage. The only +requirement is that credit is given. + +More information and new version of the code can be found at the +Protothreads homepage: + + http://www.sics.se/~adam/pt/ + +\section authors Authors + +The protothreads library was written by Adam Dunkels +with support from Oliver Schmidt . + +\section using Using protothreads + +Using protothreads in a project is easy: simply copy the files pt.h, +lc.h and lc-switch.h into the include files directory of the project, +and \#include "pt.h" in all files that should use protothreads. + +\section pt-desc Protothreads + +Protothreads are a extremely lightweight, stackless threads that +provides a blocking context on top of an event-driven system, without +the overhead of per-thread stacks. The purpose of protothreads is to +implement sequential flow of control without using complex state +machines or full multi-threading. Protothreads provides conditional +blocking inside a C function. + +In memory constrained systems, such as deeply embedded systems, +traditional multi-threading may have a too large memory overhead. In +traditional multi-threading, each thread requires its own stack, that +typically is over-provisioned. The stacks may use large parts of the +available memory. + +The main advantage of protothreads over ordinary threads is that +protothreads are very lightweight: a protothread does not require its +own stack. Rather, all protothreads run on the same stack and context +switching is done by stack rewinding. This is advantageous in memory +constrained systems, where a stack for a thread might use a large part +of the available memory. A protothread only requires only two bytes of +memory per protothread. Moreover, protothreads are implemented in pure +C and do not require any machine-specific assembler code. + +A protothread runs within a single C function and cannot span over +other functions. A protothread may call normal C functions, but cannot +block inside a called function. Blocking inside nested function calls +is instead made by spawning a separate protothread for each +potentially blocking function. The advantage of this approach is that +blocking is explicit: the programmer knows exactly which functions +that block that which functions the never blocks. + +Protothreads are similar to asymmetric co-routines. The main +difference is that co-routines uses a separate stack for each +co-routine, whereas protothreads are stackless. The most similar +mechanism to protothreads are Python generators. These are also +stackless constructs, but have a different purpose. Protothreads +provides blocking contexts inside a C function, whereas Python +generators provide multiple exit points from a generator function. + +\section pt-autovars Local variables + +\note +Because protothreads do not save the stack context across a blocking +call, local variables are not preserved when the protothread +blocks. This means that local variables should be used with utmost +care - if in doubt, do not use local variables inside a protothread! + +\section pt-scheduling Scheduling + +A protothread is driven by repeated calls to the function in which the +protothread is running. Each time the function is called, the +protothread will run until it blocks or exits. Thus the scheduling of +protothreads is done by the application that uses protothreads. + +\section pt-impl Implementation + +Protothreads are implemented using local continuations. A local +continuation represents the current state of execution at a particular +place in the program, but does not provide any call history or local +variables. 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. + + +Local continuations can be implemented in a variety of ways: + + -# by using machine specific assembler code, + -# by using standard C constructs, or + -# by using compiler extensions. + +The first way works by saving and restoring the processor state, +except for stack pointers, and requires between 16 and 32 bytes of +memory per protothread. The exact amount of memory required depends on +the architecture. + +The standard C implementation requires only two bytes of state per +protothread and utilizes the C switch() statement in a non-obvious way +that is similar to Duff's device. This implementation does, however, +impose a slight restriction to the code that uses protothreads: a +protothread cannot perform a blocking wait (PT_WAIT_UNTIL() or +PT_YIELD()) inside a switch() statement. + +Certain compilers has C extensions that can be used to implement +protothreads. GCC supports label pointers that can be used for this +purpose. With this implementation, protothreads require 4 bytes of RAM +per protothread. + +*/ diff --git a/doc/pt-refman.pdf b/doc/pt-refman.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2ee4db038a3e8dbb9bccf24199bd977d3a2c9ec1 GIT binary patch literal 226750 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 + * + * $Id: example-buffer.c,v 1.5 2005/10/07 05:21:33 adam Exp $ + */ + +#ifdef _WIN32 +#include +#else +#include +#endif +#include + +#include "pt-sem.h" + +#define NUM_ITEMS 32 +#define BUFSIZE 8 + +static int buffer[BUFSIZE]; +static int bufptr; + +static void +add_to_buffer(int item) +{ + printf("Item %d added to buffer at place %d\n", item, bufptr); + buffer[bufptr] = item; + bufptr = (bufptr + 1) % BUFSIZE; +} +static int +get_from_buffer(void) +{ + int item; + item = buffer[bufptr]; + printf("Item %d retrieved from buffer at place %d\n", + item, bufptr); + bufptr = (bufptr + 1) % BUFSIZE; + return item; +} + +static int +produce_item(void) +{ + static int item = 0; + printf("Item %d produced\n", item); + return item++; +} + +static void +consume_item(int item) +{ + printf("Item %d consumed\n", item); +} + +static struct pt_sem full, empty; + +static +PT_THREAD(producer(struct pt *pt)) +{ + static int produced; + + PT_BEGIN(pt); + + for(produced = 0; produced < NUM_ITEMS; ++produced) { + + PT_SEM_WAIT(pt, &full); + + add_to_buffer(produce_item()); + + PT_SEM_SIGNAL(pt, &empty); + } + + PT_END(pt); +} + +static +PT_THREAD(consumer(struct pt *pt)) +{ + static int consumed; + + PT_BEGIN(pt); + + for(consumed = 0; consumed < NUM_ITEMS; ++consumed) { + + PT_SEM_WAIT(pt, &empty); + + consume_item(get_from_buffer()); + + PT_SEM_SIGNAL(pt, &full); + } + + PT_END(pt); +} + +static +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_INIT(&pt_producer); + PT_INIT(&pt_consumer); + + PT_WAIT_THREAD(pt, producer(&pt_producer) & + consumer(&pt_consumer)); + + PT_END(pt); +} + + +int +main(void) +{ + struct pt driver_pt; + + PT_INIT(&driver_pt); + + while(PT_SCHEDULE(driver_thread(&driver_pt))) { + + /* + * When running this example on a multitasking system, we must + * give other processes a chance to run too and therefore we call + * usleep() resp. Sleep() here. On a dedicated embedded system, + * we usually do not need to do this. + */ +#ifdef _WIN32 + Sleep(0); +#else + usleep(10); +#endif + } + return 0; +} diff --git a/example-codelock.c b/example-codelock.c new file mode 100644 index 0000000..cbeeb96 --- /dev/null +++ b/example-codelock.c @@ -0,0 +1,414 @@ +/* + * 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 protothreads library. + * + * Author: Adam Dunkels + * + * $Id: example-codelock.c,v 1.5 2005/10/06 07:57:08 adam Exp $ + */ + +/* + * + * This example shows how to implement a simple code lock. The code + * lock waits for key presses from a numeric keyboard and if the + * correct code is entered, the lock is unlocked. There is a maximum + * time of one second between each key press, and after the correct + * code has been entered, no more keys must be pressed for 0.5 seconds + * before the lock is opened. + * + * This is an example that shows two things: + * - how to implement a code lock key input mechanism, and + * - how to implement a sequential timed routine. + * + * The program consists of two protothreads, one that implements the + * code lock reader and one that implements simulated keyboard input. + * + * + */ + +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#include + +#include "pt.h" + +/*---------------------------------------------------------------------------*/ +/* + * The following definitions are just for the simple timer library + * used in this example. The actual implementation of the functions + * can be found at the end of this file. + */ +struct timer { int start, interval; }; +static int timer_expired(struct timer *t); +static void timer_set(struct timer *t, int usecs); +/*---------------------------------------------------------------------------*/ +/* + * This example uses two timers: one for the code lock protothread and + * one for the simulated key input protothread. + */ +static struct timer codelock_timer, input_timer; +/*---------------------------------------------------------------------------*/ +/* + * This is the code that has to be entered. + */ +static const char code[4] = {'1', '4', '2', '3'}; +/*---------------------------------------------------------------------------*/ +/* + * This example has two protothread and therefor has two protothread + * control structures of type struct pt. These are initialized with + * PT_INIT() in the main() function below. + */ +static struct pt codelock_pt, input_pt; +/*---------------------------------------------------------------------------*/ +/* + * The following code implements a simple key input. Input is made + * with the press_key() function, and the function key_pressed() + * checks if a key has been pressed. The variable "key" holds the + * latest key that was pressed. The variable "key_pressed_flag" is set + * when a key is pressed and cleared when a key press is checked. + */ +static char key, key_pressed_flag; + +static void +press_key(char k) +{ + printf("--- Key '%c' pressed\n", k); + key = k; + key_pressed_flag = 1; +} + +static int +key_pressed(void) +{ + if(key_pressed_flag != 0) { + key_pressed_flag = 0; + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * Declaration of the protothread function implementing the code lock + * logic. The protothread function is declared using the PT_THREAD() + * macro. The function is declared with the "static" keyword since it + * is local to this file. The name of the function is codelock_thread + * and it takes one argument, pt, of the type struct pt. + * + */ +static +PT_THREAD(codelock_thread(struct pt *pt)) +{ + /* This is a local variable that holds the number of keys that have + * been pressed. Note that it is declared with the "static" keyword + * to make sure that the variable is *not* allocated on the stack. + */ + static int keys; + + /* + * Declare the beginning of the protothread. + */ + PT_BEGIN(pt); + + /* + * We'll let the protothread loop until the protothread is + * expliticly exited with PT_EXIT(). + */ + while(1) { + + /* + * We'll be reading key presses until we get the right amount of + * correct keys. + */ + for(keys = 0; keys < sizeof(code); ++keys) { + + /* + * If we haven't gotten any keypresses, we'll simply wait for one. + */ + if(keys == 0) { + + /* + * The PT_WAIT_UNTIL() function will block until the condition + * key_pressed() is true. + */ + PT_WAIT_UNTIL(pt, key_pressed()); + } else { + + /* + * If the "key" variable was larger than zero, we have already + * gotten at least one correct key press. If so, we'll not + * only wait for the next key, but we'll also set a timer that + * expires in one second. This gives the person pressing the + * keys one second to press the next key in the code. + */ + timer_set(&codelock_timer, 1000); + + /* + * The following statement shows how complex blocking + * conditions can be easily expressed with protothreads and + * the PT_WAIT_UNTIL() function. + */ + PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer)); + + /* + * If the timer expired, we should break out of the for() loop + * and start reading keys from the beginning of the while(1) + * loop instead. + */ + if(timer_expired(&codelock_timer)) { + printf("Code lock timer expired.\n"); + + /* + * Break out from the for() loop and start from the + * beginning of the while(1) loop. + */ + break; + } + } + + /* + * Check if the pressed key was correct. + */ + if(key != code[keys]) { + printf("Incorrect key '%c' found\n", key); + /* + * Break out of the for() loop since the key was incorrect. + */ + break; + } else { + printf("Correct key '%c' found\n", key); + } + } + + /* + * Check if we have gotten all keys. + */ + if(keys == sizeof(code)) { + printf("Correct code entered, waiting for 500 ms before unlocking.\n"); + + /* + * Ok, we got the correct code. But to make sure that the code + * was not just a fluke of luck by an intruder, but the correct + * code entered by a person that knows the correct code, we'll + * wait for half a second before opening the lock. If another + * key is pressed during this time, we'll assume that it was a + * fluke of luck that the correct code was entered the first + * time. + */ + timer_set(&codelock_timer, 500); + PT_WAIT_UNTIL(pt, key_pressed() || timer_expired(&codelock_timer)); + + /* + * If we continued from the PT_WAIT_UNTIL() statement without + * the timer expired, we don't open the lock. + */ + if(!timer_expired(&codelock_timer)) { + printf("Key pressed during final wait, code lock locked again.\n"); + } else { + + /* + * If the timer expired, we'll open the lock and exit from the + * protothread. + */ + printf("Code lock unlocked.\n"); + PT_EXIT(pt); + } + } + } + + /* + * Finally, we'll mark the end of the protothread. + */ + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +/* + * This is the second protothread in this example. It implements a + * simulated user pressing the keys. This illustrates how a linear + * sequence of timed instructions can be implemented with + * protothreads. + */ +static +PT_THREAD(input_thread(struct pt *pt)) +{ + PT_BEGIN(pt); + + printf("Waiting 1 second before entering first key.\n"); + + timer_set(&input_timer, 1000); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('1'); + + timer_set(&input_timer, 100); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('2'); + + timer_set(&input_timer, 100); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('3'); + + timer_set(&input_timer, 2000); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('1'); + + timer_set(&input_timer, 200); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('4'); + + timer_set(&input_timer, 200); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('2'); + + timer_set(&input_timer, 2000); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('3'); + + timer_set(&input_timer, 200); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('1'); + + timer_set(&input_timer, 200); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('4'); + + timer_set(&input_timer, 200); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('2'); + + timer_set(&input_timer, 100); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('3'); + + timer_set(&input_timer, 100); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('4'); + + timer_set(&input_timer, 1500); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('1'); + + timer_set(&input_timer, 300); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('4'); + + timer_set(&input_timer, 400); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('2'); + + timer_set(&input_timer, 500); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + press_key('3'); + + timer_set(&input_timer, 2000); + PT_WAIT_UNTIL(pt, timer_expired(&input_timer)); + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +/* + * This is the main function. It initializes the two protothread + * control structures and schedules the two protothreads. The main + * function returns when the protothread the runs the code lock exits. + */ +int +main(void) +{ + /* + * Initialize the two protothread control structures. + */ + PT_INIT(&input_pt); + PT_INIT(&codelock_pt); + + /* + * Schedule the two protothreads until the codelock_thread() exits. + */ + while(PT_SCHEDULE(codelock_thread(&codelock_pt))) { + PT_SCHEDULE(input_thread(&input_pt)); + + /* + * When running this example on a multitasking system, we must + * give other processes a chance to run too and therefore we call + * usleep() resp. Sleep() here. On a dedicated embedded system, + * we usually do not need to do this. + */ +#ifdef _WIN32 + Sleep(0); +#else + usleep(10); +#endif + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * Finally, the implementation of the simple timer library follows. + */ +#ifdef _WIN32 + +static int clock_time(void) +{ return (int)GetTickCount(); } + +#else /* _WIN32 */ + +static int clock_time(void) +{ + struct timeval tv; + struct timezone tz; + gettimeofday(&tv, &tz); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +#endif /* _WIN32 */ + +static int timer_expired(struct timer *t) +{ return (int)(clock_time() - t->start) >= (int)t->interval; } + +static void timer_set(struct timer *t, int interval) +{ t->interval = interval; t->start = clock_time(); } +/*---------------------------------------------------------------------------*/ diff --git a/example-small.c b/example-small.c new file mode 100644 index 0000000..37c1716 --- /dev/null +++ b/example-small.c @@ -0,0 +1,97 @@ +/** + * This is a very small example that shows how to use + * protothreads. The program consists of two protothreads that wait + * for each other to toggle a variable. + */ + +/* We must always include pt.h in our protothreads code. */ +#include "pt.h" + +#include /* For printf(). */ + +/* Two flags that the two protothread functions use. */ +static int protothread1_flag, protothread2_flag; + +/** + * The first protothread function. A protothread function must always + * return an integer, but must never explicitly return - returning is + * performed inside the protothread statements. + * + * The protothread function is driven by the main loop further down in + * the code. + */ +static int +protothread1(struct pt *pt) +{ + /* A protothread function must begin with PT_BEGIN() which takes a + pointer to a struct pt. */ + PT_BEGIN(pt); + + /* We loop forever here. */ + while(1) { + /* Wait until the other protothread has set its flag. */ + PT_WAIT_UNTIL(pt, protothread2_flag != 0); + printf("Protothread 1 running\n"); + + /* We then reset the other protothread's flag, and set our own + flag so that the other protothread can run. */ + protothread2_flag = 0; + protothread1_flag = 1; + + /* And we loop. */ + } + + /* All protothread functions must end with PT_END() which takes a + pointer to a struct pt. */ + PT_END(pt); +} + +/** + * The second protothread function. This is almost the same as the + * first one. + */ +static int +protothread2(struct pt *pt) +{ + PT_BEGIN(pt); + + while(1) { + /* Let the other protothread run. */ + protothread2_flag = 1; + + /* Wait until the other protothread has set its flag. */ + PT_WAIT_UNTIL(pt, protothread1_flag != 0); + printf("Protothread 2 running\n"); + + /* We then reset the other protothread's flag. */ + protothread1_flag = 0; + + /* And we loop. */ + } + PT_END(pt); +} + +/** + * Finally, we have the main loop. Here is where the protothreads are + * initialized and scheduled. First, however, we define the + * protothread state variables pt1 and pt2, which hold the state of + * the two protothreads. + */ +static struct pt pt1, pt2; +int +main(void) +{ + /* Initialize the protothread state variables with PT_INIT(). */ + PT_INIT(&pt1); + PT_INIT(&pt2); + + /* + * Then we schedule the two protothreads by repeatedly calling their + * protothread functions and passing a pointer to the protothread + * state variables as arguments. + */ + while(1) { + protothread1(&pt1); + protothread2(&pt2); + } +} diff --git a/lc-addrlabels.h b/lc-addrlabels.h new file mode 100644 index 0000000..3e6474e --- /dev/null +++ b/lc-addrlabels.h @@ -0,0 +1,85 @@ +/* + * 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 + * + * $Id: lc-addrlabels.h,v 1.4 2006/06/03 11:29:43 adam Exp $ + */ + +/** + * \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 + * + */ + +#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_CONCAT2(s1, s2) s1##s2 +#define LC_CONCAT(s1, s2) LC_CONCAT2(s1, s2) + +#define LC_SET(s) \ + do { \ + LC_CONCAT(LC_LABEL, __LINE__): \ + (s) = &&LC_CONCAT(LC_LABEL, __LINE__); \ + } while(0) + +#define LC_END(s) + +#endif /* __LC_ADDRLABELS_H__ */ +/** @} */ diff --git a/lc-switch.h b/lc-switch.h new file mode 100644 index 0000000..dbdde01 --- /dev/null +++ b/lc-switch.h @@ -0,0 +1,76 @@ +/* + * 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 + * + * $Id: lc-switch.h,v 1.4 2006/06/03 11:29:43 adam Exp $ + */ + +/** + * \addtogroup lc + * @{ + */ + +/** + * \file + * Implementation of local continuations based on switch() statment + * \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() statmenets. + * + * 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/lc.h b/lc.h new file mode 100644 index 0000000..a965956 --- /dev/null +++ b/lc.h @@ -0,0 +1,132 @@ +/* + * 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 protothreads library. + * + * Author: Adam Dunkels + * + * $Id: lc.h,v 1.2 2005/02/24 10:36:59 adam Exp $ + */ + +/** + * \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 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_INCLUDE +#include LC_INCLUDE +#else +#include "lc-switch.h" +#endif /* LC_INCLUDE */ + +#endif /* __LC_H__ */ + +/** @} */ +/** @} */ diff --git a/pt-sem.h b/pt-sem.h new file mode 100644 index 0000000..98ae25d --- /dev/null +++ b/pt-sem.h @@ -0,0 +1,228 @@ +/* + * 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 protothreads library. + * + * Author: Adam Dunkels + * + * $Id: pt-sem.h,v 1.2 2005/02/24 10:36:59 adam Exp $ + */ + +/** + * \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 signalled, 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 + * Couting semaphores implemented on protothreads + * \author + * Adam Dunkels + * + */ + +#ifndef __PT_SEM_H__ +#define __PT_SEM_H__ + +#include "pt.h" + +struct pt_sem { + unsigned int count; +}; + +/** + * 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) (s)->count = c + +/** + * 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, (s)->count > 0); \ + --(s)->count; \ + } 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)->count + +#endif /* __PT_SEM_H__ */ + +/** @} */ +/** @} */ + diff --git a/pt.h b/pt.h new file mode 100644 index 0000000..7f20e40 --- /dev/null +++ b/pt.h @@ -0,0 +1,315 @@ +/* + * 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 + * + * $Id: pt.h,v 1.7 2006/10/02 07:52:56 adam Exp $ + */ + +/** + * \addtogroup pt + * @{ + */ + +/** + * \file + * Protothreads implementation. + * \author + * Adam Dunkels + * + */ + +#ifndef __PT_H__ +#define __PT_H__ + +#include "lc.h" + +struct pt { + lc_t lc; +}; + +#define PT_WAITING 0 +#define PT_YIELDED 1 +#define PT_EXITED 2 +#define PT_ENDED 3 + +/** + * \name 初始化 + * @{ + */ + +/** + * 初始化protothread线程 + * + * 初始化protothread线程。初始化必须在开始执行原型线程之前完成。 + * + * \param pt 指向protothread线程控制结构的指针 + * + * \sa PT_SPAWN() + * + * \hideinitializer + */ +#define PT_INIT(pt) LC_INIT((pt)->lc) + +/** @} */ + +/** + * \name 声明和定义 + * @{ + */ + +/** + * 声明protothread线程。 + * + * 此宏用于声明protothread线程。必须使用此宏声明所有protothread线程 + * + * \param name_args 实现protothread线程的 C 函数的名称和参数。 + * + * \hideinitializer + */ +#define PT_THREAD(name_args) char name_args + +/** + * 在实现protothread线程的 C 函数中声明protothread线程的开始 + * + * 此宏用于声明protothread线程的起点。它应该放在运行protothread线程的函数的开头。 + * 每次调度 protothread 时,都将执行 PT_BEGIN() 调用上方的所有 C 语句。 + * + * \param pt 指向原型线程控制结构的指针。 + * + * \hideinitializer + */ +#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc) + +/** + * 声明原型线程的结束。 + * + * 此宏用于声明原型线程结束。它必须始终与匹配的 PT_BEGIN() 宏一起使用。 + * + * \param pt 指向原型线程控制结构的指针。 + * + * \hideinitializer + */ +#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \ + PT_INIT(pt); return PT_ENDED; } + +/** @} */ + +/** + * \name 阻止等待 + * @{ + */ + +/** + * 阻止并等待条件为真 + * + * 此宏会阻塞原型线程,直到指定的条件为真 + * + * \param pt 指向原型线程控制结构的指针 + * \param condition 条件。 + * + * \hideinitializer + */ +#define PT_WAIT_UNTIL(pt, condition) \ + do { \ + LC_SET((pt)->lc); \ + if(!(condition)) { \ + return PT_WAITING; \ + } \ + } while(0) + +/** + * 阻止并等待条件为真。 + * + * 此功能在条件为真时阻止并等待. See + * PT_WAIT_UNTIL(). + * + * \param pt 指向原型线程控制结构的指针 + * \param cond 条件。 + * + * \hideinitializer + */ +#define PT_WAIT_WHILE(pt, cond) PT_WAIT_UNTIL((pt), !(cond)) + +/** @} */ + +/** + * \name 分层原型线程 + * @{ + */ + +/** + * 阻止并等待子原型线程完成。 + * + * 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 shedules 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__ */ + +/** @} */