Index: Makefile
===================================================================
--- Makefile (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ Makefile (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 --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 fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
+++ contrib/bazaar/mbprotect/__init__.py (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -0,0 +1,72 @@
+#
+# Copyright (c) 2009 Jiri Svoboda
+# 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.
+#
+
+"""Main Branch Protection plugin for Bazaar."""
+
+#
+# This plugin employs the pre_change_branch_tip hook to protect the main
+# branch (a.k.a. linear history) of bzr repositories from unwanted change,
+# effectively making the main branch append-only.
+#
+# Specifically we verify that the new main branch contains the old tip.
+# This prevents a branch from inadvertently aquiring the tip of another branch.
+#
+# Install this plugin in ~/.bazaar/plugins/mbprotect
+#
+# See also http://trac.helenos.org/trac.fcgi/wiki/BazaarWorkflow
+#
+
+import bzrlib.branch
+from bzrlib.errors import TipChangeRejected
+
+def pre_change_branch_tip(params):
+ repo = params.branch.repository
+
+ # Check if the old repository was empty.
+ if params.old_revid == 'null:':
+ return
+
+ # 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
+
+ # 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')
+
+# Install hook.
+bzrlib.branch.Branch.hooks.install_named_hook('pre_change_branch_tip',
+ pre_change_branch_tip, 'MB-Protect tip check')
Index: contrib/stanse/ThreadChecker.xml
===================================================================
--- contrib/stanse/ThreadChecker.xml (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
+++ contrib/stanse/ThreadChecker.xml (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+ _mutex_lock_timeout
+
+
+
+
+
+
+
+ mutex_unlock
+
+
+
+
+
+
Index: contrib/toolchain.sh
===================================================================
--- contrib/toolchain.sh (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ contrib/toolchain.sh (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -92,10 +92,33 @@
}
+patch_binutils() {
+ PLATFORM="$1"
+
+ if [ "${PLATFORM}" == "arm32" ] ; then
+ patch -p1 <tc_frag_data.first_map == NULL);
+ frag->tc_frag_data.first_map = symbolP;
+ }
+- if (frag->tc_frag_data.last_map != NULL)
++ if (frag->tc_frag_data.last_map != NULL) {
+ know (S_GET_VALUE (frag->tc_frag_data.last_map) < S_GET_VALUE (symbolP));
++ }
+ frag->tc_frag_data.last_map = symbolP;
+ }
+EOF
+ check_error $? "Error patching binutils"
+ fi
+}
+
build_target() {
PLATFORM="$1"
TARGET="$2"
- BINUTILS_VERSION="2.19.1"
- GCC_VERSION="4.4.1"
+ BINUTILS_VERSION="2.20"
+ GCC_VERSION="4.4.2"
BINUTILS="binutils-${BINUTILS_VERSION}.tar.bz2"
@@ -119,8 +142,8 @@
echo ">>> Downloading tarballs"
- download_check "${BINUTILS_SOURCE}" "${BINUTILS}" "09a8c5821a2dfdbb20665bc0bd680791"
- download_check "${GCC_SOURCE}" "${GCC_CORE}" "d19693308aa6b2052e14c071111df59f"
- download_check "${GCC_SOURCE}" "${GCC_OBJC}" "f7b2a606394036e81433b2f4c3251cba"
- download_check "${GCC_SOURCE}" "${GCC_CPP}" "d449047b5761348ceec23739f5553e0b"
+ download_check "${BINUTILS_SOURCE}" "${BINUTILS}" "ee2d3e996e9a2d669808713360fa96f8"
+ download_check "${GCC_SOURCE}" "${GCC_CORE}" "d50ec5af20508974411d0c83c5f4e396"
+ download_check "${GCC_SOURCE}" "${GCC_OBJC}" "d8d26187d386a0591222a580b5a5b3d3"
+ download_check "${GCC_SOURCE}" "${GCC_CPP}" "43b1e4879eb282dc4b05e4c016d356d7"
echo ">>> Removing previous content"
@@ -142,4 +165,5 @@
cd "${BINUTILSDIR}"
check_error $? "Change directory failed."
+ patch_binutils "${PLATFORM}"
./configure "--target=${TARGET}" "--prefix=${PREFIX}" "--program-prefix=${TARGET}-" "--disable-nls"
check_error $? "Error configuring binutils."
Index: kernel/Makefile
===================================================================
--- kernel/Makefile (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/Makefile (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/Makefile.build (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/Makefile.common (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/amd64/include/mm/page.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -177,5 +177,23 @@
#define PFERR_CODE_ID (1 << 4)
-static inline int get_pt_flags(pte_t *pt, size_t i)
+/** 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)
{
pte_t *p = &pt[i];
Index: kernel/arch/amd64/include/types.h
===================================================================
--- kernel/arch/amd64/include/types.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/amd64/include/types.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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/amd64/src/amd64.c
===================================================================
--- kernel/arch/amd64/src/amd64.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/amd64/src/amd64.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -67,4 +67,5 @@
#include
#include
+#include
/** Disable I/O on non-privileged levels
Index: kernel/arch/arm32/include/atomic.h
===================================================================
--- kernel/arch/arm32/include/atomic.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/arm32/include/atomic.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -37,4 +37,6 @@
#define KERN_arm32_ATOMIC_H_
+#include
+
/** Atomic addition.
*
@@ -47,19 +49,14 @@
static inline long atomic_add(atomic_t *val, int i)
{
- int ret;
- volatile long *mem = &(val->count);
-
- asm volatile (
- "1:\n"
- "ldr r2, [%[mem]]\n"
- "add r3, r2, %[i]\n"
- "str r3, %[ret]\n"
- "swp r3, r3, [%[mem]]\n"
- "cmp r3, r2\n"
- "bne 1b\n"
- : [ret] "=m" (ret)
- : [mem] "r" (mem), [i] "r" (i)
- : "r3", "r2"
- );
+ long ret;
+
+ /*
+ * This implementation is for UP pre-ARMv6 systems where we do not have
+ * the LDREX and STREX instructions.
+ */
+ ipl_t ipl = interrupts_disable();
+ val->count += i;
+ ret = val->count;
+ interrupts_restore(ipl);
return ret;
Index: kernel/arch/arm32/include/mm/page.h
===================================================================
--- kernel/arch/arm32/include/mm/page.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/arm32/include/mm/page.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/arm32/include/types.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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/arm32/src/mm/as.c
===================================================================
--- kernel/arch/arm32/src/mm/as.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/arm32/src/mm/as.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -36,4 +36,5 @@
#include
#include
+#include
#include
#include
Index: kernel/arch/ia32/include/mm/page.h
===================================================================
--- kernel/arch/ia32/include/mm/page.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/ia32/include/mm/page.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -146,5 +146,21 @@
#define PFERR_CODE_RSVD (1 << 3)
-static inline int get_pt_flags(pte_t *pt, size_t i)
+/** 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)
{
pte_t *p = &pt[i];
Index: kernel/arch/ia32/include/types.h
===================================================================
--- kernel/arch/ia32/include/types.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/ia32/include/types.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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/ia32/src/ia32.c
===================================================================
--- kernel/arch/ia32/src/ia32.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/ia32/src/ia32.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -68,4 +68,5 @@
#include
#include
+#include
#ifdef CONFIG_SMP
Index: kernel/arch/ia64/src/cpu/cpu.c
===================================================================
--- kernel/arch/ia64/src/cpu/cpu.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/ia64/src/cpu/cpu.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -37,4 +37,5 @@
#include
#include
+#include
void cpu_arch_init(void)
Index: kernel/arch/mips32/include/mm/page.h
===================================================================
--- kernel/arch/mips32/include/mm/page.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/mips32/include/mm/page.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -141,5 +141,19 @@
#include
-static inline int get_pt_flags(pte_t *pt, size_t i)
+/** 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)
{
pte_t *p = &pt[i];
Index: kernel/arch/mips32/include/types.h
===================================================================
--- kernel/arch/mips32/include/types.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/mips32/include/types.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/ppc32/include/mm/page.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -131,5 +131,16 @@
#include
-static inline int get_pt_flags(pte_t *pt, size_t i)
+/** 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)
{
pte_t *p = &pt[i];
Index: kernel/arch/ppc32/include/types.h
===================================================================
--- kernel/arch/ppc32/include/types.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/ppc32/include/types.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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/arch/ppc32/src/mm/as.c
===================================================================
--- kernel/arch/ppc32/src/mm/as.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/ppc32/src/mm/as.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -35,4 +35,5 @@
#include
#include
+#include
#include
#include
Index: kernel/arch/ppc32/src/mm/tlb.c
===================================================================
--- kernel/arch/ppc32/src/mm/tlb.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/ppc32/src/mm/tlb.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -38,4 +38,5 @@
#include
#include
+#include
#include
#include
Index: kernel/arch/ppc32/src/ppc32.c
===================================================================
--- kernel/arch/ppc32/src/ppc32.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/ppc32/src/ppc32.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -44,4 +44,5 @@
#include
#include
+#include
#include
#include
Index: kernel/arch/sparc64/src/mm/tlb.c
===================================================================
--- kernel/arch/sparc64/src/mm/tlb.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/arch/sparc64/src/mm/tlb.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -37,4 +37,5 @@
#include
#include
+#include
#include
#include
Index: kernel/genarch/include/mm/as_pt.h
===================================================================
--- kernel/genarch/include/mm/as_pt.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/genarch/include/mm/as_pt.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -36,6 +36,5 @@
#define KERN_AS_PT_H_
-#include
-#include
+#include
#define AS_PAGE_TABLE
Index: kernel/genarch/include/mm/page_pt.h
===================================================================
--- kernel/genarch/include/mm/page_pt.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/genarch/include/mm/page_pt.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -44,7 +44,8 @@
#define KERN_PAGE_PT_H_
-#include
#include
#include
+#include
+#include
/*
Index: kernel/genarch/src/drivers/via-cuda/cuda.c
===================================================================
--- kernel/genarch/src/drivers/via-cuda/cuda.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/genarch/src/drivers/via-cuda/cuda.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -41,4 +41,5 @@
#include
#include
+#include
static irq_ownership_t cuda_claim(irq_t *irq);
Index: kernel/genarch/src/fb/fb.c
===================================================================
--- kernel/genarch/src/fb/fb.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/genarch/src/fb/fb.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -41,4 +41,5 @@
#include
#include
+#include
#include
#include
Index: kernel/generic/include/arch.h
===================================================================
--- kernel/generic/include/arch.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/include/arch.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -39,4 +39,5 @@
#include
#include
+#include
#define DEFAULT_CONTEXT 0
Index: kernel/generic/include/context.h
===================================================================
--- kernel/generic/include/context.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/include/context.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -51,17 +51,29 @@
/** Save register context.
*
- * Save current register context (including stack pointers)
- * to context structure.
- *
- * Note that call to context_restore() will return at the same
+ * Save the current register context (including stack pointer) to a context
+ * structure. A subsequent call to context_restore() will return to the same
* address as the corresponding call to context_save().
*
- * This MUST be a macro, gcc -O0 does not inline functions even
- * if they are marked inline and context_save_arch must be called
- * from level <= that when context_restore is called.
+ * Note that context_save_arch() must reuse the stack frame of the function
+ * which called context_save(). We guarantee this by:
*
- * @param c Context structure.
+ * a) implementing context_save_arch() in assembly so that it does not create
+ * its own stack frame, and by
+ * b) defining context_save() as a macro because the inline keyword is just a
+ * hint for the compiler, not a real constraint; the application of a macro
+ * will definitely not create a stack frame either.
*
- * @return context_save() returns 1, context_restore() returns 0.
+ * To imagine what could happen if there were some extra stack frames created
+ * either by context_save() or context_save_arch(), we need to realize that the
+ * sp saved in the contex_t structure points to the current stack frame as it
+ * existed when context_save_arch() was executing. After the return from
+ * context_save_arch() and context_save(), any extra stack frames created by
+ * these functions will be destroyed and their contents sooner or later
+ * overwritten by functions called next. Any attempt to restore to a context
+ * saved like that would therefore lead to a disaster.
+ *
+ * @param c Context structure.
+ *
+ * @return context_save() returns 1, context_restore() returns 0.
*/
#define context_save(c) context_save_arch(c)
@@ -69,13 +81,12 @@
/** Restore register context.
*
- * Restore previously saved register context (including stack pointers)
- * from context structure.
+ * Restore a previously saved register context (including stack pointer) from
+ * a context structure.
*
- * Note that this function does not normally return.
- * Instead, it returns at the same address as the
- * corresponding call to context_save(), the only
- * difference being return value.
+ * Note that this function does not normally return. Instead, it returns to the
+ * same address as the corresponding call to context_save(), the only difference
+ * being return value.
*
- * @param c Context structure.
+ * @param c Context structure.
*/
static inline void context_restore(context_t *c)
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/include/ipc/ipc.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/include/proc/task.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -55,4 +55,5 @@
#include
#include
+#include
#define TASK_NAME_BUFLEN 20
@@ -98,4 +99,6 @@
*/
atomic_t active_calls;
+ /** List of synchronous answerboxes. */
+ link_t sync_box_head;
#ifdef CONFIG_UDEBUG
@@ -132,4 +135,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/include/proc/thread.h
===================================================================
--- kernel/generic/include/proc/thread.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/include/proc/thread.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -225,34 +225,33 @@
extern void thread_init(void);
-extern thread_t *thread_create(void (* func)(void *), void *arg, task_t *task,
- int flags, char *name, bool uncounted);
-extern void thread_attach(thread_t *t, task_t *task);
-extern void thread_ready(thread_t *t);
+extern thread_t *thread_create(void (*)(void *), void *, task_t *, int, char *,
+ bool);
+extern void thread_attach(thread_t *, task_t *);
+extern void thread_ready(thread_t *);
extern void thread_exit(void) __attribute__((noreturn));
#ifndef thread_create_arch
-extern void thread_create_arch(thread_t *t);
+extern void thread_create_arch(thread_t *);
#endif
#ifndef thr_constructor_arch
-extern void thr_constructor_arch(thread_t *t);
+extern void thr_constructor_arch(thread_t *);
#endif
#ifndef thr_destructor_arch
-extern void thr_destructor_arch(thread_t *t);
-#endif
-
-extern void thread_sleep(uint32_t sec);
-extern void thread_usleep(uint32_t usec);
+extern void thr_destructor_arch(thread_t *);
+#endif
+
+extern void thread_sleep(uint32_t);
+extern void thread_usleep(uint32_t);
#define thread_join(t) \
thread_join_timeout((t), SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE)
-extern int thread_join_timeout(thread_t *t, uint32_t usec, int flags);
-extern void thread_detach(thread_t *t);
-
-extern void thread_register_call_me(void (* call_me)(void *),
- void *call_me_with);
+extern int thread_join_timeout(thread_t *, uint32_t, int);
+extern void thread_detach(thread_t *);
+
+extern void thread_register_call_me(void (*)(void *), void *);
extern void thread_print_list(void);
-extern void thread_destroy(thread_t *t);
+extern void thread_destroy(thread_t *);
extern void thread_update_accounting(void);
-extern bool thread_exists(thread_t *t);
+extern bool thread_exists(thread_t *);
/** Fpu context slab cache. */
@@ -260,8 +259,9 @@
/* Thread syscall prototypes. */
-extern unative_t sys_thread_create(uspace_arg_t *uspace_uarg,
- char *uspace_name, size_t name_len, thread_id_t *uspace_thread_id);
-extern unative_t sys_thread_exit(int uspace_status);
-extern unative_t sys_thread_get_id(thread_id_t *uspace_thread_id);
+extern unative_t sys_thread_create(uspace_arg_t *, char *, size_t,
+ thread_id_t *);
+extern unative_t sys_thread_exit(int);
+extern unative_t sys_thread_get_id(thread_id_t *);
+extern unative_t sys_thread_usleep(uint32_t);
#endif
Index: kernel/generic/include/string.h
===================================================================
--- kernel/generic/include/string.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/include/string.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -87,5 +87,5 @@
extern void str_cpy(char *dest, size_t size, const char *src);
extern void str_ncpy(char *dest, size_t size, const char *src, size_t n);
-extern void wstr_nstr(char *dst, const wchar_t *src, size_t size);
+extern void wstr_to_str(char *dest, size_t size, const wchar_t *src);
extern char *str_chr(const char *str, wchar_t ch);
Index: kernel/generic/include/synch/futex.h
===================================================================
--- kernel/generic/include/synch/futex.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/include/synch/futex.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -38,6 +38,4 @@
#include
#include
-#include
-#include
/** Kernel-side futex structure. */
@@ -54,7 +52,6 @@
extern void futex_init(void);
-extern unative_t sys_futex_sleep_timeout(uintptr_t uaddr, uint32_t usec,
- int flags);
-extern unative_t sys_futex_wakeup(uintptr_t uaddr);
+extern unative_t sys_futex_sleep(uintptr_t);
+extern unative_t sys_futex_wakeup(uintptr_t);
extern void futex_cleanup(void);
Index: kernel/generic/include/syscall/syscall.h
===================================================================
--- kernel/generic/include/syscall/syscall.h (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/include/syscall/syscall.h (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -43,4 +43,5 @@
SYS_THREAD_EXIT,
SYS_THREAD_GET_ID,
+ SYS_THREAD_USLEEP,
SYS_TASK_GET_ID,
Index: kernel/generic/src/console/console.c
===================================================================
--- kernel/generic/src/console/console.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/console/console.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -319,15 +319,15 @@
if (size > PAGE_SIZE)
- return ELIMIT;
+ return (unative_t) ELIMIT;
if (size > 0) {
data = (char *) malloc(size + 1, 0);
if (!data)
- return ENOMEM;
+ return (unative_t) ENOMEM;
rc = copy_from_uspace(data, buf, size);
if (rc) {
free(data);
- return rc;
+ return (unative_t) rc;
}
data[size] = 0;
Index: kernel/generic/src/console/kconsole.c
===================================================================
--- kernel/generic/src/console/kconsole.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/console/kconsole.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -289,5 +289,5 @@
char tmp[STR_BOUNDS(MAX_CMDLINE)];
- wstr_nstr(tmp, current + beg, position - beg + 1);
+ wstr_to_str(tmp, position - beg + 1, current + beg);
int found;
@@ -665,5 +665,5 @@
char cmdline[STR_BOUNDS(MAX_CMDLINE)];
- wstr_nstr(cmdline, tmp, STR_BOUNDS(MAX_CMDLINE));
+ wstr_to_str(cmdline, STR_BOUNDS(MAX_CMDLINE), tmp);
if ((!kcon) && (len == 4) && (str_lcmp(cmdline, "exit", 4) == 0))
Index: kernel/generic/src/ipc/ipc.c
===================================================================
--- kernel/generic/src/ipc/ipc.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/ipc/ipc.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/ipc/irq.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/ipc/sysipc.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/lib/elf.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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/lib/string.c
===================================================================
--- kernel/generic/src/lib/string.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/lib/string.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -537,5 +537,5 @@
* null-terminated and containing only complete characters.
*
- * @param dst Destination buffer.
+ * @param dest Destination buffer.
* @param count Size of the destination buffer (must be > 0).
* @param src Source string.
@@ -571,5 +571,5 @@
* have to be null-terminated.
*
- * @param dst Destination buffer.
+ * @param dest Destination buffer.
* @param count Size of the destination buffer (must be > 0).
* @param src Source string.
@@ -596,36 +596,32 @@
}
-/** Copy NULL-terminated wide string to string
- *
- * Copy source wide string @a src to destination buffer @a dst.
- * No more than @a size bytes are written. NULL-terminator is always
- * written after the last succesfully copied character (i.e. if the
- * destination buffer is has at least 1 byte, it will be always
- * NULL-terminated).
- *
- * @param src Source wide string.
- * @param dst Destination buffer.
- * @param count Size of the destination buffer.
- *
- */
-void wstr_nstr(char *dst, const wchar_t *src, size_t size)
-{
- /* No space for the NULL-terminator in the buffer */
- if (size == 0)
- return;
-
+/** Convert wide string to string.
+ *
+ * Convert wide string @a src to string. The output is written to the buffer
+ * specified by @a dest and @a size. @a size must be non-zero and the string
+ * written will always be well-formed.
+ *
+ * @param dest Destination buffer.
+ * @param size Size of the destination buffer.
+ * @param src Source wide string.
+ */
+void wstr_to_str(char *dest, size_t size, const wchar_t *src)
+{
wchar_t ch;
- size_t src_idx = 0;
- size_t dst_off = 0;
+ size_t src_idx;
+ size_t dest_off;
+
+ /* There must be space for a null terminator in the buffer. */
+ ASSERT(size > 0);
+
+ src_idx = 0;
+ dest_off = 0;
while ((ch = src[src_idx++]) != 0) {
- if (chr_encode(ch, dst, &dst_off, size) != EOK)
+ if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
break;
}
-
- if (dst_off >= size)
- dst[size - 1] = 0;
- else
- dst[dst_off] = 0;
+
+ dest[dest_off] = '\0';
}
Index: kernel/generic/src/mm/backend_phys.c
===================================================================
--- kernel/generic/src/mm/backend_phys.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/mm/backend_phys.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -40,4 +40,5 @@
#include
#include
+#include
#include
#include
Index: kernel/generic/src/proc/task.c
===================================================================
--- kernel/generic/src/proc/task.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/proc/task.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -54,4 +54,5 @@
#include
#include
+#include
#include
#include
@@ -75,6 +76,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 +87,6 @@
TASK = NULL;
avltree_create(&tasks_tree);
+ task_slab = slab_cache_create("task_slab", sizeof(task_t), 0,
+ tsk_constructor, NULL, 0);
}
@@ -128,4 +134,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 +175,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 +191,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 +242,5 @@
as_destroy(t->as);
- free(t);
+ slab_free(task_slab, t);
TASK = NULL;
}
Index: kernel/generic/src/proc/thread.c
===================================================================
--- kernel/generic/src/proc/thread.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/proc/thread.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -501,5 +501,12 @@
void thread_sleep(uint32_t sec)
{
- thread_usleep(sec * 1000000);
+ /* Sleep in 1000 second steps to support
+ full argument range */
+ while (sec > 0) {
+ uint32_t period = (sec > 1000) ? 1000 : sec;
+
+ thread_usleep(period * 1000000);
+ sec -= period;
+ }
}
@@ -575,7 +582,7 @@
{
waitq_t wq;
-
+
waitq_initialize(&wq);
-
+
(void) waitq_sleep_timeout(&wq, usec, SYNCH_FLAGS_NON_BLOCKING);
}
@@ -812,4 +819,11 @@
}
+/** Syscall wrapper for sleeping. */
+unative_t sys_thread_usleep(uint32_t usec)
+{
+ thread_usleep(usec);
+ return 0;
+}
+
/** @}
*/
Index: kernel/generic/src/synch/futex.c
===================================================================
--- kernel/generic/src/synch/futex.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/synch/futex.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -90,5 +90,5 @@
/** Initialize kernel futex structure.
*
- * @param futex Kernel futex structure.
+ * @param futex Kernel futex structure.
*/
void futex_initialize(futex_t *futex)
@@ -102,13 +102,11 @@
/** Sleep in futex wait queue.
*
- * @param uaddr Userspace address of the futex counter.
- * @param usec If non-zero, number of microseconds this thread is willing to
- * sleep.
- * @param flags Select mode of operation.
- *
- * @return One of ESYNCH_TIMEOUT, ESYNCH_OK_ATOMIC and ESYNCH_OK_BLOCKED. See
- * synch.h. If there is no physical mapping for uaddr ENOENT is returned.
- */
-unative_t sys_futex_sleep_timeout(uintptr_t uaddr, uint32_t usec, int flags)
+ * @param uaddr Userspace address of the futex counter.
+ *
+ * @return If there is no physical mapping for uaddr ENOENT is
+ * returned. Otherwise returns a wait result as defined in
+ * synch.h.
+ */
+unative_t sys_futex_sleep(uintptr_t uaddr)
{
futex_t *futex;
@@ -140,7 +138,5 @@
udebug_stoppable_begin();
#endif
- rc = waitq_sleep_timeout(&futex->wq, usec, flags |
- SYNCH_FLAGS_INTERRUPTIBLE);
-
+ rc = waitq_sleep_timeout(&futex->wq, 0, SYNCH_FLAGS_INTERRUPTIBLE);
#ifdef CONFIG_UDEBUG
udebug_stoppable_end();
@@ -151,7 +147,7 @@
/** Wakeup one thread waiting in futex wait queue.
*
- * @param uaddr Userspace address of the futex counter.
- *
- * @return ENOENT if there is no physical mapping for uaddr.
+ * @param uaddr Userspace address of the futex counter.
+ *
+ * @return ENOENT if there is no physical mapping for uaddr.
*/
unative_t sys_futex_wakeup(uintptr_t uaddr)
@@ -190,7 +186,7 @@
* If the structure does not exist already, a new one is created.
*
- * @param paddr Physical address of the userspace futex counter.
- *
- * @return Address of the kernel futex structure.
+ * @param paddr Physical address of the userspace futex counter.
+ *
+ * @return Address of the kernel futex structure.
*/
futex_t *futex_find(uintptr_t paddr)
@@ -284,8 +280,8 @@
/** Compute hash index into futex hash table.
*
- * @param key Address where the key (i.e. physical address of futex counter) is
- * stored.
- *
- * @return Index into futex hash table.
+ * @param key Address where the key (i.e. physical address of futex
+ * counter) is stored.
+ *
+ * @return Index into futex hash table.
*/
size_t futex_ht_hash(unative_t *key)
@@ -296,8 +292,8 @@
/** Compare futex hash table item with a key.
*
- * @param key Address where the key (i.e. physical address of futex counter) is
- * stored.
- *
- * @return True if the item matches the key. False otherwise.
+ * @param key Address where the key (i.e. physical address of futex
+ * counter) is stored.
+ *
+ * @return True if the item matches the key. False otherwise.
*/
bool futex_ht_compare(unative_t *key, size_t keys, link_t *item)
@@ -313,5 +309,5 @@
/** Callback for removal items from futex hash table.
*
- * @param item Item removed from the hash table.
+ * @param item Item removed from the hash table.
*/
void futex_ht_remove_callback(link_t *item)
Index: kernel/generic/src/syscall/syscall.c
===================================================================
--- kernel/generic/src/syscall/syscall.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/syscall/syscall.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -111,4 +111,5 @@
(syshandler_t) sys_thread_exit,
(syshandler_t) sys_thread_get_id,
+ (syshandler_t) sys_thread_usleep,
(syshandler_t) sys_task_get_id,
@@ -117,5 +118,5 @@
/* Synchronization related syscalls. */
- (syshandler_t) sys_futex_sleep_timeout,
+ (syshandler_t) sys_futex_sleep,
(syshandler_t) sys_futex_wakeup,
(syshandler_t) sys_smc_coherence,
Index: kernel/generic/src/udebug/udebug_ops.c
===================================================================
--- kernel/generic/src/udebug/udebug_ops.c (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ kernel/generic/src/udebug/udebug_ops.c (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -50,4 +50,5 @@
#include
#include
+#include
/**
Index: tools/config.py
===================================================================
--- tools/config.py (revision cb3d641acfaba056443f5a2ae15d649889c2c7a7)
+++ tools/config.py (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
+++ tools/jobfile.py (revision fbcfc4dae9c8bbb7a192b0d0050fd7e51c5faf32)
@@ -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 + "