Module: xenomai-forge
Branch: next
Commit: 1a8839289719119ad0d1b5026504e3eed5c46a63
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=1a8839289719119ad0d1b5026504e3eed5c46a63

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sun Jul  6 15:25:22 2014 +0200

lib/copperplate, lib/alchemy: introduce API tags

---

 aclocal.m4                          |   15 ---
 config/config.guess                 |  151 ++++++++++++++++------------
 config/config.sub                   |   30 +++---
 doc/doxygen/xeno3prm-common.conf.in |    2 +
 include/alchemy/alarm.h             |    1 -
 include/alchemy/buffer.h            |    1 -
 include/alchemy/cond.h              |    1 -
 include/alchemy/event.h             |    1 -
 include/alchemy/heap.h              |    1 -
 include/alchemy/mutex.h             |    1 -
 include/alchemy/pipe.h              |    1 -
 include/alchemy/queue.h             |    1 -
 include/alchemy/sem.h               |    1 -
 include/alchemy/task.h              |    1 -
 include/alchemy/timer.h             |    1 -
 lib/alchemy/alarm.c                 |   25 ++---
 lib/alchemy/buffer.c                |   61 +++++------
 lib/alchemy/cond.c                  |   53 ++++------
 lib/alchemy/event.c                 |   53 ++++------
 lib/alchemy/heap.c                  |   42 ++++----
 lib/alchemy/mutex.c                 |   53 ++++------
 lib/alchemy/pipe.c                  |   83 ++++++++++-----
 lib/alchemy/queue.c                 |   84 +++++++---------
 lib/alchemy/sem.c                   |   49 ++++-----
 lib/alchemy/task.c                  |  190 +++++++++++++++--------------------
 lib/alchemy/timer.c                 |   25 +----
 lib/copperplate/init.c              |   62 ++++++++++++
 27 files changed, 483 insertions(+), 506 deletions(-)

diff --git a/aclocal.m4 b/aclocal.m4
index f473e28..d7bb46a 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -220,21 +220,6 @@ m4_popdef([pkg_default])
 m4_popdef([pkg_description])
 ]) dnl PKG_NOARCH_INSTALLDIR
 
-
-# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
-# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
-# -------------------------------------------
-# Retrieves the value of the pkg-config variable for the given module.
-AC_DEFUN([PKG_CHECK_VAR],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
-AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
-
-_PKG_CONFIG([$1], [variable="][$3]["], [$2])
-AS_VAR_COPY([$1], [pkg_cv_][$1])
-
-AS_VAR_IF([$1], [""], [$5], [$4])dnl
-])# PKG_CHECK_VAR
-
 # Copyright (C) 2002-2013 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
diff --git a/config/config.guess b/config/config.guess
index 1804e9f..b79252d 100755
--- a/config/config.guess
+++ b/config/config.guess
@@ -1,10 +1,8 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-#   2011, 2012, 2013 Free Software Foundation, Inc.
+#   Copyright 1992-2013 Free Software Foundation, Inc.
 
-timestamp='2012-12-29'
+timestamp='2013-06-10'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -26,7 +24,7 @@ timestamp='2012-12-29'
 # program.  This Exception is an additional permission under section 7
 # of the GNU General Public License, version 3 ("GPLv3").
 #
-# Originally written by Per Bothner. 
+# Originally written by Per Bothner.
 #
 # You can get the latest version of this script from:
 # 
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
@@ -52,9 +50,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
-2012, 2013 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -136,6 +132,27 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || 
UNAME_RELEASE=unknown
 UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+       # If the system lacks a compiler, then just pick glibc.
+       # We could probably try harder.
+       LIBC=gnu
+
+       eval $set_cc_for_build
+       cat <<-EOF > $dummy.c
+       #include <features.h>
+       #if defined(__UCLIBC__)
+       LIBC=uclibc
+       #elif defined(__dietlibc__)
+       LIBC=dietlibc
+       #else
+       LIBC=gnu
+       #endif
+       EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+       ;;
+esac
+
 # Note: order is significant - the case branches are not exclusive.
 
 case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
@@ -857,21 +874,21 @@ EOF
        exit ;;
     *:GNU:*:*)
        # the GNU system
-       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo 
${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo 
${UNAME_RELEASE}|sed -e 's,/.*$,,'`
        exit ;;
     *:GNU/*:*:*)
        # other systems with GNU libc and userland
-       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' 
| tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' 
| tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
        exit ;;
     i*86:Minix:*:*)
        echo ${UNAME_MACHINE}-pc-minix
        exit ;;
     aarch64:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     aarch64_be:Linux:*:*)
        UNAME_MACHINE=aarch64_be
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     alpha:Linux:*:*)
        case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -884,59 +901,54 @@ EOF
          EV68*) UNAME_MACHINE=alphaev68 ;;
        esac
        objdump --private-headers /bin/sh | grep -q ld.so.1
-       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
-       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     arm*:Linux:*:*)
        eval $set_cc_for_build
        if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
            | grep -q __ARM_EABI__
        then
-           echo ${UNAME_MACHINE}-unknown-linux-gnu
+           echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        else
            if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
                | grep -q __ARM_PCS_VFP
            then
-               echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+               echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
            else
-               echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
+               echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
            fi
        fi
        exit ;;
     avr32*:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     cris:Linux:*:*)
-       echo ${UNAME_MACHINE}-axis-linux-gnu
+       echo ${UNAME_MACHINE}-axis-linux-${LIBC}
        exit ;;
     crisv32:Linux:*:*)
-       echo ${UNAME_MACHINE}-axis-linux-gnu
+       echo ${UNAME_MACHINE}-axis-linux-${LIBC}
        exit ;;
     frv:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     hexagon:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     i*86:Linux:*:*)
-       LIBC=gnu
-       eval $set_cc_for_build
-       sed 's/^        //' << EOF >$dummy.c
-       #ifdef __dietlibc__
-       LIBC=dietlibc
-       #endif
-EOF
-       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
-       echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+       echo ${UNAME_MACHINE}-pc-linux-${LIBC}
        exit ;;
     ia64:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     m32r*:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     m68*:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     mips:Linux:*:* | mips64:Linux:*:*)
        eval $set_cc_for_build
@@ -955,54 +967,63 @@ EOF
        #endif
 EOF
        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
-       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
        ;;
+    or1k:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+       exit ;;
     or32:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     padre:Linux:*:*)
-       echo sparc-unknown-linux-gnu
+       echo sparc-unknown-linux-${LIBC}
        exit ;;
     parisc64:Linux:*:* | hppa64:Linux:*:*)
-       echo hppa64-unknown-linux-gnu
+       echo hppa64-unknown-linux-${LIBC}
        exit ;;
     parisc:Linux:*:* | hppa:Linux:*:*)
        # Look for CPU level
        case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
-         PA7*) echo hppa1.1-unknown-linux-gnu ;;
-         PA8*) echo hppa2.0-unknown-linux-gnu ;;
-         *)    echo hppa-unknown-linux-gnu ;;
+         PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+         PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+         *)    echo hppa-unknown-linux-${LIBC} ;;
        esac
        exit ;;
     ppc64:Linux:*:*)
-       echo powerpc64-unknown-linux-gnu
+       echo powerpc64-unknown-linux-${LIBC}
        exit ;;
     ppc:Linux:*:*)
-       echo powerpc-unknown-linux-gnu
+       echo powerpc-unknown-linux-${LIBC}
+       exit ;;
+    ppc64le:Linux:*:*)
+       echo powerpc64le-unknown-linux-${LIBC}
+       exit ;;
+    ppcle:Linux:*:*)
+       echo powerpcle-unknown-linux-${LIBC}
        exit ;;
     s390:Linux:*:* | s390x:Linux:*:*)
-       echo ${UNAME_MACHINE}-ibm-linux
+       echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
        exit ;;
     sh64*:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     sh*:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     sparc:Linux:*:* | sparc64:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     tile*:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     vax:Linux:*:*)
-       echo ${UNAME_MACHINE}-dec-linux-gnu
+       echo ${UNAME_MACHINE}-dec-linux-${LIBC}
        exit ;;
     x86_64:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     xtensa*:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
        exit ;;
     i*86:DYNIX/ptx:4*:*)
        # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -1235,19 +1256,21 @@ EOF
        exit ;;
     *:Darwin:*:*)
        UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-       case $UNAME_PROCESSOR in
-           i386)
-               eval $set_cc_for_build
-               if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
-                 if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo 
'#endif') | \
-                     (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
-                     grep IS_64BIT_ARCH >/dev/null
-                 then
-                     UNAME_PROCESSOR="x86_64"
-                 fi
-               fi ;;
-           unknown) UNAME_PROCESSOR=powerpc ;;
-       esac
+       eval $set_cc_for_build
+       if test "$UNAME_PROCESSOR" = unknown ; then
+           UNAME_PROCESSOR=powerpc
+       fi
+       if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+           if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+               (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+               grep IS_64BIT_ARCH >/dev/null
+           then
+               case $UNAME_PROCESSOR in
+                   i386) UNAME_PROCESSOR=x86_64 ;;
+                   powerpc) UNAME_PROCESSOR=powerpc64 ;;
+               esac
+           fi
+       fi
        echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
        exit ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
diff --git a/config/config.sub b/config/config.sub
index 52f04bc..c765b34 100755
--- a/config/config.sub
+++ b/config/config.sub
@@ -1,10 +1,8 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-#   2011, 2012, 2013 Free Software Foundation, Inc.
+#   Copyright 1992-2013 Free Software Foundation, Inc.
 
-timestamp='2012-12-29'
+timestamp='2013-04-24'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -70,9 +68,7 @@ Report bugs and patches to <config-patc...@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
-2012, 2013 Free Software Foundation, Inc.
+Copyright 1992-2013 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -256,7 +252,7 @@ case $basic_machine in
        | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
        | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | 
alpha64pca5[67] \
        | am33_2.0 \
-       | arc \
+       | arc | arceb \
        | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
        | avr | avr32 \
        | be32 | be64 \
@@ -290,16 +286,17 @@ case $basic_machine in
        | mipsisa64r2 | mipsisa64r2el \
        | mipsisa64sb1 | mipsisa64sb1el \
        | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipsr5900 | mipsr5900el \
        | mipstx39 | mipstx39el \
        | mn10200 | mn10300 \
        | moxie \
        | mt \
        | msp430 \
        | nds32 | nds32le | nds32be \
-       | nios | nios2 \
+       | nios | nios2 | nios2eb | nios2el \
        | ns16k | ns32k \
        | open8 \
-       | or32 \
+       | or1k | or32 \
        | pdp10 | pdp11 | pj | pjl \
        | powerpc | powerpc64 | powerpc64le | powerpcle \
        | pyramid \
@@ -369,7 +366,7 @@ case $basic_machine in
        | aarch64-* | aarch64_be-* \
        | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
        | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
-       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
        | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
        | avr-* | avr32-* \
        | be32-* | be64-* \
@@ -407,12 +404,13 @@ case $basic_machine in
        | mipsisa64r2-* | mipsisa64r2el-* \
        | mipsisa64sb1-* | mipsisa64sb1el-* \
        | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipsr5900-* | mipsr5900el-* \
        | mipstx39-* | mipstx39el-* \
        | mmix-* \
        | mt-* \
        | msp430-* \
        | nds32-* | nds32le-* | nds32be-* \
-       | nios-* | nios2-* \
+       | nios-* | nios2-* | nios2eb-* | nios2el-* \
        | none-* | np1-* | ns16k-* | ns32k-* \
        | open8-* \
        | orion-* \
@@ -1354,7 +1352,7 @@ case $os in
        -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
              | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | 
-sunos[34]*\
              | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | 
-solaris* \
-             | -sym* | -kopensolaris* \
+             | -sym* | -kopensolaris* | -plan9* \
              | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
              | -aos* | -aros* \
              | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
@@ -1500,9 +1498,6 @@ case $os in
        -aros*)
                os=-aros
                ;;
-       -kaos*)
-               os=-kaos
-               ;;
        -zvmoe)
                os=-zvmoe
                ;;
@@ -1594,6 +1589,9 @@ case $basic_machine in
        mips*-*)
                os=-elf
                ;;
+       or1k-*)
+               os=-elf
+               ;;
        or32-*)
                os=-coff
                ;;
diff --git a/doc/doxygen/xeno3prm-common.conf.in 
b/doc/doxygen/xeno3prm-common.conf.in
index f0c8fc8..c6d0046 100644
--- a/doc/doxygen/xeno3prm-common.conf.in
+++ b/doc/doxygen/xeno3prm-common.conf.in
@@ -132,6 +132,7 @@ TAB_SIZE               = 8
 
 ALIASES                = \
                       "coretags{1}=@par Tags\n@ref cobalt-core-tags \"\1\""    
\
+                      "apitags{1}=@par Tags\n@ref api-tags \"\1\""     \
                       "sideeffect=@par Side effects\n"
 
 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
sources 
@@ -865,6 +866,7 @@ INPUT                  =                                    
        \
                       @top_srcdir@/kernel/cobalt                       \
                       @top_srcdir@/kernel/drivers                      \
                       @top_srcdir@/lib/cobalt                          \
+                      @top_srcdir@/lib/copperplate                     \
                       @top_srcdir@/lib/smokey                          \
                       @top_srcdir@/lib/analogy                         \
                       @top_srcdir@/lib/alchemy                         \
diff --git a/include/alchemy/alarm.h b/include/alchemy/alarm.h
index 6a8e623..c6f4b8a 100644
--- a/include/alchemy/alarm.h
+++ b/include/alchemy/alarm.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_ALARM_H
 #define _XENOMAI_ALCHEMY_ALARM_H
 
diff --git a/include/alchemy/buffer.h b/include/alchemy/buffer.h
index c384190..9c0c4e6 100644
--- a/include/alchemy/buffer.h
+++ b/include/alchemy/buffer.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_BUFFER_H
 #define _XENOMAI_ALCHEMY_BUFFER_H
 
diff --git a/include/alchemy/cond.h b/include/alchemy/cond.h
index 7c4f1d0..7043179 100644
--- a/include/alchemy/cond.h
+++ b/include/alchemy/cond.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_COND_H
 #define _XENOMAI_ALCHEMY_COND_H
 
diff --git a/include/alchemy/event.h b/include/alchemy/event.h
index 8d439ed..227f108 100644
--- a/include/alchemy/event.h
+++ b/include/alchemy/event.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_EVENT_H
 #define _XENOMAI_ALCHEMY_EVENT_H
 
diff --git a/include/alchemy/heap.h b/include/alchemy/heap.h
index 113c55f..998cb8c 100644
--- a/include/alchemy/heap.h
+++ b/include/alchemy/heap.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_HEAP_H
 #define _XENOMAI_ALCHEMY_HEAP_H
 
diff --git a/include/alchemy/mutex.h b/include/alchemy/mutex.h
index 0563f45..9cb0472 100644
--- a/include/alchemy/mutex.h
+++ b/include/alchemy/mutex.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_MUTEX_H
 #define _XENOMAI_ALCHEMY_MUTEX_H
 
diff --git a/include/alchemy/pipe.h b/include/alchemy/pipe.h
index 61bf24b..4be8f85 100644
--- a/include/alchemy/pipe.h
+++ b/include/alchemy/pipe.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_PIPE_H
 #define _XENOMAI_ALCHEMY_PIPE_H
 
diff --git a/include/alchemy/queue.h b/include/alchemy/queue.h
index afeb1ab..4cd2d70 100644
--- a/include/alchemy/queue.h
+++ b/include/alchemy/queue.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_QUEUE_H
 #define _XENOMAI_ALCHEMY_QUEUE_H
 
diff --git a/include/alchemy/sem.h b/include/alchemy/sem.h
index ef01f89..9181e95 100644
--- a/include/alchemy/sem.h
+++ b/include/alchemy/sem.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_SEM_H
 #define _XENOMAI_ALCHEMY_SEM_H
 
diff --git a/include/alchemy/task.h b/include/alchemy/task.h
index cf8824e..fc5700c 100644
--- a/include/alchemy/task.h
+++ b/include/alchemy/task.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_TASK_H
 #define _XENOMAI_ALCHEMY_TASK_H
 
diff --git a/include/alchemy/timer.h b/include/alchemy/timer.h
index 66b8ffa..c85d80f 100644
--- a/include/alchemy/timer.h
+++ b/include/alchemy/timer.h
@@ -15,7 +15,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
-
 #ifndef _XENOMAI_ALCHEMY_TIMER_H
 #define _XENOMAI_ALCHEMY_TIMER_H
 
diff --git a/lib/alchemy/alarm.c b/lib/alchemy/alarm.c
index 53ab0a4..a443d42 100644
--- a/lib/alchemy/alarm.c
+++ b/lib/alchemy/alarm.c
@@ -158,10 +158,7 @@ static void alarm_handler(struct timerobj *tmobj)
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  *
  * @note Alarms are process-private objects and thus cannot be shared
  * by multiple processes, even if they belong to the same Xenomai
@@ -228,7 +225,7 @@ out:
  * This routine deletes an alarm object previously created by a call
  * to rt_alarm_create().
  *
- * @param alarm The descriptor address of the deleted alarm.
+ * @param alarm The alarm descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -237,10 +234,7 @@ out:
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling contexts:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  */
 int rt_alarm_delete(RT_ALARM *alarm)
 {
@@ -281,7 +275,7 @@ out:
  * This service overrides any previous setup of the expiry date and
  * reload interval for the alarm.
  *
- * @param alarm The descriptor address of the started alarm.
+ * @param alarm The alarm descriptor.
  *
  * @param value The relative date of the first expiry, expressed in
  * clock ticks (see note).
@@ -295,7 +289,7 @@ out:
  *
  * - -EINVAL is returned if @a alarm is not a valid alarm descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  *
  * @note Each of the initial @a value and @a interval is interpreted
  * as a multiple of the Alchemy clock resolution (see
@@ -332,13 +326,13 @@ out:
  * This routine disables an alarm object, preventing any further
  * expiry until it is re-enabled via rt_alarm_start().
  *
- * @param alarm The descriptor address of the stopped alarm.
+ * @param alarm The alarm descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
  * - -EINVAL is returned if @a alarm is not a valid alarm descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_alarm_stop(RT_ALARM *alarm)
 {
@@ -367,8 +361,7 @@ out:
  * This routine returns the status information about the specified @a
  * alarm.
  *
- * @param alarm The descriptor address of the alarm to get the status
- * of.
+ * @param alarm The alarm descriptor.
  *
  * @param info A pointer to the @ref RT_ALARM_INFO "return
  * buffer" to copy the information to.
@@ -378,7 +371,7 @@ out:
  *
  * - -EINVAL is returned if @a alarm is not a valid alarm descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_alarm_inquire(RT_ALARM *alarm, RT_ALARM_INFO *info)
 {
diff --git a/lib/alchemy/buffer.c b/lib/alchemy/buffer.c
index 7e24467..f70e9f3 100644
--- a/lib/alchemy/buffer.c
+++ b/lib/alchemy/buffer.c
@@ -205,10 +205,7 @@ fnref_register(libalchemy, buffer_finalize);
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  *
  * @note Buffers can be shared by multiple processes which belong to
  * the same Xenomai session.
@@ -296,7 +293,7 @@ fail:
  * This routine deletes a buffer object previously created by a call
  * to rt_buffer_create().
  *
- * @param bf The descriptor address of the deleted buffer.
+ * @param bf The buffer descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -305,10 +302,7 @@ fail:
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  */
 int rt_buffer_delete(RT_BUFFER *bf)
 {
@@ -342,7 +336,7 @@ out:
  * This routine is a variant of rt_buffer_read_timed() accepting a
  * relative timeout specification expressed as a scalar value.
  *
- * @param bf The descriptor address of the buffer to read from.
+ * @param bf The buffer descriptor.
  *
  * @param ptr A pointer to a memory area which will be written upon
  * success with the received data.
@@ -351,6 +345,8 @@ out:
  * ptr.
  *
  * @param timeout A delay expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -360,7 +356,7 @@ out:
  * This routine is a variant of rt_buffer_read_timed() accepting an
  * absolute timeout specification expressed as a scalar value.
  *
- * @param bf The descriptor address of the buffer to read from.
+ * @param bf The buffer descriptor.
  *
  * @param ptr A pointer to a memory area which will be written upon
  * success with the received data.
@@ -369,6 +365,8 @@ out:
  * ptr.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -379,7 +377,7 @@ out:
  * no message is available on entry, the caller is allowed to block
  * until enough data is written to the buffer, or a timeout elapses.
  *
- * @param bf The descriptor address of the buffer to read from.
+ * @param bf The buffer descriptor.
  *
  * @param ptr A pointer to a memory area which will be written upon
  * success with the received data.
@@ -442,11 +440,7 @@ out:
  * that case arises, thread priorities, buffer and/or message lengths
  * should likely be fixed, in order to eliminate such condition.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a abs_timeout is { .tv_sec = 0,
- * .tv_nsec = 0 }.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -579,7 +573,7 @@ out:
  * This routine is a variant of rt_buffer_write_timed() accepting a
  * relative timeout specification expressed as a scalar value.
  *
- * @param bf The descriptor address of the buffer to write to.
+ * @param bf The buffer descriptor.
  *
  * @param ptr The address of the message data to be written to the
  * buffer.
@@ -587,6 +581,8 @@ out:
  * @param len The length in bytes of the message data.
  *
  * @param timeout A delay expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -596,7 +592,7 @@ out:
  * This routine is a variant of rt_buffer_write_timed() accepting an
  * absolute timeout specification expressed as a scalar value.
  *
- * @param bf The descriptor address of the buffer to write to.
+ * @param bf The buffer descriptor.
  *
  * @param ptr The address of the message data to be written to the
  * buffer.
@@ -604,6 +600,8 @@ out:
  * @param len The length in bytes of the message data.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -615,7 +613,7 @@ out:
  * caller is allowed to block until enough room is freed, or a timeout
  * elapses, whichever comes first.
  *
- * @param bf The descriptor address of the buffer to write to.
+ * @param bf The buffer descriptor.
  *
  * @param ptr The address of the message data to be written to the
  * buffer.
@@ -657,10 +655,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a abs_timeout is { .tv_sec = 0, .tv_nsec = 0 } .
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -798,13 +793,13 @@ out:
  *
  * This routine empties a buffer from any data.
  *
- * @param bf The descriptor address of the buffer to clear.
+ * @param bf The buffer descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
  * - -EINVAL is returned if @a bf is not a valid buffer descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_buffer_clear(RT_BUFFER *bf)
 {
@@ -838,8 +833,7 @@ out:
  * This routine returns the status information about the specified
  * buffer.
  *
- * @param bf The descriptor address of the buffer to get the status
- * of.
+ * @param bf The buffer descriptor.
  *
  * @param info A pointer to the @ref RT_BUFFER_INFO "return
  * buffer" to copy the information to.
@@ -849,7 +843,7 @@ out:
  *
  * - -EINVAL is returned if @a bf is not a valid buffer descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_buffer_inquire(RT_BUFFER *bf, RT_BUFFER_INFO *info)
 {
@@ -914,10 +908,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a timeout equals TM_NONBLOCK.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note The @a timeout value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -937,11 +928,13 @@ int rt_buffer_bind(RT_BUFFER *bf,
  * @fn int rt_buffer_unbind(RT_BUFFER *bf)
  * @brief Unbind from an IPC buffer.
  *
- * @param bf The descriptor address of the buffer to unbind from.
+ * @param bf The buffer descriptor.
  *
  * This routine releases a previous binding to an IPC buffer. After
  * this call has returned, the descriptor is no more valid for
  * referencing this object.
+ *
+ * @apitags{thread-unrestricted}
  */
 int rt_buffer_unbind(RT_BUFFER *bf)
 {
diff --git a/lib/alchemy/cond.c b/lib/alchemy/cond.c
index e497f47..79c941d 100644
--- a/lib/alchemy/cond.c
+++ b/lib/alchemy/cond.c
@@ -98,10 +98,7 @@ static struct registry_operations registry_ops;
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  *
  * @note Condition variables can be shared by multiple processes which
  * belong to the same Xenomai session.
@@ -167,7 +164,7 @@ out:
  * This routine deletes a condition variable object previously created
  * by a call to rt_cond_create().
  *
- * @param cond The descriptor address of the deleted condition variable.
+ * @param cond The condition variable descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -182,10 +179,7 @@ out:
  * being used in a rt_cond_wait(), rt_cond_wait_timed() or
  * rt_cond_wait_until() by another task).
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  */
 int rt_cond_delete(RT_COND *cond)
 {
@@ -224,14 +218,14 @@ out:
  * immediately unblocks the first waiting task (by queuing priority
  * order).
  *
- * @param cond The descriptor address of the condition variable to signal.
+ * @param cond The condition variable descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
  * - -EINVAL is returned if @a cond is not a valid condition variable
  * descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_cond_signal(RT_COND *cond)
 {
@@ -252,15 +246,14 @@ int rt_cond_signal(RT_COND *cond)
  * All tasks currently waiting on the condition variable are
  * immediately unblocked.
  *
- * @param cond The descriptor address of the condition variable to
- * broadcast.
+ * @param cond The condition variable descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
  * - -EINVAL is returned if @a cond is not a valid condition variable
  * descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_cond_broadcast(RT_COND *cond)
 {
@@ -281,13 +274,14 @@ int rt_cond_broadcast(RT_COND *cond)
  * This routine is a variant of rt_cond_wait_timed() accepting a
  * relative timeout specification expressed as a scalar value.
  *
- * @param cond The descriptor address of the condition variable to
- * wait on.
+ * @param cond The condition variable descriptor.
  *
  * @param mutex The address of the mutex serializing the access to the
  * shared data.
  *
  * @param timeout A delay expressed in clock ticks.
+ *
+ * @apitags{xthread-only, switch-primary}
  */
 
 /**
@@ -297,13 +291,14 @@ int rt_cond_broadcast(RT_COND *cond)
  * This routine is a variant of rt_cond_wait_timed() accepting an
  * abs_timeout specification expressed as a scalar value.
  *
- * @param cond The descriptor address of the condition variable to
- * wait on.
+ * @param cond The condition variable descriptor.
  *
  * @param mutex The address of the mutex serializing the access to the
  * shared data.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-only, switch-primary}
  */
 
 /**
@@ -315,8 +310,7 @@ int rt_cond_broadcast(RT_COND *cond)
  * occurs, whichever comes first. The mutex is re-acquired before
  * returning from this service.
  *
- * @param cond The descriptor address of the condition variable to
- * wait on.
+ * @param cond The condition variable descriptor.
  *
  * @param mutex The address of the mutex serializing the access to the
  * shared data.
@@ -347,9 +341,7 @@ int rt_cond_broadcast(RT_COND *cond)
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
+ * @apitags{xthread-only, switch-primary}
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -389,8 +381,7 @@ int rt_cond_wait_timed(RT_COND *cond, RT_MUTEX *mutex,
  * This routine returns the status information about the specified
  * condition variable.
  *
- * @param cond The descriptor address of the condition variable to get
- * the status of.
+ * @param cond The condition variable descriptor.
  *
  * @param info A pointer to the @ref RT_COND_INFO "return
  * buffer" to copy the information to.
@@ -401,7 +392,7 @@ int rt_cond_wait_timed(RT_COND *cond, RT_MUTEX *mutex,
  * - -EINVAL is returned if @a cond is not a valid condition variable
  * descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_cond_inquire(RT_COND *cond, RT_COND_INFO *info)
 {
@@ -455,10 +446,7 @@ int rt_cond_inquire(RT_COND *cond, RT_COND_INFO *info)
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a timeout equals TM_NONBLOCK.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note The @a timeout value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -478,12 +466,13 @@ int rt_cond_bind(RT_COND *cond,
  * @fn int rt_cond_unbind(RT_COND *cond)
  * @brief Unbind from a condition variable.
  *
- * @param cond The descriptor address of the condition variable to
- * unbind from.
+ * @param cond The condition variable descriptor.
  *
  * This routine releases a previous binding to a condition
  * variable. After this call has returned, the descriptor is no more
  * valid for referencing this object.
+ *
+ * @apitags{thread-unrestricted}
  */
 int rt_cond_unbind(RT_COND *cond)
 {
diff --git a/lib/alchemy/event.c b/lib/alchemy/event.c
index cd3a4b5..e2b7313 100644
--- a/lib/alchemy/event.c
+++ b/lib/alchemy/event.c
@@ -160,10 +160,7 @@ fnref_register(libalchemy, event_finalize);
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  *
  * @note Event flag groups can be shared by multiple processes which
  * belong to the same Xenomai session.
@@ -232,7 +229,7 @@ out:
  * This routine deletes a event flag group previously created by a
  * call to rt_event_create().
  *
- * @param event The descriptor address of the deleted object.
+ * @param event The event descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -242,10 +239,7 @@ out:
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  */
 int rt_event_delete(RT_EVENT *event)
 {
@@ -284,8 +278,7 @@ out:
  * This routine is a variant of rt_event_wait_timed() accepting a
  * relative timeout specification expressed as a scalar value.
  *
- * @param event The descriptor address of the event flag group to wait
- * on.
+ * @param event The event descriptor.
  *
  * @param mask The set of bits to wait for.
  *
@@ -295,6 +288,8 @@ out:
  * @param mode The pend mode.
  *
  * @param timeout A delay expressed in clock ticks,
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -304,8 +299,7 @@ out:
  * This routine is a variant of rt_event_wait_timed() accepting an
  * absolute timeout specification expressed as a scalar value.
  *
- * @param event The descriptor address of the event flag group to wait
- * on.
+ * @param event The event descriptor.
  *
  * @param mask The set of bits to wait for.
  *
@@ -315,6 +309,8 @@ out:
  * @param mode The pend mode.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -324,8 +320,7 @@ out:
  * Waits for one or more events to be signaled in @a event, or until a
  * timeout elapses.
  *
- * @param event The descriptor address of the event flag group to wait
- * on.
+ * @param event The event descriptor.
  *
  * @param mask The set of bits to wait for. Passing zero causes this
  * service to return immediately with a success value; the current
@@ -374,11 +369,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads.
- * - Any other context if @a abs_timeout is { .tv_sec = 0, .tv_nsec =
- * 0 }.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note @a abs_timeout value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -423,7 +414,7 @@ out:
  * request satisfied as a result of this operation are immediately
  * readied.
  *
- * @param event The descriptor address of the event flag group to signal.
+ * @param event The event descriptor.
  *
  * @param mask The set of events to be posted.
  *
@@ -432,7 +423,7 @@ out:
  * - -EINVAL is returned if @a event is not an event flag group
  * descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_event_signal(RT_EVENT *event, unsigned long mask)
 {
@@ -459,7 +450,7 @@ out:
  *
  * This routine clears a set of flags from @a event.
  *
- * @param event The descriptor address of the affected event.
+ * @param event The event descriptor.
  *
  * @param mask The set of event flags to be cleared.
  *
@@ -472,7 +463,7 @@ out:
  * - -EINVAL is returned if @a event is not a valid event flag group
  * descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_event_clear(RT_EVENT *event,
                   unsigned long mask, unsigned long *mask_r)
@@ -500,8 +491,7 @@ out:
  *
  * This routine returns the status information about @a event.
  *
- * @param event The descriptor address of the event flag group to get
- * the status of.
+ * @param event The event descriptor.
  *
  * @param info A pointer to the @ref RT_EVENT_INFO "return
  * buffer" to copy the information to.
@@ -512,7 +502,7 @@ out:
  * - -EINVAL is returned if @a event is not a valid event flag group
  * descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_event_inquire(RT_EVENT *event, RT_EVENT_INFO *info)
 {
@@ -577,10 +567,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a timeout equals TM_NONBLOCK.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note The @a timeout value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -600,11 +587,13 @@ int rt_event_bind(RT_EVENT *event,
  * @fn int rt_event_unbind(RT_EVENT *event)
  * @brief Unbind from an event flag group.
  *
- * @param event The descriptor address of the object to unbind from.
+ * @param event The event descriptor.
  *
  * This routine releases a previous binding to an event flag
  * group. After this call has returned, the descriptor is no more
  * valid for referencing this object.
+ *
+ * @apitags{thread-unrestricted}
  */
 int rt_event_unbind(RT_EVENT *event)
 {
diff --git a/lib/alchemy/heap.c b/lib/alchemy/heap.c
index d9a69c3..a4edf93 100644
--- a/lib/alchemy/heap.c
+++ b/lib/alchemy/heap.c
@@ -207,10 +207,7 @@ fnref_register(libalchemy, heap_finalize);
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  *
  * @note Heaps can be shared by multiple processes which belong to the
  * same Xenomai session.
@@ -298,7 +295,7 @@ fail_cballoc:
  * This routine deletes a heap object previously created by a call to
  * rt_heap_create(), releasing all tasks currently blocked on it.
  *
- * @param heap The descriptor address of the deleted heap.
+ * @param heap The heap descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -307,10 +304,7 @@ fail_cballoc:
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  */
 int rt_heap_delete(RT_HEAP *heap)
 {
@@ -343,6 +337,8 @@ out:
  *
  * This routine is a variant of rt_heap_alloc_timed() accepting a
  * relative timeout specification expressed as a scalar value.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -351,6 +347,8 @@ out:
  *
  * This routine is a variant of rt_heap_alloc_timed() accepting an
  * absolute timeout specification expressed as a scalar value.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -363,7 +361,7 @@ out:
  * available on entry to this service, tasks may be blocked until
  * their allocation request can be fulfilled.
  *
- * @param heap The descriptor address of the heap to allocate from.
+ * @param heap The heap descriptor.
  *
  * @param size The requested size (in bytes) of the block. If the heap
  * is managed as a single-block area (H_SINGLE), this value can be
@@ -407,10 +405,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a abs_timeout is { .tv_sec = 0, .tv_nsec = 0 }.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -494,8 +489,7 @@ out:
  * on rt_heap_alloc() is made once @a block is returned to the memory
  * pool.
  *
- * @param heap The descriptor address of the heap to release the block
- * to.
+ * @param heap The heap descriptor.
  *
  * @param block The address of the block to free.
  *
@@ -505,7 +499,7 @@ out:
  * @a block is not a valid block previously allocated by the
  * rt_heap_alloc() service from @a heap.
  *
- * Valid calling contexts: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_heap_free(RT_HEAP *heap, void *block)
 {
@@ -558,8 +552,7 @@ out:
  *
  * This routine returns the status information about @a heap.
  *
- * @param heap The descriptor address of the heap to get the status
- * of.
+ * @param heap The heap descriptor.
  *
  * @param info A pointer to the @ref RT_HEAP_INFO "return
  * buffer" to copy the information to.
@@ -569,7 +562,7 @@ out:
  *
  * - -EINVAL is returned if @a heap is not a valid heap descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_heap_inquire(RT_HEAP *heap, RT_HEAP_INFO *info)
 {
@@ -634,10 +627,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a timeout equals TM_NONBLOCK.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note The @a timeout value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -657,11 +647,13 @@ int rt_heap_bind(RT_HEAP *heap,
  * @fn int rt_heap_unbind(RT_HEAP *heap)
  * @brief Unbind from a heap.
  *
- * @param heap The descriptor address of the heap to unbind from.
+ * @param heap The heap descriptor.
  *
  * This routine releases a previous binding to a heap. After this call
  * has returned, the descriptor is no more valid for referencing this
  * object.
+ *
+ * @apitags{thread-unrestricted}
  */
 int rt_heap_unbind(RT_HEAP *heap)
 {
diff --git a/lib/alchemy/mutex.c b/lib/alchemy/mutex.c
index b3d66e6..466278a 100644
--- a/lib/alchemy/mutex.c
+++ b/lib/alchemy/mutex.c
@@ -98,10 +98,7 @@ static struct registry_operations registry_ops;
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  *
  * @note Mutexes can be shared by multiple processes which belong to
  * the same Xenomai session.
@@ -172,7 +169,7 @@ out:
  * This routine deletes a mutex object previously created by a call to
  * rt_mutex_create().
  *
- * @param mutex The descriptor address of the deleted mutex.
+ * @param mutex The mutex descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -186,10 +183,7 @@ out:
  * being used in a rt_mutex_acquite(), rt_mutex_acquire_timed() or
  * rt_mutex_acquire_until() by another task).
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  */
 int rt_mutex_delete(RT_MUTEX *mutex)
 {
@@ -227,9 +221,11 @@ out:
  * This routine is a variant of rt_mutex_acquire_timed() accepting a
  * relative timeout specification expressed as a scalar value.
  *
- * @param mutex The descriptor address of the mutex to acquire.
+ * @param mutex The mutex descriptor.
  *
  * @param timeout A delay expressed in clock ticks.
+ *
+ * @apitags{xthread-only, switch-primary}
  */
 
 /**
@@ -239,9 +235,11 @@ out:
  * This routine is a variant of rt_mutex_acquire_timed() accepting an
  * absolute timeout specification expressed as a scalar value.
  *
- * @param mutex The descriptor address of the mutex to acquire.
+ * @param mutex The mutex descriptor.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-only, switch-primary}
  */
 
 /**
@@ -253,7 +251,7 @@ out:
  * service returns. Xenomai mutexes are implicitely recursive and
  * implement the priority inheritance protocol.
  *
- * @param mutex The descriptor address of the mutex to acquire.
+ * @param mutex The mutex descriptor.
  *
  * @param abs_timeout An absolute date expressed in clock ticks,
  * specifying a time limit to wait for the mutex to be available (see
@@ -282,14 +280,12 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
+ * @apitags{xthread-only, switch-primary}
  *
- * Core specifics:
- *
- * Over the Cobalt core, a real-time task with effective priority zero
- * keeps running in primary mode until it releases the mutex.
+ * @sideeffect
+ * Over the Cobalt core, an Alchemy task with priority zero keeps
+ * running in primary mode until it releases the mutex, at which point
+ * it is switched back to secondary mode automatically.
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -370,7 +366,7 @@ done:
  * unblocked and transfered the ownership of the mutex; otherwise, the
  * mutex is left in an unlocked state.
  *
- * @param mutex The descriptor address of the deleted mutex.
+ * @param mutex The mutex descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -380,9 +376,7 @@ done:
  * or more generally if this service was called from a context which
  * cannot own any mutex (e.g. interrupt context).
  *
- * Valid calling context:
- *
- * - Xenomai threads
+ * @apitags{xthread-only, switch-primary}
  */
 int rt_mutex_release(RT_MUTEX *mutex)
 {
@@ -404,7 +398,7 @@ int rt_mutex_release(RT_MUTEX *mutex)
  * This routine returns the status information about the specified
  * mutex.
  *
- * @param mutex The descriptor address of the mutex to get the status of.
+ * @param mutex The mutex descriptor.
  *
  * @param info A pointer to the @ref RT_MUTEX_INFO "return
  * buffer" to copy the information to.
@@ -417,9 +411,7 @@ int rt_mutex_release(RT_MUTEX *mutex)
  * - -EPERM is returned if this service is called from an interrupt
  * context.
  *
- * Valid calling context:
- *
- * - Xenomai threads
+ * @apitags{xthread-only, switch-primary}
  */
 int rt_mutex_inquire(RT_MUTEX *mutex, RT_MUTEX_INFO *info)
 {
@@ -490,10 +482,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a timeout equals TM_NONBLOCK.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note The @a timeout value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -513,7 +502,7 @@ int rt_mutex_bind(RT_MUTEX *mutex,
  * @fn int rt_mutex_unbind(RT_MUTEX *mutex)
  * @brief Unbind from a mutex.
  *
- * @param mutex The descriptor address of the mutex to unbind from.
+ * @param mutex The mutex descriptor.
  *
  * This routine releases a previous binding to a mutex. After this
  * call has returned, the descriptor is no more valid for referencing
diff --git a/lib/alchemy/pipe.c b/lib/alchemy/pipe.c
index 6d22a6b..93da9be 100644
--- a/lib/alchemy/pipe.c
+++ b/lib/alchemy/pipe.c
@@ -126,10 +126,7 @@ DEFINE_LOOKUP_PRIVATE(pipe, RT_PIPE);
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  */
 int rt_pipe_create(RT_PIPE *pipe,
                   const char *name, int minor, size_t poolsize)
@@ -223,7 +220,7 @@ out:
  * rt_pipe_create(). All resources attached to that pipe are
  * automatically released, all pending data is flushed.
  *
- * @param pipe The descriptor address of the deleted pipe.
+ * @param pipe The pipe descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -234,10 +231,7 @@ out:
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  */
 int rt_pipe_delete(RT_PIPE *pipe)
 {
@@ -277,8 +271,7 @@ out:
  * This routine is a variant of rt_queue_read_timed() accepting a
  * relative timeout specification expressed as a scalar value.
  *
- * @param pipe The descriptor address of the message pipe to read
- * from.
+ * @param pipe The pipe descriptor.
  *
  * @param buf A pointer to a memory area which will be written upon
  * success with the message received.
@@ -290,6 +283,8 @@ out:
  * other action.
  *
  * @param timeout A delay expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -299,8 +294,7 @@ out:
  * This routine is a variant of rt_queue_read_timed() accepting an
  * absolute timeout specification expressed as a scalar value.
  *
- * @param pipe The descriptor address of the message pipe to read
- * from.
+ * @param pipe The pipe descriptor.
  *
  * @param buf A pointer to a memory area which will be written upon
  * success with the message received.
@@ -312,6 +306,8 @@ out:
  * other action.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -320,8 +316,7 @@ out:
  *
  * This service reads the next available message from a given pipe.
  *
- * @param pipe The descriptor address of the message pipe to read
- * from.
+ * @param pipe The pipe descriptor.
  *
  * @param buf A pointer to a memory area which will be written upon
  * success with the message received.
@@ -361,10 +356,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a abs_timeout is { .tv_sec = 0, .tv_nsec = 0 }.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -449,7 +441,7 @@ out:
  * pointer to the raw data to be sent, instead of a canned message
  * buffer.
  *
- * @param pipe The descriptor address of the pipe to write to.
+ * @param pipe The pipe descriptor.
  *
  * @param buf The address of the first data byte to send. The
  * data will be copied to an internal buffer before transmission.
@@ -481,6 +473,8 @@ out:
  * associated special device is allowed. The output will be buffered
  * until then, only restricted by the available memory in the
  * associated buffer pool (see rt_pipe_create()).
+ *
+ * @apitags{xcontext, switch-primary}
  */
 ssize_t rt_pipe_write(RT_PIPE *pipe,
                      const void *buf, size_t size, int mode)
@@ -496,6 +490,46 @@ ssize_t rt_pipe_write(RT_PIPE *pipe,
        return do_write_pipe(pipe, buf, size, flags);
 }
 
+ /**
+ * @brief Stream bytes through a pipe.
+ *
+ * This service writes a sequence of bytes to be received from the
+ * associated special device. Unlike rt_pipe_send(), this service does
+ * not preserve message boundaries. Instead, an internal buffer is
+ * filled on the fly with the data, which will be consumed as soon as
+ * the receiver wakes up.
+ *
+ * Data buffers sent by the rt_pipe_stream() service are always
+ * transmitted in FIFO order (i.e. P_NORMAL mode).
+ *
+ * @param pipe The pipe descriptor.
+ *
+ * @param buf The address of the first data byte to send. The
+ * data will be copied to an internal buffer before transmission.
+ *
+ * @param size The size in bytes of the buffer. Zero is a valid value,
+ * in which case the service returns immediately without sending any
+ * data.
+ *
+ * @return The number of bytes sent upon success; this value may be
+ * lower than @a size, depending on the available space in the
+ * internal buffer. Otherwise:
+ *
+ * - -EINVAL is returned if @a mode is invalid or @a pipe is not a
+ * pipe descriptor.
+ *
+ * - -ENOMEM is returned if not enough buffer space is available to
+ * complete the operation.
+ *
+ * - -EIDRM is returned if @a pipe is a closed pipe descriptor.
+ *
+ * @note Writing data to a pipe before any peer has opened the
+ * associated special device is allowed. The output will be buffered
+ * until then, only restricted by the available memory in the
+ * associated buffer pool (see rt_pipe_create()).
+ *
+ * @apitags{xcontext, switch-primary}
+ */
 ssize_t rt_pipe_stream(RT_PIPE *pipe,
                       const void *buf, size_t size)
 {
@@ -539,10 +573,7 @@ ssize_t rt_pipe_stream(RT_PIPE *pipe,
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a timeout equals TM_NONBLOCK.
+ * @apitags{xthread-nowait}
  *
  * @note The @a timeout value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -562,11 +593,13 @@ int rt_pipe_bind(RT_PIPE *pipe,
  * @fn int rt_pipe_unbind(RT_PIPE *pipe)
  * @brief Unbind from a message pipe.
  *
- * @param pipe The descriptor address of the pipe to unbind from.
+ * @param pipe The pipe descriptor.
  *
  * This routine releases a previous binding to a message pipe. After
  * this call has returned, the descriptor is no more valid for
  * referencing this object.
+ *
+ * @apitags{thread-unrestricted}
  */
 int rt_pipe_unbind(RT_PIPE *pipe)
 {
diff --git a/lib/alchemy/queue.c b/lib/alchemy/queue.c
index 69d3e4e..3d4334c 100644
--- a/lib/alchemy/queue.c
+++ b/lib/alchemy/queue.c
@@ -188,10 +188,7 @@ fnref_register(libalchemy, queue_finalize);
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  *
  * @note Queues can be shared by multiple processes which belong to
  * the same Xenomai session.
@@ -301,7 +298,7 @@ fail_cballoc:
  * rt_queue_create(). All resources attached to that queue are
  * automatically released, including all pending messages.
  *
- * @param q The descriptor address of the deleted queue.
+ * @param q The queue descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -310,10 +307,7 @@ fail_cballoc:
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  */
 int rt_queue_delete(RT_QUEUE *queue)
 {
@@ -349,8 +343,7 @@ out:
  * enqueuing it by a call to rt_queue_send().  When used in pair,
  * these services provide a zero-copy interface for sending messages.
  *
- * @param q The descriptor address of the queue to allocate a buffer
- * from.
+ * @param q The queue descriptor.
  *
  * @param size The requested size in bytes of the buffer. Zero is an
  * acceptable value, which means that the message conveys no payload;
@@ -359,7 +352,7 @@ out:
  * @return The address of the allocated buffer upon success, or NULL
  * if the call fails.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 void *rt_queue_alloc(RT_QUEUE *queue, size_t size)
 {
@@ -401,8 +394,7 @@ out:
  * This service releases a message buffer to the queue's internal
  * pool.
  *
- * @param q The descriptor address of the queue to release a buffer
- * to.
+ * @param q The queue descriptor.
  *
  * @param buf The address of the message buffer to free. Even
  * zero-sized messages carrying no payload data must be freed, since
@@ -414,7 +406,7 @@ out:
  * service, or the caller did not get ownership of the message through
  * a successful return from rt_queue_receive().
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_queue_free(RT_QUEUE *queue, void *buf)
 {
@@ -467,7 +459,7 @@ out:
  * This service sends a complete message to a given queue. The message
  * must have been allocated by a previous call to rt_queue_alloc().
  *
- * @param q The descriptor address of the message queue to send to.
+ * @param q The queue descriptor.
  *
  * @param buf The address of the message buffer to be sent.  The
  * message buffer must have been allocated using the rt_queue_alloc()
@@ -508,7 +500,7 @@ out:
  * - -ENOMEM is returned if queuing the message would exceed the limit
  * defined for the queue at creation.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_queue_send(RT_QUEUE *queue,
                  const void *buf, size_t size, int mode)
@@ -587,7 +579,7 @@ out:
  * This service builds a message out of a raw data buffer, then send
  * it to a given queue.
  *
- * @param q The descriptor address of the message queue to write to.
+ * @param q The queue descriptor.
  *
  * @param buf The address of the payload data to be written to the
  * queue. The payload is copied to a message buffer allocated
@@ -624,7 +616,7 @@ out:
  * defined for the queue at creation, or if no memory can be obtained
  * to convey the message data internally.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_queue_write(RT_QUEUE *queue,
                   const void *buf, size_t size, int mode)
@@ -723,13 +715,14 @@ out:
  * This routine is a variant of rt_queue_receive_timed() accepting a
  * relative timeout specification expressed as a scalar value.
  *
- * @param q The descriptor address of the message queue to receive
- * from.
+ * @param q The queue descriptor.
  *
  * @param bufp A pointer to a memory location which will be written
  * with the address of the received message.
  *
  * @param timeout A delay expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -739,13 +732,14 @@ out:
  * This routine is a variant of rt_queue_receive_timed() accepting an
  * absolute timeout specification expressed as a scalar value.
  *
- * @param q The descriptor address of the message queue to receive
- * from.
+ * @param q The queue descriptor.
  *
  * @param bufp A pointer to a memory location which will be written
  * with the address of the received message.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -755,8 +749,7 @@ out:
  * This service receives the next available message from a given
  * queue.
  *
- * @param q The descriptor address of the message queue to receive
- * from.
+ * @param q The queue descriptor.
  *
  * @param bufp A pointer to a memory location which will be written
  * with the address of the received message, upon success. Once
@@ -793,10 +786,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a abs_timeout is { .tv_sec = 0, .tv_nsec = 0 } .
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -870,8 +860,7 @@ out:
  * This routine is a variant of rt_queue_read_timed() accepting a
  * relative timeout specification expressed as a scalar value.
  *
- * @param q The descriptor address of the message queue to read
- * from.
+ * @param q The queue descriptor.
  *
  * @param buf A pointer to a memory area which will be written upon
  * success with the received message payload.
@@ -880,6 +869,8 @@ out:
  * buf.
  *
  * @param timeout A delay expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -889,8 +880,7 @@ out:
  * This routine is a variant of rt_queue_read_timed() accepting an
  * absolute timeout specification expressed as a scalar value.
  *
- * @param q The descriptor address of the message queue to read
- * from.
+ * @param q The queue descriptor.
  *
  * @param buf A pointer to a memory area which will be written upon
  * success with the received message payload.
@@ -899,6 +889,8 @@ out:
  * buf.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -908,8 +900,7 @@ out:
  * This service reads the next available message from a given
  * queue.
  *
- * @param q The descriptor address of the message queue to read
- * from.
+ * @param q The queue descriptor.
  *
  * @param buf A pointer to a memory area which will be written upon
  * success with the received message payload. The internal message
@@ -948,10 +939,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a abs_timeout is { .tv_sec = 0, .tv_nsec = 0 }.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -1032,13 +1020,13 @@ out:
  * This routine flushes all messages currently pending in a queue,
  * releasing all message buffers appropriately.
  *
- * @param q The descriptor address of the queue to flush.
+ * @param q The queue descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
  * - -EINVAL is returned if @a q is not a valid queue descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_queue_flush(RT_QUEUE *queue)
 {
@@ -1084,8 +1072,7 @@ out:
  * This routine returns the status information about the specified
  * queue.
  *
- * @param q The descriptor address of the queue to get the status
- * of.
+ * @param q The queue descriptor.
  *
  * @param info A pointer to the @ref RT_QUEUE_INFO "return
  * buffer" to copy the information to.
@@ -1095,7 +1082,7 @@ out:
  *
  * - -EINVAL is returned if @a q is not a valid queue descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_queue_inquire(RT_QUEUE *queue, RT_QUEUE_INFO *info)
 {
@@ -1162,10 +1149,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a timeout equals TM_NONBLOCK.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note The @a timeout value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -1185,11 +1169,13 @@ int rt_queue_bind(RT_QUEUE *queue,
  * @fn int rt_queue_unbind(RT_QUEUE *q)
  * @brief Unbind from a message queue.
  *
- * @param q The descriptor address of the queue to unbind from.
+ * @param q The queue descriptor.
  *
  * This routine releases a previous binding to a message queue. After
  * this call has returned, the descriptor is no more valid for
  * referencing this object.
+ *
+ * @apitags{thread-unrestricted}
  */
 int rt_queue_unbind(RT_QUEUE *queue)
 {
diff --git a/lib/alchemy/sem.c b/lib/alchemy/sem.c
index 21ed2dc..320573c 100644
--- a/lib/alchemy/sem.c
+++ b/lib/alchemy/sem.c
@@ -170,10 +170,7 @@ fnref_register(libalchemy, sem_finalize);
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  *
  * @note Semaphores can be shared by multiple processes which belong
  * to the same Xenomai session.
@@ -249,7 +246,7 @@ out:
  * This routine deletes a semaphore previously created by a call to
  * rt_sem_create().
  *
- * @param sem The descriptor address of the deleted object.
+ * @param sem The semaphore descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -259,10 +256,7 @@ out:
  * - -EPERM is returned if this service was called from an
  * asynchronous context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-secondary}
  */
 int rt_sem_delete(RT_SEM *sem)
 {
@@ -303,9 +297,11 @@ out:
  * This routine is a variant of rt_sem_p_timed() accepting a
  * relative timeout specification expressed as a scalar value.
  *
- * @param sem The descriptor address of the semaphore to wait on.
+ * @param sem The semaphore descriptor.
  *
  * @param timeout A delay expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -315,9 +311,11 @@ out:
  * This routine is a variant of rt_sem_p_timed() accepting an
  * absolute timeout specification expressed as a scalar value.
  *
- * @param sem The descriptor address of the semaphore to wait on.
+ * @param sem The semaphore descriptor.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-nowait, switch-primary}
  */
 
 /**
@@ -330,7 +328,7 @@ out:
  * until the semaphore is either signaled or destroyed, unless a
  * non-blocking operation was required.
  *
- * @param sem The descriptor address of the semaphore to wait on.
+ * @param sem The semaphore descriptor.
  *
  * @param abs_timeout An absolute date expressed in clock ticks,
  * specifying a time limit to wait for the request to be satisfied
@@ -360,10 +358,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a abs_timeout is { .tv_sec = 0, .tv_nsec = 0 }.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -397,14 +392,14 @@ out:
  * incremented by one, unless the semaphore is used in "pulse" mode
  * (see rt_sem_create()).
  *
- * @param sem The descriptor address of the semaphore to signal.
+ * @param sem The semaphore descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
  * - -EINVAL is returned if @a sem is not a valid semaphore
  * descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted}
  */
 int rt_sem_v(RT_SEM *sem)
 {
@@ -432,14 +427,14 @@ out:
  * All tasks currently waiting on the semaphore are immediately
  * unblocked. The semaphore count is set to zero.
  *
- * @param sem The descriptor address of the semaphore to broadcast.
+ * @param sem The semaphore descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
  * - -EINVAL is returned if @a sem is not a valid semaphore
  * descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted}
  */
 int rt_sem_broadcast(RT_SEM *sem)
 {
@@ -467,8 +462,7 @@ out:
  * This routine returns the status information about the specified
  * semaphore.
  *
- * @param sem The descriptor address of the semaphore to get the
- * status of.
+ * @param sem The semaphore descriptor.
  *
  * @param info A pointer to the @ref RT_SEM_INFO "return
  * buffer" to copy the information to.
@@ -479,7 +473,7 @@ out:
  * - -EINVAL is returned if @a sem is not a valid semaphore
  * descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted}
  */
 int rt_sem_inquire(RT_SEM *sem, RT_SEM_INFO *info)
 {
@@ -543,10 +537,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a timeout equals TM_NONBLOCK.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note The @a timeout value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -566,11 +557,13 @@ int rt_sem_bind(RT_SEM *sem,
  * @fn int rt_sem_unbind(RT_SEM *sem)
  * @brief Unbind from a semaphore.
  *
- * @param sem The descriptor address of the semaphore to unbind from.
+ * @param sem The semaphore descriptor.
  *
  * This routine releases a previous binding to a semaphore. After this
  * call has returned, the descriptor is no more valid for referencing
  * this object.
+ *
+ * @apitags{thread-unrestricted}
  */
 int rt_sem_unbind(RT_SEM *sem)
 {
diff --git a/lib/alchemy/task.c b/lib/alchemy/task.c
index 26e29cb..2238934 100644
--- a/lib/alchemy/task.c
+++ b/lib/alchemy/task.c
@@ -386,23 +386,19 @@ fail_syncinit:
  * - -EEXIST is returned if the @a name is conflicting with an already
  * registered task.
  *
- * Valid calling context:
+ * @apitags{thread-unrestricted, switch-secondary}
  *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @sideeffect
+ * - When running over the Cobalt core:
  *
- * Core specifics:
- *
- * When running over the Cobalt core:
- *
- * - calling rt_task_create() causes SCHED_FIFO tasks to switch to
+ *   - calling rt_task_create() causes SCHED_FIFO tasks to switch to
  * secondary mode.
  *
- * - members of Xenomai's SCHED_FIFO class running in the primary
+ *   - members of Xenomai's SCHED_FIFO class running in the primary
  * domain have utmost priority over all Linux activities in the
  * system, including Linux interrupt handlers.
  *
- * When running over the Mercury core, the new task belongs to the
+ * - When running over the Mercury core, the new task belongs to the
  * regular POSIX SCHED_FIFO class.
  *
  * @note Tasks can be referred to from multiple processes which all
@@ -459,8 +455,7 @@ out:
  * subsequent call to rt_task_join() once successfully deleted, to
  * reclaim all resources.
  *
- * @param task The descriptor address of the deleted task, or NULL for
- * self-deletion.
+ * @param task The task descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -471,10 +466,9 @@ out:
  * when this service is called from asynchronous context, such as a
  * timer/alarm handler.
  *
- * Valid calling context:
+ * @apitags{thread-unrestricted, switch-secondary}
  *
- * - Alchemy tasks only if @a task is NULL, any thread context
- * otherwise.
+ * @note The caller must be an Alchemy task if @a task is NULL.
  */
 int rt_task_delete(RT_TASK *task)
 {
@@ -514,7 +508,7 @@ int rt_task_delete(RT_TASK *task)
  * subsequent call to rt_task_join() once successfully deleted, to
  * reclaim all resources.
  *
- * @param task The descriptor address of the task to join.
+ * @param task The task descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -528,10 +522,7 @@ int rt_task_delete(RT_TASK *task)
  * - -ESRCH is returned if @a task no longer exists or refers to task
  * created by a different process.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{thread-unrestricted, switch-primary}
  *
  * @note After successful completion of this service, it is neither
  * required nor valid to additionally invoke rt_task_delete() on the
@@ -542,7 +533,7 @@ int rt_task_join(RT_TASK *task)
        if (bad_pointer(task))
                return -EINVAL;
 
-       return -pthread_join(task->thread, NULL);
+       return -__RT(pthread_join(task->thread, NULL));
 }
 
 /**
@@ -552,8 +543,8 @@ int rt_task_join(RT_TASK *task)
  * This calls makes @a task affine to the set of CPUs defined by @a
  * cpus.
  *
- * @param task The descriptor address of the task.  If @a task is
- * NULL, the CPU affinity of the current task is changed.
+ * @param task The task descriptor.  If @a task is NULL, the CPU
+ * affinity of the current task is changed.
  *
  * @param cpus The set of CPUs @a task should be affine to.
  *
@@ -568,9 +559,9 @@ int rt_task_join(RT_TASK *task)
  * according to any restrictions that may be imposed by the "cpuset"
  * mechanism described in cpuset(7).
  *
- * Valid calling context:
+ * @apitags{thread-unrestricted, switch-secondary}
  *
- * - Alchemy tasks if @a task is NULL, any otherwise.
+ * @note The caller must be an Alchemy task if @a task is NULL.
  */
 int rt_task_set_affinity(RT_TASK *task, const cpu_set_t *cpus)
 {
@@ -606,7 +597,7 @@ out:
  * rt_task_create(). This service causes the started task to leave the
  * initial dormant state.
  *
- * @param task The descriptor address of the task to be started.
+ * @param task The task descriptor.
  *
  * @param entry The address of the task entry point.
  *
@@ -616,7 +607,7 @@ out:
  *
  * - -EINVAL is returned if @a task is not a valid task descriptor.
  *
- * Valid calling context: any.
+ * @apitags{thread-unrestricted, switch-primary}
  *
  * @note Starting an already started task leads to a nop, returning a
  * success status.
@@ -714,15 +705,10 @@ out:
  * - -EPERM is returned if this service was called from an invalid
  * context.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
+ * @apitags{pthread-only, switch-secondary}
  *
- * Core specifics:
- *
- * When running over the Cobalt core:
- *
- * - the caller always returns from this service in primary mode.
+ * @sideeffect Over the Cobalt core, the caller always returns from
+ * this service in primary mode.
  *
  * @note Tasks can be referred to from multiple processes which all
  * belong to the same Xenomai session.
@@ -789,9 +775,8 @@ undo:
  * rt_task_wait_period() to sleep until the next periodic release
  * point in the processor timeline is reached.
  *
- * @param task The descriptor address of the periodic task.  If @a
- * task is NULL, the current task is made periodic. @a task must
- * belong the current process.
+ * @param task The task descriptor.  If @a task is NULL, the current
+ * task is made periodic. @a task must belong the current process.
  *
  * @param idate The initial (absolute) date of the first release
  * point, expressed in clock ticks (see note).  If @a idate is equal
@@ -810,15 +795,14 @@ undo:
  * - -ETIMEDOUT is returned if @a idate is different from TM_INFINITE
  * and represents a date in the past.
  *
- * Valid calling contexts:
- *
- * - Alchemy tasks if @a task is NULL, any otherwise.
+ * @apitags{thread-unrestricted, switch-primary}
  *
- * Core specifics:
+ * @note The caller must be an Alchemy task if @a task is NULL.
  *
- * Over Cobalt, -EINVAL is returned if @a period is different from
- * TM_INFINITE but shorter than the scheduling latency value for the
- * target system, as available from /proc/xenomai/latency.
+ * @sideeffect Over Cobalt, -EINVAL is returned if @a period is
+ * different from TM_INFINITE but shorter than the user scheduling
+ * latency value for the target system, as displayed by
+ * /proc/xenomai/latency.
  *
  * @note The @a idate and @a period values are interpreted as a
  * multiple of the Alchemy clock resolution (see
@@ -901,9 +885,7 @@ out:
  * - -EPERM is returned if this service was called from an invalid
  * context.
  *
- * Valid calling context:
- *
- * - Alchemy tasks.
+ * @apitags{xthread-only, switch-primary}
  *
  * @note If the current release point has already been reached at the
  * time of the call, the current task immediately returns from this
@@ -911,10 +893,7 @@ out:
  */
 int rt_task_wait_period(unsigned long *overruns_r)
 {
-       struct alchemy_task *tcb;
-
-       tcb = alchemy_task_current();
-       if (tcb == NULL)
+       if (!threadobj_current_p())
                return -EPERM;
 
        return threadobj_wait_period(overruns_r);
@@ -944,9 +923,9 @@ int rt_task_wait_period(unsigned long *overruns_r)
  * - -EPERM is returned if this service was called from an invalid
  * context.
  *
- * Valid calling context:
+ * @apitags{xthread-only, switch-primary}
  *
- * - Xenomai threads
+ * @note The caller must be an Alchemy task if @a task is NULL.
  *
  * @note The @a date value is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -988,6 +967,8 @@ int rt_task_sleep_until(RTIME date)
  *
  * @return See rt_task_sleep_until().
  *
+ * @apitags{xthread-only, switch-primary}
+ *
  * @note The @a delay value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
  * defaults to 1 nanosecond).
@@ -1040,12 +1021,9 @@ int rt_task_sleep(RTIME delay)
  *
  * @return See rt_task_create().
  *
- * Valid calling context:
+ * @apitags{thread-unrestricted, switch-secondary}
  *
- * - Regular POSIX threads
- * - Xenomai threads
- *
- * Core specifics: see rt_task_create().
+ * @sideeffect see rt_task_create().
  */
 int rt_task_spawn(RT_TASK *task, const char *name,
                  int stksize, int prio, int mode,
@@ -1074,6 +1052,8 @@ int rt_task_spawn(RT_TASK *task, const char *name,
  *
  * @return A non-zero value is returned if both descriptors refer to
  * the same task, zero otherwise.
+ *
+ * @apitags{unrestricted}
  */
 int rt_task_same(RT_TASK *task1, RT_TASK *task2)
 {
@@ -1097,8 +1077,8 @@ int rt_task_same(RT_TASK *task1, RT_TASK *task2)
  * Receiving a Linux signal causes the suspended task to resume
  * immediately.
  *
- * @param task The descriptor address of the task to suspend. If @a
- * task is NULL, the current task is suspended.
+ * @param task The task descriptor. If @a task is NULL, the current
+ * task is suspended.
  *
  * @return Zero is returned upon success. Otherwise:
  *
@@ -1112,9 +1092,9 @@ int rt_task_same(RT_TASK *task1, RT_TASK *task2)
  * - -EPERM is returned if @a task is NULL and this service was called
  * from an invalid context.
  *
- * Valid calling context:
+ * @apitags{thread-unrestricted, switch-primary}
  *
- * - Alchemy tasks if @a task is NULL, any otherwise.
+ * @note The caller must be an Alchemy task if @a task is NULL.
  *
  * @note Blocked and suspended task states are cumulative. Therefore,
  * suspending a task currently waiting on a synchronization object
@@ -1152,13 +1132,13 @@ out:
  * suspended by a call to rt_task_suspend(), if the suspend nesting
  * count decrements to zero.
  *
- * @param task The descriptor address of the task to resume.
+ * @param task The task descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
  * - -EINVAL is returned if @a task is not a valid task descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  *
  * @note Blocked and suspended task states are cumulative. Therefore,
  * resuming a task currently waiting on a synchronization object
@@ -1195,12 +1175,10 @@ out:
  * Return the address of the current Alchemy task descriptor.
  *
  * @return The address of the task descriptor referring to the current
- * Alchemy task is returned upon success, or NULL if not called from an
- * valid task context.
+ * Alchemy task is returned upon success, or NULL if not called from a
+ * valid Alchemy task context.
  *
- * Valid calling context:
- *
- * - Alchemy tasks.
+ * @apitags{xthread-only}
  */
 RT_TASK *rt_task_self(void)
 {
@@ -1225,8 +1203,8 @@ RT_TASK *rt_task_self(void)
  * boost the target task might have obtained as a consequence of a
  * priority inheritance undergoing.
  *
- * @param task The descriptor address of the task to update. If @a
- * task is NULL, the priority of the current task is changed.
+ * @param task The task descriptor. If @a task is NULL, the priority
+ * of the current task is changed.
  *
  * @param prio The new priority. This value must range from [T_LOPRIO
  * .. T_HIPRIO] (inclusive) where T_LOPRIO is the lowest effective
@@ -1240,9 +1218,9 @@ RT_TASK *rt_task_self(void)
  * - -EPERM is returned if @a task is NULL and this service was called
  * from an invalid context.
  *
- * Valid calling context:
+ * @apitags{thread-unrestricted, switch-primary}
  *
- * - Alchemy tasks if @a task is NULL, any otherwise.
+ * @note The caller must be an Alchemy task if @a task is NULL.
  *
  * @note Assigning the same priority to a running or ready task moves
  * it to the end of its priority group, thus causing a manual
@@ -1287,9 +1265,7 @@ out:
  * - -EPERM is returned if this service was called from an invalid
  * context.
  *
- * Valid calling context:
- *
- * - Xenomai threads.
+ * @apitags{xthread-only, switch-primary}
  */
 int rt_task_yield(void)
 {
@@ -1314,13 +1290,13 @@ int rt_task_yield(void)
  * suspensive conditions are gone, the task becomes eligible anew for
  * scheduling.
  *
- * @param task The descriptor address of the task to unblock.
+ * @param task The task descriptor.
  *
  * @return Zero is returned upon success. Otherwise:
  *
  * - -EINVAL is returned if @a task is not a valid task descriptor.
  *
- * Valid calling context: any.
+ * @apitags{unrestricted, switch-primary}
  */
 int rt_task_unblock(RT_TASK *task)
 {
@@ -1354,9 +1330,9 @@ out:
  * In other words, rt_task_slice() should be used to toggle
  * round-robin scheduling for an Alchemy task.
  *
- * @param task The descriptor address of the task to update. If @a
- * task is NULL, the time credit of the current task is changed. @a
- * task must belong to the current process.
+ * @param task The task descriptor. If @a task is NULL, the time
+ * credit of the current task is changed. @a task must belong to the
+ * current process.
  *
  * @param quantum The round-robin quantum for the task expressed in
  * clock ticks (see note).
@@ -1369,9 +1345,9 @@ out:
  * - -EPERM is returned if @a task is NULL and this service was called
  * from an invalid context.
  *
- * Valid calling context:
+ * @apitags{thread-unrestricted, switch-primary}
  *
- * - Alchemy tasks if @a task is NULL, any otherwise.
+ * @note The caller must be an Alchemy task if @a task is NULL.
  *
  * @note The @a quantum value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -1457,9 +1433,9 @@ out:
  * - -EPERM is returned if this service was called from an invalid
  * context.
  *
- * Valid calling context:
+ * @apitags{xthread-only, switch-primary}
  *
- * - Alchemy tasks.
+ * @note The caller must be an Alchemy task.
  *
  * @note Forcing the task mode using the T_CONFORMING bit from user
  * code is almost always wrong, since the Xenomai/cobalt core handles
@@ -1504,7 +1480,7 @@ out:
  * Return various information about an Alchemy task. This service may
  * also be used to probe for task existence.
  *
- * @param task The descriptor address of the task. If @a task is NULL,
+ * @param task The task descriptor. If @a task is NULL, the
  * information about the current task is returned.
  *
  * @param info  The address of a structure the task information will be
@@ -1520,10 +1496,9 @@ out:
  * - -EPERM is returned if @a task is NULL and this service was called
  * from an invalid context.
  *
- * Valid calling context:
+ * @apitags{thread-unrestricted, switch-primary}
  *
- * - Alchemy tasks if @a task is NULL, any otherwise.
-
+ * @note The caller must be an Alchemy task if @a task is NULL.
  */
 int rt_task_inquire(RT_TASK *task, RT_TASK_INFO *info)
 {
@@ -1560,7 +1535,7 @@ out:
  * This routine is a variant of rt_task_send_timed() accepting a
  * relative timeout specification expressed as a scalar value.
  *
- * @param task The descriptor address of the recipient task.
+ * @param task The task descriptor.
  *
  * @param mcb_s The address of the message control block referring to
  * the message to be sent.
@@ -1569,6 +1544,8 @@ out:
  * referring to the reply message area.
  *
  * @param timeout A delay expressed in clock ticks.
+ *
+ * @apitags{xthread-only, switch-primary}
  */
 
 /**
@@ -1578,7 +1555,7 @@ out:
  * This routine is a variant of rt_task_send_timed() accepting an
  * absolute timeout specification expressed as a scalar value.
  *
- * @param task The descriptor address of the recipient task.
+ * @param task The task descriptor.
  *
  * @param mcb_s The address of the message control block referring to
  * the message to be sent.
@@ -1587,6 +1564,8 @@ out:
  * referring to the reply message area.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-only, switch-primary}
  */
 
 /**
@@ -1603,7 +1582,7 @@ out:
  * size of the data area to send or retrieve upon reply, in addition
  * to a user-defined operation code.
  *
- * @param task The descriptor address of the recipient task.
+ * @param task The task descriptor.
  *
  * @param mcb_s The address of the message control block referring to
  * the message to be sent. The fields from this control block should
@@ -1675,9 +1654,7 @@ out:
  * current task before any reply was received from the recipient @a
  * task.
  *
- * Valid calling context:
- *
- * - Xenomai threads
+ * @apitags{xthread-only, switch-primary}
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -1771,6 +1748,8 @@ out:
  * the receive message area.
  *
  * @param timeout A delay expressed in clock ticks.
+ *
+ * @apitags{xthread-only, switch-primary}
  */
 
 /**
@@ -1784,6 +1763,8 @@ out:
  * the receive message area.
  *
  * @param abs_timeout An absolute date expressed in clock ticks.
+ *
+ * @apitags{xthread-only, switch-primary}
  */
 
 /**
@@ -1842,9 +1823,7 @@ out:
  * - -ETIMEDOUT is returned if no message was received within the @a
  * timeout.
  *
- * Valid calling context:
- *
- * - Alchemy tasks
+ * @apitags{xthread-only, switch-primary}
  *
  * @note @a abs_timeout is interpreted as a multiple of the Alchemy
  * clock resolution (see --alchemy-clock-resolution option, defaults
@@ -1963,9 +1942,7 @@ out:
  * - -EPERM is returned if this service was called from an invalid
  * context.
  *
- * Valid calling context:
- *
- * - Alchemy tasks
+ * @apitags{xthread-only, switch-primary}
  */
 int rt_task_reply(int flowid, RT_TASK_MCB *mcb_s)
 {
@@ -2069,10 +2046,7 @@ out:
  * - -EPERM is returned if this service should block, but was not
  * called from a Xenomai thread.
  *
- * Valid calling contexts:
- *
- * - Xenomai threads
- * - Any other context if @a timeout equals TM_NONBLOCK.
+ * @apitags{xthread-nowait, switch-primary}
  *
  * @note The @a timeout value is interpreted as a multiple of the
  * Alchemy clock resolution (see --alchemy-clock-resolution option,
@@ -2092,11 +2066,13 @@ int rt_task_bind(RT_TASK *task,
  * @fn int rt_task_unbind(RT_TASK *task)
  * @brief Unbind from a task.
  *
- * @param task The descriptor address of the task to unbind from.
+ * @param task The task descriptor.
  *
  * This routine releases a previous binding to an Alchemy task. After
  * this call has returned, the descriptor is no more valid for
  * referencing this object.
+ *
+ * @apitags{thread-unrestricted}
  */
 int rt_task_unbind(RT_TASK *task)
 {
diff --git a/lib/alchemy/timer.c b/lib/alchemy/timer.c
index 4d22267..dfe4f6d 100644
--- a/lib/alchemy/timer.c
+++ b/lib/alchemy/timer.c
@@ -38,10 +38,7 @@ struct clockobj alchemy_clock;
  *
  * @return The current time expressed in clock ticks (see note).
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{unrestricted}
  *
  * @note The @a time value is a multiple of the Alchemy clock
  * resolution (see --alchemy-clock-resolution option, defaults to 1
@@ -71,10 +68,7 @@ RTIME rt_timer_read(void)
  * the --alchemy-clock-resolution option when starting the application
  * process (defaults to 1 nanosecond).
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{unrestricted}
  */
 SRTIME rt_timer_ns2ticks(SRTIME ns)
 {
@@ -96,10 +90,7 @@ SRTIME rt_timer_ns2ticks(SRTIME ns)
  * --alchemy-clock-resolution option when starting the application
  * process (defaults to 1 nanosecond).
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{unrestricted}
  */
 SRTIME rt_timer_ticks2ns(SRTIME ticks)
 {
@@ -117,10 +108,7 @@ SRTIME rt_timer_ticks2ns(SRTIME ticks)
  *
  * @return This service always returns 0.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{unrestricted}
  */
 int rt_timer_inquire(RT_TIMER_INFO *info)
 {
@@ -142,10 +130,7 @@ int rt_timer_inquire(RT_TIMER_INFO *info)
  *
  * @param ns The time to wait expressed in nanoseconds.
  *
- * Valid calling context:
- *
- * - Regular POSIX threads
- * - Xenomai threads
+ * @apitags{unrestricted}
  */
 void rt_timer_spin(RTIME ns)
 {
diff --git a/lib/copperplate/init.c b/lib/copperplate/init.c
index 6d7e722..10889e8 100644
--- a/lib/copperplate/init.c
+++ b/lib/copperplate/init.c
@@ -643,3 +643,65 @@ void copperplate_register_skin(struct copperskin *p)
 {
        pvlist_append(&p->__reserved.next, &skins);
 }
+
+/**
+ * @{
+ *
+ * @page api-tags API service tags
+ *
+ * The non-POSIX API services based on the Copperplate library may be
+ * restricted to particular calling contexts, or entail specific
+ * side-effects. This information applies to the Alchemy API services,
+ * and to all RTOS emulators as well. To describe this information,
+ * each service documented by this section bears a set of tags when
+ * applicable.
+ *
+ * The table below matches the tags used throughout the documentation
+ * with the description of their meaning for the caller.
+ *
+ * @par
+ * <b>Context tags</b>
+ * <TABLE>
+ * <TR><TH>Tag</TH> <TH>Context on entry</TH></TR>
+ * <TR><TD>xthread-only</TD>   <TD>Must be called from a Xenomai 
thread</TD></TR>
+ * <TR><TD>xhandler-only</TD>  <TD>Must be called from a Xenomai handler. See 
note.</TD></TR>
+ * <TR><TD>xcontext</TD>       <TD>May be called from any Xenomai context 
(thread or handler).</TD></TR>
+ * <TR><TD>pthread-only</TD>   <TD>Must be called from a regular POSIX 
thread</TD></TR>
+ * <TR><TD>thread-unrestricted</TD>    <TD>May be called from a Xenomai or 
regular POSIX thread indifferently</TD></TR>
+ * <TR><TD>xthread-nowait</TD> <TD>May be called from a Xenomai thread 
unrestricted, or from a regular thread as a non-blocking service only. See 
note.</TD></TR>
+ * <TR><TD>unrestricted</TD>   <TD>May be called from any context previously 
described</TD></TR>
+ * </TABLE>
+ *
+ * @note A Xenomai handler is most often used for callback-based
+ * timeout notifications. This context is @a NOT mapped to a regular
+ * Linux signal handler, it is actually underlaid by a special thread
+ * context, so that async-unsafe POSIX services may be invoked
+ * internally by the API implementation when running on behalf of such
+ * handler. Therefore, calling Xenomai API services from asynchronous
+ * regular signal handlers is fundamentally unsafe.
+ *
+ * @note A non-blocking call for an API service is defined by a
+ * special value passed as a timeout specification.
+ *
+ * @par
+ * <b>Possible side-effects over the Cobalt core (i.e. dual kernel 
configuration)</b>
+ * <TABLE>
+ * <TR><TH>Tag</TH> <TH>Description</TH></TR>
+ * <TR><TD>switch-primary</TD>         <TD>the caller may switch to primary 
mode</TD></TR>
+ * <TR><TD>switch-secondary</TD>       <TD>the caller may switch to secondary 
mode</TD></TR>
+ * </TABLE>
+ *
+ * @note As a rule of thumb, any service which might block the caller,
+ * causes a switch to primary mode if invoked from secondary
+ * mode. This rule might not apply in case the service can complete
+ * fully from user-space without any syscall entailed, due to a
+ * particular optimization (e.g. fast acquisition of semaphore
+ * resources directly from user-space in the non-contended
+ * case). Therefore, the switch-{primary, secondary} tags denote
+ * either services which _will_ always switch the caller to the mode
+ * mentioned, or _might_ have to do so, depending on the context. The
+ * absence of such tag indicates that such services can complete in
+ * either modes and as such will entail no switch.
+ *
+ * @}
+ */


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to