Index: Makefile
===================================================================
--- Makefile	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ Makefile	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -30,5 +30,8 @@
 #
 
-.PHONY: all config config_default distclean clean cscope
+CSCOPE = cscope
+STANSE = stanse
+
+.PHONY: all config config_default distclean clean cscope stanse
 
 all: Makefile.config config.h config.defs
@@ -36,4 +39,12 @@
 	$(MAKE) -C uspace
 	$(MAKE) -C boot
+
+stanse: Makefile.config config.h config.defs
+	$(MAKE) -C kernel clean
+	$(MAKE) -C kernel EXTRA_TOOL=stanse
+	$(STANSE) --checker ReachabilityChecker --checker ThreadChecker:contrib/$(STANSE)/ThreadChecker.xml --jobfile kernel/kernel.job
+
+cscope:
+	find kernel boot uspace -regex '^.*\.[chsS]$$' | xargs $(CSCOPE) -b -k -u -f$(CSCOPE).out
 
 Makefile.config: config_default
@@ -50,13 +61,8 @@
 
 distclean: clean
-	rm -f Makefile.config config.h config.defs tools/*.pyc
+	rm -f $(CSCOPE).out Makefile.config config.h config.defs tools/*.pyc
 
 clean:
-	-$(MAKE) -C kernel clean
-	-$(MAKE) -C uspace clean
-	-$(MAKE) -C boot clean
-
-cscope:
-	find kernel boot uspace -regex '^.*\.[chsS]$$' -print > srclist
-	rm -f cscope.out
-	cscope -bi srclist
+	$(MAKE) -C kernel clean
+	$(MAKE) -C uspace clean
+	$(MAKE) -C boot clean
Index: contrib/bazaar/mbprotect/__init__.py
===================================================================
--- contrib/bazaar/mbprotect/__init__.py	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ contrib/bazaar/mbprotect/__init__.py	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -52,10 +52,17 @@
 	return
 
-    # Look for old tip in new main branch.
+    # First permitted case is appending changesets to main branch.Look for
+    # old tip in new main branch.
     for revision_id in repo.iter_reverse_revision_history(params.new_revid):
 	if revision_id == params.old_revid:
 	    return	# Found old tip
 
-    # Old tip was not found. Reject the change.
+    # Another permitted case is backing out changesets. Look for new tip
+    # in old branch.
+    for revision_id in repo.iter_reverse_revision_history(params.old_revid):
+	if revision_id == params.new_revid:
+	    return	# Found new tip
+
+    # Trying to do something else. Reject the change.
     raise TipChangeRejected('Bad tip. Read http://trac.helenos.org/trac.fcgi/' +
 	'wiki/BazaarWorkflow')
Index: contrib/stanse/ThreadChecker.xml
===================================================================
--- contrib/stanse/ThreadChecker.xml	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
+++ contrib/stanse/ThreadChecker.xml	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+
+ Copyright (c) 2009 Martin Decky
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+ - 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.
+ - The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-->
+
+<threadChecker>
+	<analyseType type="local" />
+	<patterns>
+		<pattern name="lockFunction">
+			<nested>
+				<functionCall>
+					<id>_mutex_lock_timeout</id>
+					<var name="mtx" />
+				</functionCall>
+			</nested>
+		</pattern>
+		<pattern name="unlockFunction">
+			<nested>
+				<functionCall>
+					<id>mutex_unlock</id>
+					<var name="mtx" />
+				</functionCall>
+			</nested>
+		</pattern>
+	</patterns>
+</threadChecker>
Index: kernel/Makefile
===================================================================
--- kernel/Makefile	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/Makefile	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -33,7 +33,8 @@
 all: ../version ../Makefile.config ../config.h ../config.defs
 	-[ -f $(DEPEND) ] && mv -f $(DEPEND) $(DEPEND_PREV)
-	$(MAKE) -f Makefile.build
+	$(MAKE) -f Makefile.build EXTRA_TOOL=$(EXTRA_TOOL)
 
 clean:
-	rm -f $(DEPEND) $(DEPEND_PREV) $(RAW) $(BIN) $(MAP) $(MAP_PREV) $(DISASM) $(DUMP) $(REAL_MAP).* $(ARCH_INCLUDE) $(GENARCH_INCLUDE) arch/*/_link.ld
+	rm -f $(DEPEND) $(DEPEND_PREV) $(RAW) $(BIN) $(MAP) $(JOB) $(MAP_PREV) $(DISASM) $(DUMP) $(REAL_MAP).* $(ARCH_INCLUDE) $(GENARCH_INCLUDE) arch/*/_link.ld
 	find generic/src/ arch/*/src/ genarch/src/ test/ -name '*.o' -follow -exec rm \{\} \;
+	find generic/src/ arch/*/src/ genarch/src/ test/ -name '*.o.preproc' -follow -exec rm \{\} \;
Index: kernel/Makefile.build
===================================================================
--- kernel/Makefile.build	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/Makefile.build	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -91,5 +91,5 @@
 ## Cross-platform assembly to start a symtab.data section
 #
-SYMTAB_SECTION=".section symtab.data, \"a\", $(ATSIGN)progbits;"
+SYMTAB_SECTION = ".section symtab.data, \"a\", $(ATSIGN)progbits;"
 
 ## Simple detection for the type of the host system
@@ -110,5 +110,5 @@
 ifeq ($(COMPILER),gcc_native)
 	CC = gcc
-	GCC = $(CC)
+	GCC = gcc
 	AS = $(BINUTILS_PREFIX)as
 	LD = $(BINUTILS_PREFIX)ld
@@ -168,4 +168,5 @@
 	DEPEND_DEFS = $(DEFS) $(CONFIG_DEFS)
 endif
+
 
 ## Generic kernel sources
@@ -384,4 +385,7 @@
 test/fpu/%.o: test/fpu/%.c $(DEPEND)
 	$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) -c $< -o $@
+ifeq ($(EXTRA_TOOL),stanse)
+	../tools/jobfile.py $(JOB) $< $@ $(DEFS) $(CFLAGS) $(EXTRA_FLAGS)
+endif
 
 #
@@ -390,4 +394,7 @@
 %.o: %.c $(DEPEND)
 	$(CC) $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) $(FPU_NO_CFLAGS) -c $< -o $@
+ifeq ($(EXTRA_TOOL),stanse)
+	../tools/jobfile.py $(JOB) $< $@ $(DEFS) $(CFLAGS) $(EXTRA_FLAGS) $(FPU_NO_CFLAGS)
+endif
 
 $(REAL_MAP).o: $(REAL_MAP).bin
Index: kernel/Makefile.common
===================================================================
--- kernel/Makefile.common	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/Makefile.common	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -36,4 +36,5 @@
 BIN = kernel.bin
 MAP = kernel.map
+JOB = kernel.job
 MAP_PREV = $(MAP).prev
 DISASM = kernel.disasm
Index: kernel/arch/amd64/include/mm/page.h
===================================================================
--- kernel/arch/amd64/include/mm/page.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/arch/amd64/include/mm/page.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -177,4 +177,22 @@
 #define PFERR_CODE_ID		(1 << 4)
 
+/** Page Table Entry. */
+typedef struct {
+	unsigned present : 1;
+	unsigned writeable : 1;
+	unsigned uaccessible : 1;
+	unsigned page_write_through : 1;
+	unsigned page_cache_disable : 1;
+	unsigned accessed : 1;
+	unsigned dirty : 1;
+	unsigned unused: 1;
+	unsigned global : 1;
+	unsigned soft_valid : 1;		/**< Valid content even if present bit is cleared. */
+	unsigned avl : 2;
+	unsigned addr_12_31 : 30;
+	unsigned addr_32_51 : 21;
+	unsigned no_execute : 1;
+} __attribute__ ((packed)) pte_t;
+
 static inline unsigned int get_pt_flags(pte_t *pt, size_t i)
 {
Index: kernel/arch/amd64/include/types.h
===================================================================
--- kernel/arch/amd64/include/types.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/arch/amd64/include/types.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -82,22 +82,4 @@
 #define PRIxn "llx"
 
-/** Page Table Entry. */
-typedef struct {
-	unsigned present : 1;
-	unsigned writeable : 1;
-	unsigned uaccessible : 1;
-	unsigned page_write_through : 1;
-	unsigned page_cache_disable : 1;
-	unsigned accessed : 1;
-	unsigned dirty : 1;
-	unsigned unused: 1;
-	unsigned global : 1;
-	unsigned soft_valid : 1;		/**< Valid content even if present bit is cleared. */
-	unsigned avl : 2;
-	unsigned addr_12_31 : 30;
-	unsigned addr_32_51 : 21;
-	unsigned no_execute : 1;
-} __attribute__ ((packed)) pte_t;
-
 #endif
 
Index: kernel/arch/arm32/include/mm/page.h
===================================================================
--- kernel/arch/arm32/include/mm/page.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/arch/arm32/include/mm/page.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -75,5 +75,5 @@
 /* Get PTE address accessors for each level. */
 #define GET_PTL1_ADDRESS_ARCH(ptl0, i) \
-	((pte_t *) ((((pte_level0_t *)(ptl0))[(i)]).coarse_table_addr << 10))
+	((pte_t *) ((((pte_t *)(ptl0))[(i)].l0).coarse_table_addr << 10))
 #define GET_PTL2_ADDRESS_ARCH(ptl1, i) \
 	(ptl1)
@@ -81,19 +81,19 @@
 	(ptl2)
 #define GET_FRAME_ADDRESS_ARCH(ptl3, i) \
-	((uintptr_t) ((((pte_level1_t *)(ptl3))[(i)]).frame_base_addr << 12))
+	((uintptr_t) ((((pte_t *)(ptl3))[(i)].l1).frame_base_addr << 12))
 
 /* Set PTE address accessors for each level. */
 #define SET_PTL0_ADDRESS_ARCH(ptl0) \
-	(set_ptl0_addr((pte_level0_t *) (ptl0)))
+	(set_ptl0_addr((pte_t *) (ptl0)))
 #define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \
-	(((pte_level0_t *) (ptl0))[(i)].coarse_table_addr = (a) >> 10)
+	(((pte_t *) (ptl0))[(i)].l0.coarse_table_addr = (a) >> 10)
 #define SET_PTL2_ADDRESS_ARCH(ptl1, i, a)
 #define SET_PTL3_ADDRESS_ARCH(ptl2, i, a)
 #define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \
-	(((pte_level1_t *) (ptl3))[(i)].frame_base_addr = (a) >> 12)
+	(((pte_t *) (ptl3))[(i)].l1.frame_base_addr = (a) >> 12)
 
 /* Get PTE flags accessors for each level. */
 #define GET_PTL1_FLAGS_ARCH(ptl0, i) \
-	get_pt_level0_flags((pte_level0_t *) (ptl0), (size_t) (i))
+	get_pt_level0_flags((pte_t *) (ptl0), (size_t) (i))
 #define GET_PTL2_FLAGS_ARCH(ptl1, i) \
 	PAGE_PRESENT
@@ -101,13 +101,13 @@
 	PAGE_PRESENT
 #define GET_FRAME_FLAGS_ARCH(ptl3, i) \
-	get_pt_level1_flags((pte_level1_t *) (ptl3), (size_t) (i))
+	get_pt_level1_flags((pte_t *) (ptl3), (size_t) (i))
 
 /* Set PTE flags accessors for each level. */
 #define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
-	set_pt_level0_flags((pte_level0_t *) (ptl0), (size_t) (i), (x))
+	set_pt_level0_flags((pte_t *) (ptl0), (size_t) (i), (x))
 #define SET_PTL2_FLAGS_ARCH(ptl1, i, x)
 #define SET_PTL3_FLAGS_ARCH(ptl2, i, x)
 #define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
-	set_pt_level1_flags((pte_level1_t *) (ptl3), (size_t) (i), (x))
+	set_pt_level1_flags((pte_t *) (ptl3), (size_t) (i), (x))
 
 /* Macros for querying the last-level PTE entries. */
@@ -115,10 +115,9 @@
 	(*((uint32_t *) (pte)) != 0)
 #define PTE_PRESENT_ARCH(pte) \
-	(((pte_level0_t *) (pte))->descriptor_type != 0)
+	(((pte_t *) (pte))->l0.descriptor_type != 0)
 #define PTE_GET_FRAME_ARCH(pte) \
-	(((pte_level1_t *) (pte))->frame_base_addr << FRAME_WIDTH)
+	(((pte_t *) (pte))->l1.frame_base_addr << FRAME_WIDTH)
 #define PTE_WRITABLE_ARCH(pte) \
-	(((pte_level1_t *) (pte))->access_permission_0 == \
-	    PTE_AP_USER_RW_KERNEL_RW)
+	(((pte_t *) (pte))->l1.access_permission_0 == PTE_AP_USER_RW_KERNEL_RW)
 #define PTE_EXECUTABLE_ARCH(pte) \
 	1
@@ -159,4 +158,8 @@
 } ATTRIBUTE_PACKED pte_level1_t;
 
+typedef union {
+	pte_level0_t l0;
+	pte_level1_t l1;
+} pte_t;
 
 /* Level 1 page tables access permissions */
@@ -191,5 +194,5 @@
  * @param pt    Pointer to the page table to set.
  */   
-static inline void set_ptl0_addr(pte_level0_t *pt)
+static inline void set_ptl0_addr(pte_t *pt)
 {
 	asm volatile (
@@ -205,7 +208,7 @@
  *  @param i      Index of the entry to return.
  */
-static inline int get_pt_level0_flags(pte_level0_t *pt, size_t i)
-{
-	pte_level0_t *p = &pt[i];
+static inline int get_pt_level0_flags(pte_t *pt, size_t i)
+{
+	pte_level0_t *p = &pt[i].l0;
 	int np = (p->descriptor_type == PTE_DESCRIPTOR_NOT_PRESENT);
 
@@ -220,7 +223,7 @@
  *  @param i      Index of the entry to return.
  */
-static inline int get_pt_level1_flags(pte_level1_t *pt, size_t i)
-{
-	pte_level1_t *p = &pt[i];
+static inline int get_pt_level1_flags(pte_t *pt, size_t i)
+{
+	pte_level1_t *p = &pt[i].l1;
 
 	int dt = p->descriptor_type;
@@ -245,7 +248,7 @@
  *  @param flags  new flags
  */
-static inline void set_pt_level0_flags(pte_level0_t *pt, size_t i, int flags)
-{
-	pte_level0_t *p = &pt[i];
+static inline void set_pt_level0_flags(pte_t *pt, size_t i, int flags)
+{
+	pte_level0_t *p = &pt[i].l0;
 
 	if (flags & PAGE_NOT_PRESENT) {
@@ -273,7 +276,7 @@
  *  @param flags  New flags.
  */  
-static inline void set_pt_level1_flags(pte_level1_t *pt, size_t i, int flags)
-{
-	pte_level1_t *p = &pt[i];
+static inline void set_pt_level1_flags(pte_t *pt, size_t i, int flags)
+{
+	pte_level1_t *p = &pt[i].l1;
 	
 	if (flags & PAGE_NOT_PRESENT) {
Index: kernel/arch/arm32/include/types.h
===================================================================
--- kernel/arch/arm32/include/types.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/arch/arm32/include/types.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -87,13 +87,4 @@
 #define PRIxn "x"	/**< Format for hexadecimal (u)native_t. */
 
-/** Page table entry.
- *
- *  We have different structs for level 0 and level 1 page table entries.
- *  See page.h for definition of pte_level*_t.
- */
-typedef struct {
-	unsigned dummy : 32;
-} pte_t;
-
 #endif
 
Index: kernel/arch/ia32/include/mm/page.h
===================================================================
--- kernel/arch/ia32/include/mm/page.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/arch/ia32/include/mm/page.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -146,4 +146,20 @@
 #define PFERR_CODE_RSVD		(1 << 3)	
 
+/** Page Table Entry. */
+typedef struct {
+	unsigned present : 1;
+	unsigned writeable : 1;
+	unsigned uaccessible : 1;
+	unsigned page_write_through : 1;
+	unsigned page_cache_disable : 1;
+	unsigned accessed : 1;
+	unsigned dirty : 1;
+	unsigned pat : 1;
+	unsigned global : 1;
+	unsigned soft_valid : 1;	/**< Valid content even if the present bit is not set. */
+	unsigned avl : 2;
+	unsigned frame_address : 20;
+} __attribute__ ((packed)) pte_t;
+
 static inline unsigned int get_pt_flags(pte_t *pt, size_t i)
 {
Index: kernel/arch/ia32/include/types.h
===================================================================
--- kernel/arch/ia32/include/types.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/arch/ia32/include/types.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -80,20 +80,4 @@
 #define PRIxn "x"	/**< Format for hexadecimal (u)native_t. */
 
-/** Page Table Entry. */
-typedef struct {
-	unsigned present : 1;
-	unsigned writeable : 1;
-	unsigned uaccessible : 1;
-	unsigned page_write_through : 1;
-	unsigned page_cache_disable : 1;
-	unsigned accessed : 1;
-	unsigned dirty : 1;
-	unsigned pat : 1;
-	unsigned global : 1;
-	unsigned soft_valid : 1;	/**< Valid content even if the present bit is not set. */
-	unsigned avl : 2;
-	unsigned frame_address : 20;
-} __attribute__ ((packed)) pte_t;
-
 #endif
 
Index: kernel/arch/mips32/include/mm/page.h
===================================================================
--- kernel/arch/mips32/include/mm/page.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/arch/mips32/include/mm/page.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -141,4 +141,18 @@
 #include <arch/exception.h>
 
+/** Page Table Entry. */
+typedef struct {
+	unsigned g : 1;			/**< Global bit. */
+	unsigned p : 1;			/**< Present bit. */
+	unsigned d : 1;			/**< Dirty bit. */
+	unsigned cacheable : 1;		/**< Cacheable bit. */
+	unsigned : 1;			/**< Unused. */
+	unsigned soft_valid : 1;	/**< Valid content even if not present. */
+	unsigned pfn : 24;		/**< Physical frame number. */
+	unsigned w : 1;			/**< Page writable bit. */
+	unsigned a : 1;			/**< Accessed bit. */
+} pte_t;
+
+
 static inline unsigned int get_pt_flags(pte_t *pt, size_t i)
 {
Index: kernel/arch/mips32/include/types.h
===================================================================
--- kernel/arch/mips32/include/types.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/arch/mips32/include/types.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -80,17 +80,4 @@
 #define PRIxn "x"	/**< Format for hexadecimal (u)native_t. */
 
-/** Page Table Entry. */
-typedef struct {
-	unsigned g : 1;			/**< Global bit. */
-	unsigned p : 1;			/**< Present bit. */
-	unsigned d : 1;			/**< Dirty bit. */
-	unsigned cacheable : 1;		/**< Cacheable bit. */
-	unsigned : 1;			/**< Unused. */
-	unsigned soft_valid : 1;	/**< Valid content even if not present. */
-	unsigned pfn : 24;		/**< Physical frame number. */
-	unsigned w : 1;			/**< Page writable bit. */
-	unsigned a : 1;			/**< Accessed bit. */
-} pte_t;
-
 #endif
 
Index: kernel/arch/ppc32/include/mm/page.h
===================================================================
--- kernel/arch/ppc32/include/mm/page.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/arch/ppc32/include/mm/page.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -131,4 +131,15 @@
 #include <arch/interrupt.h>
 
+/** Page Table Entry. */
+typedef struct {
+	unsigned present : 1;             /**< Present bit. */
+	unsigned page_write_through : 1;  /**< Write thought caching. */
+	unsigned page_cache_disable : 1;  /**< No caching. */
+	unsigned accessed : 1;            /**< Accessed bit. */
+	unsigned global : 1;              /**< Global bit. */
+	unsigned valid : 1;               /**< Valid content even if not present. */
+	unsigned pfn : 20;                /**< Physical frame number. */
+} pte_t;
+
 static inline unsigned int get_pt_flags(pte_t *pt, size_t i)
 {
Index: kernel/arch/ppc32/include/types.h
===================================================================
--- kernel/arch/ppc32/include/types.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/arch/ppc32/include/types.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -82,15 +82,4 @@
 #define PRIxn "x"
 
-/** Page Table Entry. */
-typedef struct {
-	unsigned present : 1;             /**< Present bit. */
-	unsigned page_write_through : 1;  /**< Write thought caching. */
-	unsigned page_cache_disable : 1;  /**< No caching. */
-	unsigned accessed : 1;            /**< Accessed bit. */
-	unsigned global : 1;              /**< Global bit. */
-	unsigned valid : 1;               /**< Valid content even if not present. */
-	unsigned pfn : 20;                /**< Physical frame number. */
-} pte_t;
-
 #endif
 
Index: kernel/genarch/include/mm/as_pt.h
===================================================================
--- kernel/genarch/include/mm/as_pt.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/genarch/include/mm/as_pt.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -36,6 +36,5 @@
 #define KERN_AS_PT_H_
 
-#include <mm/mm.h>
-#include <arch/types.h>
+#include <arch/mm/page.h>
 
 #define AS_PAGE_TABLE
Index: kernel/genarch/include/mm/page_pt.h
===================================================================
--- kernel/genarch/include/mm/page_pt.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/genarch/include/mm/page_pt.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -44,7 +44,8 @@
 #define KERN_PAGE_PT_H_
 
-#include <arch/types.h>
 #include <mm/as.h>
 #include <mm/page.h>
+#include <arch/mm/page.h>
+#include <arch/types.h>
 
 /*
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/generic/include/ipc/ipc.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -51,14 +51,12 @@
 /** This is answer to a call */
 #define IPC_CALL_ANSWERED	(1 << 0)
-/** This call will not be freed on error */
-#define IPC_CALL_STATIC_ALLOC	(1 << 1)
 /** Answer will not be passed to userspace, will be discarded */
-#define IPC_CALL_DISCARD_ANSWER	(1 << 2)
+#define IPC_CALL_DISCARD_ANSWER (1 << 1)
 /** Call was forwarded */
-#define IPC_CALL_FORWARDED	(1 << 3)
+#define IPC_CALL_FORWARDED	(1 << 2)
 /** Identify connect_me_to answer */
-#define IPC_CALL_CONN_ME_TO	(1 << 4)
+#define IPC_CALL_CONN_ME_TO	(1 << 3)
 /** Interrupt notification */
-#define IPC_CALL_NOTIF		(1 << 5)
+#define IPC_CALL_NOTIF		(1 << 4)
 
 /*
@@ -267,4 +265,7 @@
 	waitq_t wq;
 
+	/** Linkage for the list of task's synchronous answerboxes. */
+	link_t sync_box_link;
+
 	/** Phones connected to this answerbox. */
 	link_t connected_phones;
@@ -316,25 +317,31 @@
 } call_t;
 
+
+extern answerbox_t *ipc_phone_0;
+
+
 extern void ipc_init(void);
-extern call_t * ipc_wait_for_call(answerbox_t *, uint32_t, int);
-extern void ipc_answer(answerbox_t *, call_t *);
+
+extern call_t * ipc_call_alloc(int);
+extern void ipc_call_free(call_t *);
+
 extern int ipc_call(phone_t *, call_t *);
 extern int ipc_call_sync(phone_t *, call_t *);
+extern call_t * ipc_wait_for_call(answerbox_t *, uint32_t, int);
+extern int ipc_forward(call_t *, phone_t *, answerbox_t *, int);
+extern void ipc_answer(answerbox_t *, call_t *);
+
 extern void ipc_phone_init(phone_t *);
 extern void ipc_phone_connect(phone_t *, answerbox_t *);
-extern void ipc_call_free(call_t *);
-extern call_t * ipc_call_alloc(int);
+extern int ipc_phone_hangup(phone_t *);
+
 extern void ipc_answerbox_init(answerbox_t *, struct task *);
-extern void ipc_call_static_init(call_t *);
-extern void task_print_list(void);
-extern int ipc_forward(call_t *, phone_t *, answerbox_t *, int);
+
 extern void ipc_cleanup(void);
-extern int ipc_phone_hangup(phone_t *);
 extern void ipc_backsend_err(phone_t *, call_t *, unative_t);
-extern void ipc_print_task(task_id_t);
 extern void ipc_answerbox_slam_phones(answerbox_t *, bool);
 extern void ipc_cleanup_call_list(link_t *);
 
-extern answerbox_t *ipc_phone_0;
+extern void ipc_print_task(task_id_t);
 
 #endif
Index: kernel/generic/include/proc/task.h
===================================================================
--- kernel/generic/include/proc/task.h	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/generic/include/proc/task.h	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -98,4 +98,6 @@
 	 */
 	atomic_t active_calls;
+	/** List of synchronous answerboxes. */
+	link_t sync_box_head;
 
 #ifdef CONFIG_UDEBUG
@@ -132,4 +134,5 @@
 extern int task_kill(task_id_t id);
 extern uint64_t task_get_accounting(task_t *t);
+extern void task_print_list(void);
 
 extern void cap_set(task_t *t, cap_t caps);
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/generic/src/ipc/ipc.c	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -62,4 +62,5 @@
 
 static slab_cache_t *ipc_call_slab;
+static slab_cache_t *ipc_answerbox_slab;
 
 /** Initialize a call structure.
@@ -96,15 +97,4 @@
 }
 
-/** Initialize a statically allocated call structure.
- *
- * @param call		Statically allocated kernel call structure to be
- *			initialized.
- */
-void ipc_call_static_init(call_t *call)
-{
-	_ipc_call_init(call);
-	call->flags |= IPC_CALL_STATIC_ALLOC;
-}
-
 /** Deallocate a call structure.
  *
@@ -113,5 +103,4 @@
 void ipc_call_free(call_t *call)
 {
-	ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
 	/* Check to see if we have data in the IPC_M_DATA_SEND buffer. */
 	if (call->buffer)
@@ -130,4 +119,5 @@
 	spinlock_initialize(&box->irq_lock, "ipc_box_irqlock");
 	waitq_initialize(&box->wq);
+	link_initialize(&box->sync_box_link);
 	list_initialize(&box->connected_phones);
 	list_initialize(&box->calls);
@@ -179,15 +169,41 @@
 int ipc_call_sync(phone_t *phone, call_t *request)
 {
-	answerbox_t sync_box; 
-
-	ipc_answerbox_init(&sync_box, TASK);
+	answerbox_t *sync_box; 
+	ipl_t ipl;
+
+	sync_box = slab_alloc(ipc_answerbox_slab, 0);
+	ipc_answerbox_init(sync_box, TASK);
+
+	/*
+	 * Put the answerbox on the TASK's list of synchronous answerboxes so
+	 * that it can be cleaned up if the call is interrupted.
+	 */
+	ipl = interrupts_disable();
+	spinlock_lock(&TASK->lock);
+	list_append(&sync_box->sync_box_link, &TASK->sync_box_head);
+	spinlock_unlock(&TASK->lock);
+	interrupts_restore(ipl);
 
 	/* We will receive data in a special box. */
-	request->callerbox = &sync_box;
+	request->callerbox = sync_box;
 
 	ipc_call(phone, request);
-	if (!ipc_wait_for_call(&sync_box, SYNCH_NO_TIMEOUT,
-	    SYNCH_FLAGS_INTERRUPTIBLE))
+	if (!ipc_wait_for_call(sync_box, SYNCH_NO_TIMEOUT,
+	    SYNCH_FLAGS_INTERRUPTIBLE)) {
+	    	/* The answerbox and the call will be freed by ipc_cleanup(). */
 		return EINTR;
+	}
+
+	/*
+	 * The answer arrived without interruption so we can remove the
+	 * answerbox from the TASK's list of synchronous answerboxes.
+	 */
+	(void) interrupts_disable();
+	spinlock_lock(&TASK->lock);
+	list_remove(&sync_box->sync_box_link);
+	spinlock_unlock(&TASK->lock);
+	interrupts_restore(ipl);
+
+	slab_free(ipc_answerbox_slab, sync_box);
 	return EOK;
 }
@@ -520,4 +536,5 @@
 	int i;
 	call_t *call;
+	ipl_t ipl;
 
 	/* Disconnect all our phones ('ipc_phone_hangup') */
@@ -545,5 +562,19 @@
 	spinlock_unlock(&TASK->answerbox.lock);
 	
-	/* Wait for all async answers to arrive */
+	/* Wait for all answers to interrupted synchronous calls to arrive */
+	ipl = interrupts_disable();
+	while (!list_empty(&TASK->sync_box_head)) {
+		answerbox_t *box = list_get_instance(TASK->sync_box_head.next,
+		    answerbox_t, sync_box_link);
+
+		list_remove(&box->sync_box_link);
+		call = ipc_wait_for_call(box, SYNCH_NO_TIMEOUT,
+		    SYNCH_FLAGS_NONE);
+		ipc_call_free(call);
+		slab_free(ipc_answerbox_slab, box);
+	}
+	interrupts_restore(ipl);
+
+	/* Wait for all answers to asynchronous calls to arrive */
 	while (1) {
 		/* Go through all phones, until all are FREE... */
@@ -552,6 +583,8 @@
 		for (i = 0; i < IPC_MAX_PHONES; i++) {
 			if (TASK->phones[i].state == IPC_PHONE_HUNGUP &&
-			    atomic_get(&TASK->phones[i].active_calls) == 0)
+			    atomic_get(&TASK->phones[i].active_calls) == 0) {
 				TASK->phones[i].state = IPC_PHONE_FREE;
+				TASK->phones[i].callee = NULL;
+			}
 			
 			/* Just for sure, we might have had some 
@@ -574,5 +607,4 @@
 		ASSERT((call->flags & IPC_CALL_ANSWERED) ||
 		    (call->flags & IPC_CALL_NOTIF));
-		ASSERT(!(call->flags & IPC_CALL_STATIC_ALLOC));
 		
 		/*
@@ -593,4 +625,6 @@
 	ipc_call_slab = slab_cache_create("ipc_call", sizeof(call_t), 0, NULL,
 	    NULL, 0);
+	ipc_answerbox_slab = slab_cache_create("ipc_answerbox",
+	    sizeof(answerbox_t), 0, NULL, NULL, 0);
 }
 
Index: kernel/generic/src/ipc/irq.c
===================================================================
--- kernel/generic/src/ipc/irq.c	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/generic/src/ipc/irq.c	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -418,5 +418,4 @@
 		case CMD_ACCEPT:
 			return IRQ_ACCEPT;
-			break;
 		case CMD_DECLINE:
 		default:
Index: kernel/generic/src/ipc/sysipc.c
===================================================================
--- kernel/generic/src/ipc/sysipc.c	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/generic/src/ipc/sysipc.c	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -61,5 +61,5 @@
 { \
 	if (phoneid > IPC_MAX_PHONES) { \
-		err; \
+		err \
 	} \
 	phone = &TASK->phones[phoneid]; \
@@ -122,5 +122,4 @@
 	case IPC_M_DATA_READ:
 		return 1;
-		break;
 	default:
 		return 0;
@@ -376,5 +375,5 @@
 		phone_t *cloned_phone;
 		GET_CHECK_PHONE(cloned_phone, IPC_GET_ARG1(call->data),
-		    return ENOENT);
+		    return ENOENT;);
 		phones_lock(cloned_phone, phone);
 		if ((cloned_phone->state != IPC_PHONE_CONNECTED) ||
@@ -531,39 +530,42 @@
     unative_t arg1, unative_t arg2, unative_t arg3, ipc_data_t *data)
 {
-	call_t call;
+	call_t *call;
 	phone_t *phone;
 	int res;
 	int rc;
 	
-	GET_CHECK_PHONE(phone, phoneid, return ENOENT);
-
-	ipc_call_static_init(&call);
-	IPC_SET_METHOD(call.data, method);
-	IPC_SET_ARG1(call.data, arg1);
-	IPC_SET_ARG2(call.data, arg2);
-	IPC_SET_ARG3(call.data, arg3);
+	GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
+
+	call = ipc_call_alloc(0);
+	IPC_SET_METHOD(call->data, method);
+	IPC_SET_ARG1(call->data, arg1);
+	IPC_SET_ARG2(call->data, arg2);
+	IPC_SET_ARG3(call->data, arg3);
 	/*
 	 * To achieve deterministic behavior, zero out arguments that are beyond
 	 * the limits of the fast version.
 	 */
-	IPC_SET_ARG4(call.data, 0);
-	IPC_SET_ARG5(call.data, 0);
-
-	if (!(res = request_preprocess(&call, phone))) {
+	IPC_SET_ARG4(call->data, 0);
+	IPC_SET_ARG5(call->data, 0);
+
+	if (!(res = request_preprocess(call, phone))) {
 #ifdef CONFIG_UDEBUG
 		udebug_stoppable_begin();
 #endif
-		rc = ipc_call_sync(phone, &call);
+		rc = ipc_call_sync(phone, call);
 #ifdef CONFIG_UDEBUG
 		udebug_stoppable_end();
 #endif
-		if (rc != EOK)
+		if (rc != EOK) {
+			/* The call will be freed by ipc_cleanup(). */
 			return rc;
-		process_answer(&call);
+		}
+		process_answer(call);
 
 	} else {
-		IPC_SET_RETVAL(call.data, res);
-	}
-	rc = STRUCT_TO_USPACE(&data->args, &call.data.args);
+		IPC_SET_RETVAL(call->data, res);
+	}
+	rc = STRUCT_TO_USPACE(&data->args, &call->data.args);
+	ipc_call_free(call);
 	if (rc != 0)
 		return rc;
@@ -584,32 +586,38 @@
     ipc_data_t *reply)
 {
-	call_t call;
+	call_t *call;
 	phone_t *phone;
 	int res;
 	int rc;
 
-	ipc_call_static_init(&call);
-	rc = copy_from_uspace(&call.data.args, &question->args,
-	    sizeof(call.data.args));
-	if (rc != 0)
+	GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
+
+	call = ipc_call_alloc(0);
+	rc = copy_from_uspace(&call->data.args, &question->args,
+	    sizeof(call->data.args));
+	if (rc != 0) {
+		ipc_call_free(call);
 		return (unative_t) rc;
-
-	GET_CHECK_PHONE(phone, phoneid, return ENOENT);
-
-	if (!(res = request_preprocess(&call, phone))) {
+	}
+
+
+	if (!(res = request_preprocess(call, phone))) {
 #ifdef CONFIG_UDEBUG
 		udebug_stoppable_begin();
 #endif
-		rc = ipc_call_sync(phone, &call);
+		rc = ipc_call_sync(phone, call);
 #ifdef CONFIG_UDEBUG
 		udebug_stoppable_end();
 #endif
-		if (rc != EOK)
+		if (rc != EOK) {
+			/* The call will be freed by ipc_cleanup(). */
 			return rc;
-		process_answer(&call);
+		}
+		process_answer(call);
 	} else 
-		IPC_SET_RETVAL(call.data, res);
-
-	rc = STRUCT_TO_USPACE(&reply->args, &call.data.args);
+		IPC_SET_RETVAL(call->data, res);
+
+	rc = STRUCT_TO_USPACE(&reply->args, &call->data.args);
+	ipc_call_free(call);
 	if (rc != 0)
 		return rc;
@@ -658,5 +666,5 @@
 		return IPC_CALLRET_TEMPORARY;
 
-	GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
+	GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;);
 
 	call = ipc_call_alloc(0);
@@ -697,5 +705,5 @@
 		return IPC_CALLRET_TEMPORARY;
 
-	GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL);
+	GET_CHECK_PHONE(phone, phoneid, return IPC_CALLRET_FATAL;);
 
 	call = ipc_call_alloc(0);
@@ -747,5 +755,5 @@
 	call->flags |= IPC_CALL_FORWARDED;
 
-	GET_CHECK_PHONE(phone, phoneid, { 
+	GET_CHECK_PHONE(phone, phoneid, {
 		IPC_SET_RETVAL(call->data, EFORWARD);
 		ipc_answer(&TASK->answerbox, call);
@@ -952,5 +960,5 @@
 	phone_t *phone;
 
-	GET_CHECK_PHONE(phone, phoneid, return ENOENT);
+	GET_CHECK_PHONE(phone, phoneid, return ENOENT;);
 
 	if (ipc_phone_hangup(phone))
@@ -991,6 +999,4 @@
 
 	if (call->flags & IPC_CALL_NOTIF) {
-		ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
-
 		/* Set in_phone_hash to the interrupt counter */
 		call->data.phone = (void *) call->priv;
@@ -1005,6 +1011,4 @@
 	if (call->flags & IPC_CALL_ANSWERED) {
 		process_answer(call);
-
-		ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
 
 		if (call->flags & IPC_CALL_DISCARD_ANSWER) {
Index: kernel/generic/src/lib/elf.c
===================================================================
--- kernel/generic/src/lib/elf.c	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/generic/src/lib/elf.c	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -163,5 +163,4 @@
 	case PT_LOAD:
 		return load_segment(entry, elf, as);
-		break;
 	case PT_DYNAMIC:
 	case PT_INTERP:
@@ -182,5 +181,4 @@
 	default:
 		return EE_UNSUPPORTED;
-		break;
 	}
 	return EE_OK;
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ kernel/generic/src/proc/task.c	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -75,6 +75,9 @@
 static task_id_t task_counter = 0;
 
+static slab_cache_t *task_slab;
+
 /* Forward declarations. */
 static void task_kill_internal(task_t *);
+static int tsk_constructor(void *, int);
 
 /** Initialize kernel tasks support. */
@@ -83,4 +86,6 @@
 	TASK = NULL;
 	avltree_create(&tasks_tree);
+	task_slab = slab_cache_create("task_slab", sizeof(task_t), 0,
+	    tsk_constructor, NULL, 0);
 }
 
@@ -128,4 +133,33 @@
 }
 
+int tsk_constructor(void *obj, int kmflags)
+{
+	task_t *ta = obj;
+	int i;
+
+	atomic_set(&ta->refcount, 0);
+	atomic_set(&ta->lifecount, 0);
+	atomic_set(&ta->active_calls, 0);
+
+	spinlock_initialize(&ta->lock, "task_ta_lock");
+	mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE);
+
+	list_initialize(&ta->th_head);
+	list_initialize(&ta->sync_box_head);
+
+	ipc_answerbox_init(&ta->answerbox, ta);
+	for (i = 0; i < IPC_MAX_PHONES; i++)
+		ipc_phone_init(&ta->phones[i]);
+
+#ifdef CONFIG_UDEBUG
+	/* Init kbox stuff */
+	ta->kb.thread = NULL;
+	ipc_answerbox_init(&ta->kb.box, ta);
+	mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE);
+#endif
+
+	return 0;
+}
+
 /** Create new task with no threads.
  *
@@ -140,21 +174,12 @@
 	ipl_t ipl;
 	task_t *ta;
-	int i;
-	
-	ta = (task_t *) malloc(sizeof(task_t), 0);
-
+	
+	ta = (task_t *) slab_alloc(task_slab, 0);
 	task_create_arch(ta);
-
-	spinlock_initialize(&ta->lock, "task_ta_lock");
-	list_initialize(&ta->th_head);
 	ta->as = as;
-
 	memcpy(ta->name, name, TASK_NAME_BUFLEN);
 	ta->name[TASK_NAME_BUFLEN - 1] = 0;
 
-	atomic_set(&ta->refcount, 0);
-	atomic_set(&ta->lifecount, 0);
 	ta->context = CONTEXT;
-
 	ta->capabilities = 0;
 	ta->cycles = 0;
@@ -165,28 +190,15 @@
 
 	/* Init kbox stuff */
-	ipc_answerbox_init(&ta->kb.box, ta);
-	ta->kb.thread = NULL;
-	mutex_initialize(&ta->kb.cleanup_lock, MUTEX_PASSIVE);
 	ta->kb.finished = false;
 #endif
 
-	ipc_answerbox_init(&ta->answerbox, ta);
-	for (i = 0; i < IPC_MAX_PHONES; i++)
-		ipc_phone_init(&ta->phones[i]);
-	if ((ipc_phone_0) && (context_check(ipc_phone_0->task->context,
-	    ta->context)))
+	if ((ipc_phone_0) &&
+	    (context_check(ipc_phone_0->task->context, ta->context)))
 		ipc_phone_connect(&ta->phones[0], ipc_phone_0);
-	atomic_set(&ta->active_calls, 0);
-
-	mutex_initialize(&ta->futexes_lock, MUTEX_PASSIVE);
+
 	btree_create(&ta->futexes);
 	
 	ipl = interrupts_disable();
-
-	/*
-	 * Increment address space reference count.
-	 */
 	atomic_inc(&as->refcount);
-
 	spinlock_lock(&tasks_lock);
 	ta->taskid = ++task_counter;
@@ -229,5 +241,5 @@
 		as_destroy(t->as);
 	
-	free(t);
+	slab_free(task_slab, t);
 	TASK = NULL;
 }
Index: tools/config.py
===================================================================
--- tools/config.py	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ tools/config.py	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -227,5 +227,8 @@
 	
 	timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
+	
+	sys.stderr.write("Fetching current revision identifier ... ")
 	version = subprocess.Popen(['bzr', 'version-info', '--custom', '--template={clean}:{revno}:{revision_id}'], stdout = subprocess.PIPE).communicate()[0].split(':')
+	sys.stderr.write("OK\n")
 	
 	if (len(version) == 3):
Index: tools/jobfile.py
===================================================================
--- tools/jobfile.py	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
+++ tools/jobfile.py	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2009 Martin Decky
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - 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.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+"""
+Add a source/object file pair to a Stanse jobfile
+"""
+
+import sys
+import os
+import fcntl
+
+def usage(prname):
+	"Print usage syntax"
+	print prname + " <JOBFILE> <SOURCE> <OBJECT> [OPTIONS ...]"
+
+def main():
+	if (len(sys.argv) < 4):
+		usage(sys.argv[0])
+		return
+	
+	jobfname = sys.argv[1]
+	srcfname = sys.argv[2]
+	objfname = sys.argv[3]
+	cwd = os.getcwd()
+	options = " ".join(sys.argv[4:])
+	
+	jobfile = file(jobfname, "a")
+	fcntl.lockf(jobfile, fcntl.LOCK_EX)
+	jobfile.write("{%s},{%s},{%s},{%s}\n" % (srcfname, objfname, cwd, options))
+	fcntl.lockf(jobfile, fcntl.LOCK_UN)
+	jobfile.close()
+
+if __name__ == '__main__':
+	main()
Index: uspace/lib/libc/generic/async.c
===================================================================
--- uspace/lib/libc/generic/async.c	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ uspace/lib/libc/generic/async.c	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -392,4 +392,18 @@
 	/* If nothing in queue, wait until something arrives */
 	while (list_empty(&conn->msg_queue)) {
+		if (conn->close_callid) {
+			/*
+			 * Handle the case when the connection was already
+			 * closed by the client but the server did not notice
+			 * the first IPC_M_PHONE_HUNGUP call and continues to
+			 * call async_get_call_timeout(). Repeat
+			 * IPC_M_PHONE_HUNGUP until the caller notices. 
+			 */
+			memset(call, 0, sizeof(ipc_call_t));
+			IPC_SET_METHOD(*call, IPC_M_PHONE_HUNGUP);
+			futex_up(&async_futex);
+			return conn->close_callid;
+		}
+
 		if (usecs)
 			async_insert_timeout(&conn->wdata);
@@ -528,5 +542,5 @@
 	list_initialize(&conn->msg_queue);
 	conn->callid = callid;
-	conn->close_callid = false;
+	conn->close_callid = 0;
 	
 	if (call)
Index: uspace/lib/libc/generic/vfs/canonify.c
===================================================================
--- uspace/lib/libc/generic/vfs/canonify.c	(revision 3da11f37e6b8b0d64576fbe67ae8bf361a41793d)
+++ uspace/lib/libc/generic/vfs/canonify.c	(revision 3f35634cf8784398faec3ed02b32b4a4ffe2033a)
@@ -142,5 +142,5 @@
 	t->start[-1] = '\0';
 }
-/** Eat the extra '/'..
+/** Eat the extra '/'.
  *
  * @param t		The current TK_SLASH token.
@@ -288,9 +288,15 @@
  *
  * A file system path is canonical, if the following holds:
- * 1) the path is absolute (i.e. a/b/c is not canonical)
- * 2) there is no trailing slash in the path (i.e. /a/b/c is not canonical)
- * 3) there is no extra slash in the path (i.e. /a//b/c is not canonical)
- * 4) there is no '.' component in the path (i.e. /a/./b/c is not canonical)
- * 5) there is no '..' component in the path (i.e. /a/b/../c is not canonical) 
+ *
+ * 1) the path is absolute
+ *    (i.e. a/b/c is not canonical)
+ * 2) there is no trailing slash in the path if it has components
+ *    (i.e. /a/b/c/ is not canonical)
+ * 3) there is no extra slash in the path
+ *    (i.e. /a//b/c is not canonical)
+ * 4) there is no '.' component in the path
+ *    (i.e. /a/./b/c is not canonical)
+ * 5) there is no '..' component in the path
+ *    (i.e. /a/b/../c is not canonical)
  *
  * This function makes a potentially non-canonical file system path canonical.
