panthema / 2006 / SDIOS06 / sdios06 / include / l4 / message.h (Download File)
/*********************************************************************
 *                
 * Copyright (C) 2001, 2002, 2003-2004,  Karlsruhe University
 *                
 * File path:     l4/message.h
 * Description:   Message construction functions
 *                
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *                
 * $Id: message.h,v 1.26.2.4 2004/03/15 18:05:08 skoglund Exp $
 *                
 ********************************************************************/
#ifndef __L4__MESSAGE_H__
#define __L4__MESSAGE_H__

#include <l4/types.h>
#include __L4_INC_ARCH(vregs.h)

#define __L4_NUM_MRS	64
#define __L4_NUM_BRS	33

#if defined(L4_64BIT)
# define __PLUS32	+ 32
#else
# define __PLUS32
#endif




/*
 * Message tag
 */

typedef union {
    L4_Word_t	raw;
    struct {
#if defined(L4_BIG_ENDIAN)
	L4_Word_t	label:16 __PLUS32;
	L4_Word_t	flags:4;
	L4_Word_t	t:6;
	L4_Word_t	u:6;
#else
	L4_Word_t	u:6;
	L4_Word_t	t:6;
	L4_Word_t	flags:4;
	L4_Word_t	label:16 __PLUS32;
#endif
    } X;
} L4_MsgTag_t;

#define L4_Niltag		((L4_MsgTag_t) { raw : 0UL })

L4_INLINE L4_Bool_t L4_IsMsgTagEqual (const L4_MsgTag_t l,
				      const L4_MsgTag_t r)
{
    return l.raw == r.raw;
}

L4_INLINE L4_Bool_t L4_IsMsgTagNotEqual (const L4_MsgTag_t l,
					 const L4_MsgTag_t r)
{
    return l.raw != r.raw;
}

#if defined(__cplusplus)
static inline L4_Bool_t operator == (const L4_MsgTag_t & l,
				     const L4_MsgTag_t & r)
{
    return l.raw == r.raw;
}

static inline L4_Bool_t operator != (const L4_MsgTag_t & l,
				     const L4_MsgTag_t & r)
{
    return l.raw != r.raw;
}
#endif /* __cplusplus */

L4_INLINE L4_MsgTag_t L4_MsgTagAddLabel (const L4_MsgTag_t t, int label)
{
    L4_MsgTag_t tag = t;
    tag.X.label = label;
    return tag;
}

L4_INLINE L4_MsgTag_t L4_MsgTagAddLabelTo (L4_MsgTag_t * t, int label)
{
    t->X.label = label;
    return *t;
}

#if defined(__cplusplus)
static inline L4_MsgTag_t operator + (const L4_MsgTag_t & t, int label)
{
    return L4_MsgTagAddLabel (t, label);
}

static inline L4_MsgTag_t operator += (L4_MsgTag_t & t, int label)
{
    return L4_MsgTagAddLabelTo (&t, label);
}
#endif /* __cplusplus */

L4_INLINE L4_Word_t L4_Label (L4_MsgTag_t t)
{
    return t.X.label;
}

L4_INLINE L4_Word_t L4_UntypedWords (L4_MsgTag_t t)
{
    return t.X.u;
}

L4_INLINE L4_Word_t L4_TypedWords (L4_MsgTag_t t)
{
    return t.X.t;
}

L4_INLINE void L4_Set_Label (L4_MsgTag_t * t, L4_Word_t label)
{
    t->X.label = label;
}

L4_INLINE L4_MsgTag_t L4_MsgTag (void)
{
    L4_MsgTag_t msgtag;
    L4_StoreMR (0, &msgtag.raw);
    return msgtag;
}

L4_INLINE void L4_Set_MsgTag (L4_MsgTag_t t)
{
    L4_LoadMR (0, t.raw);
}





/*
 * Map item
 */

typedef union {
    L4_Word_t	raw[2];
    struct {
#if defined(L4_BIG_ENDIAN)
	L4_Word_t	snd_base:22 __PLUS32;
	L4_Word_t	__zeros:6;
	L4_Word_t	__type:3;
	L4_Word_t	C:1;
#else
	L4_Word_t	C:1;
	L4_Word_t	__type:3;
	L4_Word_t	__zeros:6;
	L4_Word_t	snd_base:22 __PLUS32;
#endif
	L4_Fpage_t	snd_fpage;
    } X;
} L4_MapItem_t;	


L4_INLINE L4_MapItem_t L4_MapItem (L4_Fpage_t f, L4_Word_t SndBase)
{
    L4_MapItem_t item;
    item.raw[0] = 0;
    item.X.__type = 0x04;
    item.X.snd_base = SndBase >> 10;
    item.X.snd_fpage.raw = f.raw;
    return item;
}

L4_INLINE L4_Bool_t L4_IsMapItem (L4_MapItem_t m)
{
    return m.X.__type == 0x04;
}

L4_INLINE L4_Fpage_t L4_MapItemSndFpage (L4_MapItem_t m)
{
    return m.X.snd_fpage;
}

L4_INLINE L4_Word_t L4_MapItemSndBase (L4_MapItem_t m)
{
    return m.X.snd_base << 10;
}

#if defined(__cplusplus)
L4_INLINE L4_Bool_t L4_MapItem (L4_MapItem_t m)
{
    return L4_IsMapItem (m);
}

L4_INLINE L4_Fpage_t L4_SndFpage (L4_MapItem_t m)
{
    return L4_MapItemSndFpage (m);
}

L4_INLINE L4_Word_t L4_SndBase (L4_MapItem_t m)
{
    return L4_MapItemSndBase (m);
}
#endif /* __cplusplus */





/*
 * Grant item
 */

typedef union {
    L4_Word_t	raw[2];
    struct {
#if defined(L4_BIG_ENDIAN)
	L4_Word_t	snd_base:22 __PLUS32;
	L4_Word_t	__zeros:6;
	L4_Word_t	__type:3;
	L4_Word_t	C:1;
#else
	L4_Word_t	C:1;
	L4_Word_t	__type:3;
	L4_Word_t	__zeros:6;
	L4_Word_t	snd_base:22 __PLUS32;
#endif
	L4_Fpage_t	snd_fpage;
    } X;
} L4_GrantItem_t;	

L4_INLINE L4_Bool_t L4_IsGrantItem (L4_GrantItem_t g)
{
    return g.X.__type == 0x05;
}

L4_INLINE L4_GrantItem_t L4_GrantItem (L4_Fpage_t f, L4_Word_t SndBase)
{
    L4_GrantItem_t item;
    item.raw[0] = 0;
    item.X.__type = 0x05;
    item.X.snd_base = SndBase >> 10;
    item.X.snd_fpage.raw = f.raw;
    return item;
}

L4_INLINE L4_Fpage_t L4_GrantItemSndFpage (L4_GrantItem_t m)
{
    return m.X.snd_fpage;
}

L4_INLINE L4_Word_t L4_GrantItemSndBase (L4_GrantItem_t m)
{
    return m.X.snd_base << 10;
}

#if defined(__cplusplus)
L4_INLINE L4_Bool_t L4_GrantItem (L4_GrantItem_t g)
{
    return L4_IsGrantItem (g);
}

L4_INLINE L4_Fpage_t L4_SndFpage (L4_GrantItem_t m)
{
    return L4_GrantItemSndFpage (m);
}

L4_INLINE L4_Word_t L4_SndBase (L4_GrantItem_t m)
{
    return L4_GrantItemSndBase (m);
}
#endif /* __cplusplus */





/*
 * String item
 */

typedef union {
    L4_Word_t	raw[2];
    struct {
#if defined(L4_BIG_ENDIAN)
	L4_Word_t	string_length:22 __PLUS32;
	L4_Word_t	c:1;
	L4_Word_t	j:5;
	L4_Word_t	__type:3;
	L4_Word_t	C:1;
#else
	L4_Word_t	C:1;
	L4_Word_t	__type:3;
	L4_Word_t	j:5;
	L4_Word_t	c:1;
	L4_Word_t	string_length:22 __PLUS32;
#endif
	union {
	    void *	string_ptr;
	    void *	substring_ptr[0];
	} str;
    } X;
} L4_StringItem_t;


L4_INLINE L4_StringItem_t L4_StringItem (int size, void * address)
{
    L4_StringItem_t item;
    item.X.C = 0;
    item.X.__type = 0;
    item.X.j = 0;
    item.X.c = 0;
    item.X.string_length = size;
    item.X.str.string_ptr = address;
    return item;
}

L4_INLINE L4_Bool_t L4_IsStringItem (L4_StringItem_t * s)
{
    return (s->X.__type & 0x04) == 0;
}

#if defined(__cplusplus)
L4_INLINE L4_Bool_t L4_StringItem (L4_StringItem_t * s)
{
    return L4_IsStringItem (s);
}
#endif

L4_INLINE L4_Bool_t L4_CompoundString (L4_StringItem_t * s)
{
    return s->X.c != 0;
}

L4_INLINE L4_Word_t L4_Substrings (L4_StringItem_t * s)
{
    return s->X.j + 1;
}

L4_INLINE void * L4_Substring (L4_StringItem_t * s, L4_Word_t n)
{
    return s->X.str.substring_ptr[n - 1];
}

L4_INLINE L4_StringItem_t * __L4_EndOfString (L4_StringItem_t * s,
					      L4_StringItem_t ** p)
{
    L4_StringItem_t *prev;
    do {
	prev = s;
	s = (L4_StringItem_t *) &s->X.str.substring_ptr[s->X.j+1];
    } while (prev->X.c);
    if (p)
	*p = prev;
    return s;
}

L4_INLINE L4_StringItem_t * __L4_EndOfStrings (L4_StringItem_t * s,
					       L4_StringItem_t ** p)
{
    L4_StringItem_t *prev;
    do {
	prev = s;
	s = __L4_EndOfString (s, (L4_StringItem_t **) 0);
    } while (prev->X.C);
    if (p)
	*p = prev;
    return s;
}

L4_INLINE void __L4_Copy_String (L4_StringItem_t * d,
				 L4_StringItem_t * s)
{
    L4_Word_t *dest, *from, *end;
    from = (L4_Word_t *) s;
    dest = (L4_Word_t *) d;
    end = (L4_Word_t *) __L4_EndOfString (s, (L4_StringItem_t **) 0);
    while (from < end)
	*dest++ = *from++;
}

L4_INLINE L4_StringItem_t * L4_AddSubstringTo (L4_StringItem_t * dest,
					       L4_StringItem_t * substr)
{
    L4_StringItem_t *prev;
    dest = __L4_EndOfString (dest, &prev);
    prev->X.c = 1;
    __L4_Copy_String (dest, substr);
    return dest;
}

L4_INLINE L4_StringItem_t * L4_AddSubstringAddressTo (L4_StringItem_t * dest,
						      void * substring_addr)
{
    L4_StringItem_t *last;
    __L4_EndOfString (dest, &last);
    last->X.j++;
    last->X.str.substring_ptr[last->X.j] = substring_addr;
    return dest;
}

#if defined(__cplusplus)
static inline L4_StringItem_t * operator += (L4_StringItem_t & dest,
					     L4_StringItem_t substring)
{
    substring.X.c = 0;
    L4_AddSubstringTo (&dest, &substring);
    return &dest;
}

static inline L4_StringItem_t * operator += (L4_StringItem_t & dest,
					     L4_StringItem_t & substring)
{
    L4_AddSubstringTo (&dest, &substring);
    return &dest;
}

static inline L4_StringItem_t * operator += (L4_StringItem_t & dest,
					     void * substring_addr)
{
    L4_AddSubstringAddressTo (&dest, (L4_StringItem_t *) substring_addr);
    return &dest;
}
#endif /* __cplusplus */





/*
 * Cache allocation hints
 */

typedef struct L4_CacheAllocationHint {
    L4_Word_t	raw;
} L4_CacheAllocationHint_t;

#define L4_UseDefaultCacheAllocation ((L4_CacheAllocationHint_t) { raw: 0 })

L4_INLINE L4_CacheAllocationHint_t L4_CacheAlloctionHint (
    const L4_StringItem_t s)
{
    L4_CacheAllocationHint_t hint;
    hint.raw = s.raw[0] & 0x6;
    return hint;
}

L4_INLINE L4_Bool_t L4_IsCacheAllocationHintEqual (
    const L4_CacheAllocationHint_t l, const L4_CacheAllocationHint_t r)
{
    return (l.raw & 0x6) == (r.raw & 0x6);
}

L4_INLINE L4_Bool_t L4_IsCacheAllocationHintNotEqual (
    const L4_CacheAllocationHint_t l, const L4_CacheAllocationHint_t r)
{
    return (l.raw & 0x6) != (r.raw & 0x6);
}

L4_INLINE L4_StringItem_t L4_AddCacheAllocationHint (
    const L4_StringItem_t dest, const L4_CacheAllocationHint_t h)
{
    L4_StringItem_t item = dest;
    item.raw[0] |= (h.raw & 0x6);
    return item;
}

L4_INLINE L4_StringItem_t L4_AddCacheAllocationHintTo (
    L4_StringItem_t * dest, const L4_CacheAllocationHint_t h)
{
    dest->raw[0] |= (h.raw & 0x6);
    return *dest;
}

#if defined(__cplusplus)
L4_INLINE L4_CacheAllocationHint_t L4_CacheAlloctionHint (
    const L4_StringItem_t & s)
{
    L4_CacheAllocationHint_t hint;
    hint.raw = s.raw[0] & 0x6;
    return hint;
}

static inline L4_Bool_t operator == (const L4_CacheAllocationHint_t & l,
				     const L4_CacheAllocationHint_t & r)
{
    return (l.raw & 0x6) == (r.raw & 0x6);
}

static inline L4_Bool_t operator != (const L4_CacheAllocationHint_t & l,
				     const L4_CacheAllocationHint_t & r)
{
    return (l.raw & 0x6) != (r.raw & 0x6);
}

static inline L4_StringItem_t operator + (const L4_StringItem_t & dest,
					  const L4_CacheAllocationHint_t & h)
{
    return L4_AddCacheAllocationHint (dest, h);
}

static inline L4_StringItem_t operator += (L4_StringItem_t & dest,
					   const L4_CacheAllocationHint_t & h)
{
    return L4_AddCacheAllocationHintTo (&dest, h);
}
#endif /* __cplusplus */





/*
 * Message objects
 */

typedef union {
    L4_Word_t raw[__L4_NUM_MRS];
    L4_Word_t msg[__L4_NUM_MRS];
    L4_MsgTag_t tag;
} L4_Msg_t;

L4_INLINE void L4_MsgPut (L4_Msg_t * msg, L4_Word_t label,
			  int u, L4_Word_t * Untyped,
			  int t, void * Items)
{
    int i;

    for (i = 0; i < u; i++)
	msg->msg[i+1] = Untyped[i];
    for (i = 0; i < t; i++)
	msg->msg[i+u+1] = ((L4_Word_t *) Items)[i];

    msg->tag.X.label = label;
    msg->tag.X.flags = 0;
    msg->tag.X.u = u;
    msg->tag.X.t = t;
}

L4_INLINE void L4_MsgGet (const L4_Msg_t * msg, L4_Word_t * Untyped,
			  void * Items)
{
    int i, u, t;
    u = msg->tag.X.u;
    t = msg->tag.X.t;

    for (i = 0; i < u; i++)
	Untyped[i] = msg->msg[i + 1];
    for (i = 0; i < t; i++)
	((L4_Word_t *) Items)[i] = msg->msg[i + 1 + u];
}

L4_INLINE L4_MsgTag_t L4_MsgMsgTag (const L4_Msg_t * msg)
{
    return msg->tag;
}

L4_INLINE void L4_Set_MsgMsgTag (L4_Msg_t * msg, L4_MsgTag_t t)
{
    msg->tag = t;
}

L4_INLINE L4_Word_t L4_MsgLabel (const L4_Msg_t * msg)
{
    return msg->tag.X.label;
}

L4_INLINE void L4_Set_MsgLabel (L4_Msg_t * msg, L4_Word_t label)
{
    msg->tag.X.label = label;
}

L4_INLINE void L4_MsgLoad (L4_Msg_t * msg)
{
    L4_LoadMRs (0, msg->tag.X.u + msg->tag.X.t + 1, &msg->msg[0]);
}

L4_INLINE void L4_MsgStore (L4_MsgTag_t t, L4_Msg_t * msg)
{
    L4_StoreMRs (1, t.X.u + t.X.t, &msg->msg[1]);
    msg->tag = t;
}

L4_INLINE void L4_MsgClear (L4_Msg_t * msg)
{
    msg->msg[0] = 0;
}

L4_INLINE void L4_MsgAppendWord (L4_Msg_t * msg, L4_Word_t w)
{
    if (msg->tag.X.t)
    {
	L4_Word_t i = 1 + msg->tag.X.u + msg->tag.X.t;
	for (; i > (L4_Word_t)(msg->tag.X.u + 1); i--)
	    msg->msg[i] = msg->msg[i-1];
    }
    msg->msg[++msg->tag.X.u] = w;
}

L4_INLINE void L4_MsgAppendMapItem (L4_Msg_t * msg, L4_MapItem_t m)
{
    msg->msg[msg->tag.X.u + msg->tag.X.t + 1] = m.raw[0];
    msg->msg[msg->tag.X.u + msg->tag.X.t + 2] = m.raw[1];
    msg->tag.X.t += 2;
}

L4_INLINE void L4_MsgAppendGrantItem (L4_Msg_t * msg, L4_GrantItem_t g)
{
    msg->msg[msg->tag.X.u + msg->tag.X.t + 1] = g.raw[0];
    msg->msg[msg->tag.X.u + msg->tag.X.t + 2] = g.raw[1];
    msg->tag.X.t += 2;
}

L4_INLINE void L4_MsgAppendSimpleStringItem (L4_Msg_t * msg, L4_StringItem_t s)
{
    s.X.c = 0;
    s.X.j = 0;
    msg->msg[msg->tag.X.u + msg->tag.X.t + 1] = s.raw[0];
    msg->msg[msg->tag.X.u + msg->tag.X.t + 2] = s.raw[1];
    msg->tag.X.t += 2;
}

L4_INLINE void L4_MsgAppendStringItem (L4_Msg_t * msg,
				       L4_StringItem_t * s)
{
    L4_StringItem_t *d = (L4_StringItem_t *)
	&msg->msg[msg->tag.X.u + msg->tag.X.t + 1];
    L4_StringItem_t *e = __L4_EndOfString (s, (L4_StringItem_t **) 0);
    int size = ((L4_Word_t) e - (L4_Word_t) s) / sizeof (L4_Word_t);
    __L4_Copy_String (d, s);
    msg->tag.X.t += size;
}

L4_INLINE void L4_MsgPutWord (L4_Msg_t * msg, L4_Word_t u, L4_Word_t w)
{
    msg->msg[u+1] = w;
}

L4_INLINE void L4_MsgPutMapItem (L4_Msg_t * msg, L4_Word_t t, L4_MapItem_t m)
{
    msg->msg[msg->tag.X.u + t + 1] = m.raw[0];
    msg->msg[msg->tag.X.u + t + 2] = m.raw[1];
}

L4_INLINE void L4_MsgPutGrantItem (L4_Msg_t * msg, L4_Word_t t,
				   L4_GrantItem_t g)
{
    msg->msg[msg->tag.X.u + t + 1] = g.raw[0];
    msg->msg[msg->tag.X.u + t + 2] = g.raw[1];
}

L4_INLINE void L4_MsgPutSimpleStringItem (L4_Msg_t * msg, L4_Word_t t,
					  L4_StringItem_t s)
{
    s.X.c = 0;
    s.X.j = 0;
    msg->msg[msg->tag.X.u + t + 1] = s.raw[0];
    msg->msg[msg->tag.X.u + t + 2] = s.raw[1];
}

L4_INLINE void L4_MsgPutStringItem (L4_Msg_t * msg, L4_Word_t t,
				    L4_StringItem_t * s)
{
    L4_StringItem_t *d = (L4_StringItem_t *) &msg->msg[msg->tag.X.u + t + 1];
    __L4_Copy_String (d, s);
}

L4_INLINE L4_Word_t L4_MsgWord (L4_Msg_t * msg, L4_Word_t u)
{
    return msg->msg[u + 1];
}

L4_INLINE void L4_MsgGetWord (L4_Msg_t * msg, L4_Word_t u, L4_Word_t * w)
{
    *w = msg->msg[u + 1];
}

L4_INLINE L4_Word_t L4_MsgGetMapItem (L4_Msg_t * msg, L4_Word_t t,
				      L4_MapItem_t * m)
{
    m->raw[0] = msg->msg[msg->tag.X.u + t + 1];
    m->raw[1] = msg->msg[msg->tag.X.u + t + 2];
    return 2;
}

L4_INLINE L4_Word_t L4_MsgGetGrantItem (L4_Msg_t * msg, L4_Word_t t,
					L4_GrantItem_t * g)
{
    g->raw[0] = msg->msg[msg->tag.X.u + t + 1];
    g->raw[1] = msg->msg[msg->tag.X.u + t + 2];
    return 2;
}

L4_INLINE L4_Word_t L4_MsgGetStringItem (L4_Msg_t * msg, L4_Word_t t,
					 L4_StringItem_t * s)
{
    L4_StringItem_t *b = (L4_StringItem_t *) &msg->msg[msg->tag.X.u + t + 1];
    L4_StringItem_t *e = __L4_EndOfString (b, &s);
    __L4_Copy_String (s, b);
    return ((L4_Word_t) e - (L4_Word_t) b) / sizeof (L4_Word_t);
}

#if defined(__cplusplus)
L4_INLINE void L4_Put (L4_Msg_t * msg, L4_Word_t label,
		       int u, L4_Word_t * Untyped,
		       int t, void * Items)
{
    L4_MsgPut (msg, label, u, Untyped, t, Items);
}

L4_INLINE void L4_Get (const L4_Msg_t * msg, L4_Word_t * Untyped, void * Items)
{
    L4_MsgGet (msg, Untyped, Items);
}

L4_INLINE L4_MsgTag_t L4_MsgTag (const L4_Msg_t * msg)
{
    return L4_MsgMsgTag (msg);
}

L4_INLINE void L4_Set_MsgTag (L4_Msg_t * msg, L4_MsgTag_t t)
{
    L4_Set_MsgMsgTag (msg, t);
}

L4_INLINE L4_Word_t L4_Label (const L4_Msg_t * msg)
{
    return L4_MsgLabel (msg);
}

L4_INLINE void L4_Set_Label (L4_Msg_t * msg, L4_Word_t label)
{
    L4_Set_MsgLabel (msg, label);
}

L4_INLINE void L4_Load (L4_Msg_t * msg)
{
    L4_MsgLoad (msg);
}

L4_INLINE void L4_Store (L4_MsgTag_t t, L4_Msg_t * msg)
{
    L4_MsgStore (t, msg);
}

L4_INLINE void L4_Clear (L4_Msg_t * msg)
{
    L4_MsgClear (msg);
}

L4_INLINE void L4_Append (L4_Msg_t * msg, L4_Word_t w)
{
    L4_MsgAppendWord (msg, w);
}

L4_INLINE void L4_Append (L4_Msg_t * msg, int w)
{
    L4_MsgAppendWord (msg, (L4_Word_t) w);
}

L4_INLINE void L4_Append (L4_Msg_t * msg, L4_MapItem_t m)
{
    L4_MsgAppendMapItem (msg, m);
}

L4_INLINE void L4_Append (L4_Msg_t * msg, L4_GrantItem_t g)
{
    L4_MsgAppendGrantItem (msg, g);
}

L4_INLINE void L4_Append (L4_Msg_t * msg, L4_StringItem_t s)
{
    L4_MsgAppendSimpleStringItem (msg, s);
}

L4_INLINE void L4_Append (L4_Msg_t * msg, L4_StringItem_t * s)
{
    L4_MsgAppendStringItem (msg, s);
}

L4_INLINE void L4_Put (L4_Msg_t * msg, L4_Word_t u, L4_Word_t w)
{
    L4_MsgPutWord (msg, u, w);
}

L4_INLINE void L4_Put (L4_Msg_t * msg, L4_Word_t t, L4_MapItem_t m)
{
    L4_MsgPutMapItem (msg, t, m);
}

L4_INLINE void L4_Put (L4_Msg_t * msg, L4_Word_t t, L4_GrantItem_t g)
{
    L4_MsgPutGrantItem (msg, t, g);
}

L4_INLINE void L4_Put (L4_Msg_t * msg, L4_Word_t t, L4_StringItem_t s)
{
    L4_MsgPutSimpleStringItem (msg, t, s);
}

L4_INLINE void L4_Put (L4_Msg_t * msg, L4_Word_t t, L4_StringItem_t * s)
{
    L4_MsgPutStringItem (msg, t, s);
}

L4_INLINE L4_Word_t L4_Get (L4_Msg_t * msg, L4_Word_t u)
{
    return L4_MsgWord (msg, u);
}

L4_INLINE void L4_Get (L4_Msg_t * msg, L4_Word_t u, L4_Word_t * w)
{
    L4_MsgGetWord (msg, u, w);
}

L4_INLINE L4_Word_t L4_Get (L4_Msg_t * msg, L4_Word_t t, L4_MapItem_t * m)
{
    return L4_MsgGetMapItem (msg, t, m);
}

L4_INLINE L4_Word_t L4_Get (L4_Msg_t * msg, L4_Word_t t, L4_GrantItem_t * g)
{
    return L4_MsgGetGrantItem (msg, t, g);
}

L4_INLINE L4_Word_t L4_Get (L4_Msg_t * msg, L4_Word_t t, L4_StringItem_t * s)
{
    return L4_MsgGetStringItem (msg, t, s);
}
#endif /* __cplusplus */




/*
 * Acceptors and mesage buffers.
 */

typedef union {
    L4_Word_t	raw;
    struct {
#if defined(L4_BIG_ENDIAN)
	L4_Word_t	RcvWindow:28 __PLUS32;
	L4_Word_t	__zeros:3;
	L4_Word_t	s:1;
#else
	L4_Word_t	s:1;
	L4_Word_t	__zeros:3;
	L4_Word_t	RcvWindow:28 __PLUS32;
#endif
    } X;
} L4_Acceptor_t;

typedef union {
    L4_Word_t 		raw[__L4_NUM_BRS-1];
    L4_StringItem_t	string[0];
} L4_MsgBuffer_t;

//#define L4_UntypedWordsAcceptor		((L4_Acceptor_t) { 0 })
//#define L4_StringItemsAcceptor		((L4_Acceptor_t) { 1 })
static const L4_Acceptor_t L4_UntypedWordsAcceptor = { 0 };
static const L4_Acceptor_t L4_StringItemsAcceptor = { 1 };

L4_INLINE L4_Acceptor_t L4_MapGrantItems (L4_Fpage_t RcvWindow)
{
    L4_Acceptor_t a;
    a.raw = RcvWindow.raw;
    a.X.s = 1;
    a.X.__zeros = 0;
    return a;
}

L4_INLINE L4_Acceptor_t L4_AddAcceptor (const L4_Acceptor_t l,
					const L4_Acceptor_t r)
{
    L4_Acceptor_t a;
    a.raw = 0;
    a.X.s = (l.X.s | r.X.s);
    a.X.RcvWindow = (r.X.RcvWindow != 0) ? r.X.RcvWindow : l.X.RcvWindow;
    return a;
}

L4_INLINE L4_Acceptor_t L4_AddAcceptorTo (L4_Acceptor_t l,
					  const L4_Acceptor_t r)
{
    l.X.s = (l.X.s | r.X.s);
    if (r.X.RcvWindow != 0)
	l.X.RcvWindow = r.X.RcvWindow;
    return l;
}

L4_INLINE L4_Acceptor_t L4_RemoveAcceptor (const L4_Acceptor_t l,
					   const L4_Acceptor_t r)
{
    L4_Acceptor_t a = l;
    if (r.X.s)
	a.X.s = 0;
    if (r.X.RcvWindow != 0)
	a.X.RcvWindow = 0;
    return a;
}

L4_INLINE L4_Acceptor_t L4_RemoveAcceptorFrom (L4_Acceptor_t l,
					       const L4_Acceptor_t r)
{
    if (r.X.s)
	l.X.s = 0;
    if (r.X.RcvWindow != 0)
	l.X.RcvWindow = 0;
    return l;
}

#if defined(__cplusplus)
static inline L4_Acceptor_t operator + (const L4_Acceptor_t & l,
					const L4_Acceptor_t & r)
{
    return L4_AddAcceptor (l, r);
}

static inline L4_Acceptor_t operator += (L4_Acceptor_t & l,
					 const L4_Acceptor_t & r)
{
    return L4_AddAcceptorTo (l, r);
}

static inline L4_Acceptor_t operator - (const L4_Acceptor_t & l,
					const L4_Acceptor_t & r)
{
    return L4_RemoveAcceptor (l, r);
}

static inline L4_Acceptor_t operator -= (L4_Acceptor_t & l,
					 const L4_Acceptor_t & r)
{
    return L4_RemoveAcceptorFrom (l, r);
}
#endif /* __cplusplus */

L4_INLINE L4_Bool_t L4_HasStringItems (const L4_Acceptor_t a)
{
    return (a.raw & 0x01UL) == 1;
}

L4_INLINE L4_Bool_t L4_HasMapGrantItems (const L4_Acceptor_t a)
{
    return (a.raw & ~0x0fUL) != 0;
}

#if defined(__cplusplus)
L4_INLINE L4_Bool_t L4_StringItems (const L4_Acceptor_t a)
{
    return L4_HasStringItems (a);
}

L4_INLINE L4_Bool_t L4_MapGrantItems (const L4_Acceptor_t a)
{
    return L4_HasMapGrantItems (a);
}
#endif /* __cplusplus */

L4_INLINE L4_Fpage_t L4_RcvWindow (const L4_Acceptor_t a)
{
    L4_Fpage_t fp;
    fp.raw = a.raw;
    fp.X.rwx = 0;
    return fp;
}

L4_INLINE void L4_Accept (const L4_Acceptor_t a)
{
    L4_LoadBR (0, a.raw);
}
L4_INLINE void L4_AcceptStrings (const L4_Acceptor_t a,
				 const L4_MsgBuffer_t * b)
{
    L4_StringItem_t *prev, *t, *s = (L4_StringItem_t *) &b->string[0];
    int n, i = 1;

    L4_LoadBR (0, a.raw);
    do {
	prev = s;
	do {
	    t = s;
	    n = s->X.j + 2;
	    s = (L4_StringItem_t *) &s->X.str.substring_ptr[n-1];
	    L4_LoadBRs (i, n, (L4_Word_t *) t);
	    i += n;
	} while (t->X.c);
    } while (prev->X.C);
}
#if defined(__cplusplus)
L4_INLINE void L4_Accept (const L4_Acceptor_t a, const L4_MsgBuffer_t * b)
{
    L4_AcceptStrings (a, b);
}
#endif

L4_INLINE L4_Acceptor_t L4_Accepted (void)
{
    L4_Acceptor_t a;
    L4_StoreBR (0, &a.raw);
    return a;
}

L4_INLINE void L4_MsgBufferClear (L4_MsgBuffer_t * b)
{
    b->raw[0] = b->raw[2] = 0;
}

#if defined(__cplusplus)
L4_INLINE void L4_Clear (L4_MsgBuffer_t * b)
{
    L4_MsgBufferClear (b);
}
#endif /* __cplusplus */

L4_INLINE void L4_MsgBufferAppendSimpleRcvString (L4_MsgBuffer_t * b,
						  L4_StringItem_t s)
{
    L4_StringItem_t *prev, *tmp;

    s.X.j = 0;
    s.X.c = 0;

    if (b->raw[0] || b->raw[2]) {
	tmp = __L4_EndOfStrings ((L4_StringItem_t*)&b[0], &prev);
	prev->X.C = 1;
	*tmp = s;
    } else {
	b->raw[2] = ~0UL;
	((L4_StringItem_t*)b)[0] = s;
	b->string[0].X.C = 0;
    }
}

L4_INLINE void L4_MsgBufferAppendRcvString (L4_MsgBuffer_t * b,
					    L4_StringItem_t * s)
{
    L4_StringItem_t *prev, *tmp;

    if (b->raw[0] || b->raw[2]) {
	tmp = __L4_EndOfStrings ((L4_StringItem_t *) &b->raw[0], &prev);
	prev->X.C = 1;
    } else
	tmp = (L4_StringItem_t *) &b->raw[0];

    __L4_Copy_String (tmp, s);
    tmp->X.C = 0;
}

#if defined(__cplusplus)
L4_INLINE void L4_Append (L4_MsgBuffer_t * b, L4_StringItem_t s)
{
    L4_MsgBufferAppendSimpleRcvString (b, s);
}

L4_INLINE void L4_Append (L4_MsgBuffer_t * b, L4_StringItem_t * s)
{
    L4_MsgBufferAppendRcvString (b, s);
}
#endif /* __cplusplus */

#undef __PLUS32

#endif /* !__L4__MESSAGE_H__ */